You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

180 lines
4.5 KiB
TypeScript

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* @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.
*/