这个下拉选择器用在游戏界面的投入勋章按钮上,如下图:

静态页面
首先创建一个布局节点Widget(UI组件)命名为 buy-btn-group
,调整其水平对齐方式为水平居中,然后垂直对齐方式为底部对齐:

这样,这个节点就会出现在页面的下方居中位置。
然后再给这个节点添加精灵图组件(注意,是名称为 buy-btn-group
的节点上同时存在布局组件和精灵图组件两种组件),然后将按钮的图片拖动到精灵图组件的SpriteFrame中,最后调整该节点的大小,如下:

然后在 buy-btn-group
节点下,添加一个Label文本子节点 text
,内容为"投入勋章",然后调调位置、字体样式等等:

在 buy-btn-group
节点下新增一个空节点 buy-number
,这个 buy-number
节点的大小和位置调整至刚好覆盖按钮背景的黑色半边:

然后这个节点下新增3个子节点:
- 精灵图节点:coin,用于放货币的图标;
- 文本节点:num,用于放当前选中的金额,锚点设为
anchor(1,0.5)
; - 精灵图节点:arrow,用于放一个向下的箭头;

接着在 buy-btn-group
节点下新增一个遮罩Mask节点 monkey-word
,然后该节点下新建两个节点:
- 精灵图节点:monkey,放猴子的图片;
- 精灵图节点:dialog-bg,对话框背景图;
- 文本节点:word,猴子说的话;
因为没找到对话框背景图素材,这里就只放置一个猴子图片:

然后将 monkey-word
节点隐藏起来先,在属性检查器中进行隐藏:

然后在 buy-btn-group
节点下新增单色精灵图节点 selector
,然后在该节点下新增一个空节点 option-500
,然后 option-500
节点下新增一个精灵图组件 coin
和一个文本节点 num
以及一个 单色精灵图节点 selected
,这3个节点的层级关系如下:
- selected节点,表示选中状态的遮罩,透明度20%左右;
- coin节点,货币图标;
- num节点,货币金额;
完成这个 option-500
节点之后,复制两份,分别命名为 option-100
和 option-10
,用来表示100金额和10金额,最后移动位置,得到下图这样的效果:

不是圆角的,感觉有点丑。。。
最后一步,将 options
节点隐藏,然后将 monkey-word
节点取消隐藏,至此,静态页面部分就搞定了,此时 buy-btn-group
节点的结构如下:

脚本组件
静态页面完成之后,就到实现通过代码来控制选项列表的显示与隐藏以及选项确定逻辑了。
首先新建一个脚本组件 buybtn-control.ts
,将其挂载到 buy-btn-group
节点下。
属性定义
首先定义5个属性:
- investText:投入勋章4个字的文本节点;
- buyNumber:buy-number节点;
- selector:selector节点;
- monkeyWord:monkey-word节点;
- investMoney:number类型,保存当前选中的金额,默认值100;
然后在start周期中通过getChildByName方法进行节点获取:
ts
this.investText = this.node.getChildByName('text')
this.buyNumber = this.node.getChildByName('buy-number')
this.selector = this.node.getChildByName('selector')
this.monkeyWord = this.node.getChildByName('monkey-word')
点击事件绑定
节点赋值之后,分别对每个节点进行点击事件绑定,同样是在start周期,获取节点之后:
ts
this.investText.on(Node.EventType.TOUCH_END, () => {
console.log('投入勋章')
})
this.buyNumber.on(Node.EventType.TOUCH_END, () => {
this.buyNumberClick()
})
const options = this.selector.children
for (const option of options) {
option.on(Node.EventType.TOUCH_END, (e) => {
this.optionClick(e)
}, this)
}
下拉选项节点中的每一个option节点都需要绑定点击事件,所以通过forof循环进行事件绑定。
buyNumberClick
当点击 buy-number
节点的时候,会将selector选择器节点的显隐状态取反,然后 monkey-word
节点的显隐再根据更新后的selector节点的显隐状态进行变更,反正就是selector显示的时候 monkey-word
就会隐藏起来,反之亦然,除此之外,当selector为显示状态的时候,还要遍历其下的option节点,通过节点的name属性获取改节点的金额,与investMoney进行对比,相同的话则将改option节点设为selected状态:
ts
buyNumberClick() {
this.selector.active = !this.selector.active
this.monkeyWord.active = !this.selector.active
if (this.selector.active) {
const options = this.selector.children
for (const node of options) {
const num = Number(node.name.split('-')[1])
node.getChildByName('selected').active = num === this.investMoney
}
}
}
optionClick
当option节点被点击的时候,会通过event对象的target属性获取到当前点击节点的name和parent属性,然后通过name给investMoney赋值,通过parent的active属性,将整个选项列表隐藏,再去改变buyNumber节点显示的金额,最后还要将monkeyWord节点放出来:
ts
optionClick(event) {
const { parent, name } = event.target
this.investMoney = Number(name.split('-')[1])
parent.active = false
const num = this.buyNumber.getComponentInChildren(Label)
num.string = this.investMoney + ''
this.monkeyWord.active = true
}
效果示例
至此,下拉选择器就实现了,效果如下:
