import { Widget, _decorator } from "cc"; import { EDITOR } from "cc/env"; import { Adapter } from "./Adapter"; const { ccclass, property, executeInEditMode, menu } = _decorator; enum Flags { None = 0, TOP = 1 << 0, BOTTOM = 1 << 1, LEFT = 1 << 2, RIGHT = 1 << 3, } /** * @classdesc 安全区域适配Widget , App.isFullScreenAdaption = true 时有效 * @description * * 用法: * * 1. 将本组件挂载在节点上即可(注意:该节点上必须挂在 Widget 组件) * * 适配原理: * * 1. 根据安全区域范围,修改widget组件属性 * 自动添加刘海宽度,以避免显示到安全区域之外 */ @ccclass("AdapterSafeArea") @executeInEditMode @menu("Quick适配组件/AdapterSafeArea") export default class AdapterSafeArea extends Adapter { @property protected _flags: number = Flags.None; protected setFlag(flag: Flags, value: boolean) { const current = (this._flags & flag) > 0; if (value == current) { return; } if (value) { this._flags |= flag; } else { this._flags &= ~flag; } this._isDirty = true; } @property({ tooltip: EDITOR ? "是否对齐上边" : "" }) get isAlignTop() { return (this._flags & Flags.TOP) > 0; } set isAlignTop(v) { this.setFlag(Flags.TOP, v); } @property({ tooltip: EDITOR ? "是否对齐下边" : "" }) get isAlignBottom() { return (this._flags & Flags.BOTTOM) > 0; } set isAlignBottom(v) { this.setFlag(Flags.BOTTOM, v); } @property({ tooltip: EDITOR ? "是否对齐左边" : "" }) get isAlignLeft() { return (this._flags & Flags.LEFT) > 0; } set isAlignLeft(v) { this.setFlag(Flags.LEFT, v); } @property({ tooltip: EDITOR ? "是否对齐右边" : "" }) get isAlignRight() { return (this._flags & Flags.RIGHT) > 0; } set isAlignRight(v) { this.setFlag(Flags.RIGHT, v); } @property _top = 0; @property({ visible: function (this: AdapterSafeArea) { return this.isAlignTop; }, tooltip: EDITOR ? "本节点顶边和父节点顶边的距离,可填写负值,只有在 isAlignTop 开启时才有作用" : "" }) get top() { return this._top; } set top(v) { if (this._top == v) { return; } this._top = v; this._isDirty = true; } @property _bottom = 0; @property({ visible: function (this: AdapterSafeArea) { return this.isAlignBottom; }, tooltip: EDITOR ? "本节点顶边和父节点底边的距离,可填写负值,只有在 isAlignBottom 开启时才有作用" : "" }) get bottom() { return this._bottom; } set bottom(v) { if (this._bottom == v) { return; } this._bottom = v; this._isDirty = true; } @property _left = 0; @property({ visible: function (this: AdapterSafeArea) { return this.isAlignLeft; }, tooltip: EDITOR ? "本节点顶边和父节点左边的距离,可填写负值,只有在 isAlignLeft 开启时才有作用" : "" }) get left() { return this._left; } set left(v) { if (this._left == v) { return; } this._left = v; this._isDirty = true; } @property _right = 0; @property({ visible: function (this: AdapterSafeArea) { return this.isAlignRight; }, tooltip: EDITOR ? "本节点顶边和父节点右边的距离,可填写负值,只有在 isAlignRight 开启时才有作用" : "" }) get right() { return this._right; } set right(v) { if (this._right == v) { return; } this._right = v; this._isDirty = true; } protected _isDirty = false; protected get widget() { let comp = this.getComponent(Widget); if (comp) { return comp; } return this.addComponent(Widget); } resetInEditor() { this.doLayout(true); } protected doLayout(isForce = false) { if (this._isDirty || isForce) { let widget = this.widget!; if (EDITOR) { widget.left = this.left; widget.right = this.right; widget.top = this.top; widget.bottom = this.bottom; return; } if (!this.isFullScreenAdaption) { return; } if (!widget || !widget.enabled) { return; } // 屏幕向上时,加上安全区域高度 if (widget.isAlignTop && this.isAlignTop) { widget.isAbsoluteTop = true; if (this.direction == Adapter.direction.Portrait) { widget.top = this.top + Adapter.safeArea.outside.height; } else { widget.top = this.top; } } // 屏幕向下时,加上安全区域高度 if (widget.isAlignBottom && this.isAlignBottom) { widget.isAbsoluteBottom = true; if (this.direction == Adapter.direction.UpsideDown) { widget.bottom = this.bottom + Adapter.safeArea.outside.height; } else { widget.bottom = this.bottom; } } // 屏幕向左时,加上安全区域宽度 if (widget.isAlignLeft && this.isAlignLeft) { widget.isAbsoluteLeft = true; if (this.direction == Adapter.direction.LandscapeLeft) { widget.left = this.left + Adapter.safeArea.outside.width; } else { widget.left = this.left; } } // 屏幕向右时,加上安全区域宽度 if (widget.isAlignRight && this.isAlignRight) { widget.isAbsoluteRight = true; if (this.direction == Adapter.direction.LandscapeRight) { widget.right = this.right + Adapter.safeArea.outside.width; } else { widget.right = this.right; } } widget.updateAlignment(); this._isDirty = false; this.doOnAdapterComplete(); } } protected onChangeSize() { this.doLayout(true); } protected update(dt: number) { super.update && super.update(dt); this.doLayout(); } }