前言:
学生:老师,我有 2 个下拉菜单,菜单项内容都是一样的,怎么实现第一个下拉菜单选择了的那一项不出现在第二个下拉菜单中。
我:??
初闻甚为诧异,还有这种需求?
而后一想,确有实现这个功能的必要:与人斗其乐无穷,如此一来游戏还未开始便可暗自较量了起来(PS:同学使用下拉菜单选择装备)
实现:
Talk is cheap , show me the code
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
public class LockedOptionItemManager : MonoBehaviour
{
public List<Dropdown> dropdowns;
public List<string> data;
public Dictionary<Dropdown, string> hasSelected = new Dictionary<Dropdown, string>();
public IEnumerable<Dropdown.OptionData> options;
void Start()
{
options = data.Select(v => new Dropdown.OptionData(v));
foreach (var dropdown in dropdowns)
{
dropdown.options.Clear();
dropdown.options.AddRange(options);
dropdown.onValueChanged.AddListener(v => OnDropdownSelected(v, dropdown));
}
}
private void OnDropdownSelected(int index, Dropdown dropdown)
{
//获取前期被占用的菜单项
hasSelected.TryGetValue(dropdown, out string selected);
//更新此 Dropdown 占用的菜单项
hasSelected[dropdown] = index == 0 ? "" : dropdown.captionText.text;
// 刷新其他 dropdowm 的菜单项
foreach (var item in dropdowns)
{
if (item != dropdown)
{
// 只要选的不是默认项(第0项 )就需要将此菜单项从其他下拉菜单中剔除
if (index != 0)
{
item.options.RemoveAll(v => v.text == dropdown.captionText.text);
}
// 只要发现之前选择的菜单项不是 空值 ,就为其他下拉菜单添加回去
if (!string.IsNullOrEmpty(selected))
{
var option = options.FirstOrDefault(v => v.text == selected);
item.options.Add(option);
}
// 发现如果下拉菜单项中发生了移除的行为,dropdown.value 与 captionText 数据将有可能不匹配,
// 我们需要重新刷新 dropdown.value
var value = item.options.FindIndex(v => v.text == item.captionText.text);
item.SetValueWithoutNotify(value);
}
}
}
}
- 关键流程每一步都有注释,注释见脚本上下文
- 可以学到:List 、Dictionary 等数据结构, Lambda 表达式、Linq基础语法,以及 Dropdown 系列 API
动画
- 将需要互锁菜单项的 Dropdown 放在 Dropdowns 列表中
- 将共享菜单项写入到 脚本 data 列表中
- 运行即可
结语
之前可没想过这种需求,在一脸懵逼的情况下实现&调试着实费了一番功夫,不过,甚是有趣~
网友评论