|
|
|
|
|
/**
|
|
|
|
|
|
* @packageDocumentation
|
|
|
|
|
|
* @module ui
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
import { CustomToggleGroup } from "./CustomToggleGroup"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const { property, ccclass, requireComponent, executionOrder, menu } = cc._decorator
|
|
|
|
|
|
|
|
|
|
|
|
export enum ToggleSwitchType {
|
|
|
|
|
|
active,
|
|
|
|
|
|
animation
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @en
|
|
|
|
|
|
* The toggle component is a CheckBox, when it used together with a ToggleGroup,
|
|
|
|
|
|
* it could be treated as a RadioButton.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @zh
|
|
|
|
|
|
* Toggle 是一个 CheckBox,当它和 ToggleGroup 一起使用的时候,可以变成 RadioButton。
|
|
|
|
|
|
*/
|
|
|
|
|
|
@ccclass
|
|
|
|
|
|
@executionOrder(110)
|
|
|
|
|
|
@menu('UI/CustomToggle')
|
|
|
|
|
|
export class CustomToggle extends cc.Component {
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @en
|
|
|
|
|
|
* When this value is true, the check mark component will be enabled,
|
|
|
|
|
|
* otherwise the check mark component will be disabled.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @zh
|
|
|
|
|
|
* 如果这个设置为 true,则 check mark 组件会处于 enabled 状态,否则处于 disabled 状态。
|
|
|
|
|
|
*/
|
|
|
|
|
|
@property
|
|
|
|
|
|
get isChecked() {
|
|
|
|
|
|
return this._isChecked
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
set isChecked(value) {
|
|
|
|
|
|
this._set(value)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
set _resizeToTarget(value: boolean) {
|
|
|
|
|
|
// if (value) {
|
|
|
|
|
|
// this._resizeNodeToTargetNode();
|
|
|
|
|
|
// }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
get _toggleContainer() {
|
|
|
|
|
|
const parent = this.node.parent!
|
|
|
|
|
|
if (parent instanceof cc.Node) {
|
|
|
|
|
|
return parent.getComponent(CustomToggleGroup)
|
|
|
|
|
|
}
|
|
|
|
|
|
return null
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @en
|
|
|
|
|
|
* If Toggle is clicked, it will trigger event's handler.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @zh
|
|
|
|
|
|
* Toggle 按钮的点击事件列表。
|
|
|
|
|
|
*/
|
|
|
|
|
|
@property({ type: [cc.Component.EventHandler], tooltip: 'i18n:toggle.check_events' })
|
|
|
|
|
|
public checkEvents: cc.Component.EventHandler[] = []
|
|
|
|
|
|
@property(cc.Boolean)
|
|
|
|
|
|
protected _isChecked = true
|
|
|
|
|
|
@property([cc.Node])
|
|
|
|
|
|
protected onNodeList: cc.Node[] = []
|
|
|
|
|
|
@property([cc.Node])
|
|
|
|
|
|
protected offNodeList: cc.Node[] = []
|
|
|
|
|
|
@property({ type: cc.Enum(ToggleSwitchType) })
|
|
|
|
|
|
toggleSwitchType: ToggleSwitchType = ToggleSwitchType.active
|
|
|
|
|
|
//是否關閉點擊事件
|
|
|
|
|
|
@property(cc.Boolean)
|
|
|
|
|
|
isDoNotEmitToggle = false
|
|
|
|
|
|
|
|
|
|
|
|
private toggleEventMap: Map<ToggleSwitchType, Function> = new Map([
|
|
|
|
|
|
[ToggleSwitchType.active, this.switchByActive.bind(this)],
|
|
|
|
|
|
[ToggleSwitchType.animation, this.switchByAnimation.bind(this)]
|
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
|
|
protected _internalToggle() {
|
|
|
|
|
|
if (this.isDoNotEmitToggle) {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
this.isChecked = !this.isChecked
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected _set(value: boolean, emitEvent = true) {
|
|
|
|
|
|
if (this._isChecked == value) return
|
|
|
|
|
|
|
|
|
|
|
|
this._isChecked = value
|
|
|
|
|
|
|
|
|
|
|
|
const group = this._toggleContainer
|
|
|
|
|
|
if (group && group.enabled && this.enabled) {
|
|
|
|
|
|
if (value || (!group.anyTogglesChecked() && !group.allowSwitchOff)) {
|
|
|
|
|
|
this._isChecked = true
|
|
|
|
|
|
group.notifyToggleCheck(this as any, emitEvent)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
this.playEffect()
|
|
|
|
|
|
if (emitEvent) {
|
|
|
|
|
|
this._emitToggleEvents()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
public playEffect() {
|
|
|
|
|
|
this.toggleEventMap.get(this.toggleSwitchType)()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
switchByActive() {
|
|
|
|
|
|
this.onNodeList.forEach((node) => {
|
|
|
|
|
|
node.active = this._isChecked
|
|
|
|
|
|
})
|
|
|
|
|
|
this.offNodeList.forEach((node) => {
|
|
|
|
|
|
node.active = !this._isChecked
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
switchByAnimation() { }
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @en
|
|
|
|
|
|
* Set isChecked without invoking checkEvents.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @zh
|
|
|
|
|
|
* 设置 isChecked 而不调用 checkEvents 回调。
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param value - 是否被按下
|
|
|
|
|
|
*/
|
|
|
|
|
|
public setIsCheckedWithoutNotify(value: boolean) {
|
|
|
|
|
|
this._set(value, false)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
onEnable() {
|
|
|
|
|
|
this.playEffect()
|
|
|
|
|
|
if (!CC_EDITOR || CC_PREVIEW) {
|
|
|
|
|
|
this.node.on(cc.Node.EventType.TOUCH_END, this._internalToggle, this)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
onDisable() {
|
|
|
|
|
|
if (!CC_EDITOR || CC_PREVIEW) {
|
|
|
|
|
|
this.node.off(cc.Node.EventType.TOUCH_END, this._internalToggle, this)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public OnDestroy() {
|
|
|
|
|
|
const group = this._toggleContainer
|
|
|
|
|
|
if (group) {
|
|
|
|
|
|
group.ensureValidState()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected _emitToggleEvents() {
|
|
|
|
|
|
this.node.emit("toggle", this)
|
|
|
|
|
|
if (this.checkEvents) {
|
|
|
|
|
|
cc.Component.EventHandler.emitEvents(this.checkEvents, this)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @en
|
|
|
|
|
|
* Note: This event is emitted from the node to which the component belongs.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @zh
|
|
|
|
|
|
* 注意:此事件是从该组件所属的 Node 上面派发出来的,需要用 node.on 来监听。
|
|
|
|
|
|
* @event toggle
|
|
|
|
|
|
* @param {Event.EventCustom} event
|
|
|
|
|
|
* @param {Toggle} toggle - The Toggle component.
|
|
|
|
|
|
*/
|