前言

为了便于UI的开发,设计了一个简单的导航栏结构。目前版本的导航栏抽象类简化了导航栏选项的事件监听、移除。后续根据需求再丰富功能、结构。

本次实例用于设计角色·技能UI窗口的左侧导航栏以及右下角的按钮集。让事件能统一管理,减少过多的事件方法并简化的代码编写。


实现效果:

角色·技能界面


代码

UI的通用接口(IButtonProcessor可能用于RadioButton等各类的设计,所有抽出为接口)

using UnityEngine.UI;/// <summary>
/// 游戏UI
/// 说明:
///     1.包含UI方面的各个接口
/// </summary>
namespace GameUI
{/// <summary>/// 按钮处理器/// </summary>public interface IButtonProcessor{void OnClickEvent(string key,Button button);}
}

抽象类TCBarClass

using GameUI;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;/// <summary>
/// 导航栏工具类-基类
/// </summary>
public abstract class TCBarClass : IButtonProcessor
{//保存匿名委托的引用private Dictionary<string, UnityAction> dicBarButtonsAction = new Dictionary<string, UnityAction>();//导航按钮集public Dictionary<string, Button> dicBarButtons = new Dictionary<string, Button>();/// <summary>/// 移除本类相关的事件/// 说明:///     1.dicBarButtons按钮集事件/// </summary>public virtual void ClearEvent(){//为按钮选项dicBarButton移除事件foreach (KeyValuePair<string, Button> item in dicBarButtons){//添加委托事件//item.Value.onClick.RemoveAllListeners();              //可以通过RemoveAllListeners直接进行事件删除(该操作会删除绑定上的所有事件)//获取匿名委托索引并通过其来删除(反注册)事件item.Value.onClick.RemoveListener(dicBarButtonsAction[item.Key]);dicBarButtonsAction.Remove(item.Key);}}//ClearEvent_end/// <summary>/// 将目标游戏对象的子对象(含有Button组件)加入导航按钮集/// 流程:将所有需要添加事件的按钮加入dicBarButtons/// 注:dicBarButtons的key与OnClickEvent(string key, Button button)的key一致即可。若是采用默认的key匹配规则:通过名字来匹配,会比较容易、方便。/// 说明:根据按钮对象的结构进行编写,如不采用默认的barItem预设体结构,请重写override该方法/// barItem预设体结构为barItem-bg(Image)、btnClick(Button)/// </summary>/// <param name="barContent">目标游戏对象</param>public virtual void InitDicBarButtonsByGameObj(GameObject barContent){foreach (Transform item in barContent.transform){foreach (Transform item2 in item){Button tryButton;bool hasButton;//尝试获取ButtonhasButton = item2.TryGetComponent<Button>(out tryButton);if (hasButton){//如果有Button组件,则给dicBarButtons加入数据//传入为barItem的name与其btnClick的按钮dicBarButtons.Add(item.name, tryButton);}}}//遍历barContent子对象}//InitDicBarButtonsByGameObj_end/// <summary>/// 初始化BarButton的事件./// 说明:为dicBarButtons的按钮添加OnClickEvent()事件.///     前提:dicBarButtons的初始化完成.///             1.使用InitDicBarButtonsByGameObj(GameObject barContent)进行dicBarButtons的自动化初始化.///             2.手动进行dicBarButtons添加./// 注:调用本方法进行添加事件后需在不再使用相关事件时移除事件,请调用ClearEvent()./// </summary>public virtual void InitBarButtonsEvent() {//按钮选项集dicBarButtons为0则直接结束方法if (dicBarButtons.Count<=0){return;}//为按钮选项dicBarButtons添加事件foreach (KeyValuePair<string,Button> item in dicBarButtons){//添加匿名委托事件,传入key与按钮组件本身//为能传递参数,使用匿名委托//item.Value.onClick.AddListener(delegate { OnClickEvent(item.Key, item.Value); });//记录匿名委托到dicBarButtonsActionUnityAction eve = delegate { OnClickEvent(item.Key, item.Value); } ;dicBarButtonsAction.Add(item.Key,eve);item.Value.onClick.AddListener(eve);}}//InitBarButtonsEvent_end/// <summary>/// 按钮事件/// 说明:通过key(按钮名)在switch遍历执行不同的具体方法/// </summary>/// <param name="key">按钮名</param>/// <param name="button">按钮组件对象</param>public virtual void OnClickEvent(string key, Button button){Debug.Log("class TCBarClass:OnClickEvent()");/** 使用switch进行Key的匹配,在具体实现中重写该方法。* 模板如下:switch (key){case "匹配的key1"://具体事件key1的实现break;case "匹配的key2"://具体事件key2的实现break;default://错误提示:key不匹配,1.key写错造成不匹配;2.没有写key对应的switch-case实现。Debug.LogError("Wrong key matching!Check key or Complement the switch:"+key);break;}*/}//OnClickEvent_end
}

角色·技能UI窗口类

using GameUI;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 角色·技能面板
/// </summary>
public class RoleSkillPanel : BaseWindowWrapper<RoleSkillPanel>
{private Dictionary<int, RefSkillEffect> playerSkill;                //玩家的技能数据总表private RefSkillEffect curSkillEffect;                                //当前选中的技能private List<SkillItem> listSkillItem;                              //技能对应的所有生成的UI类private Button btnExit;                                             //“退出”按钮private Text txtTitleName;                                          //标题_名字private GameObject goBtnUse;                                        //使用按钮private GameObject goBtnDetail;                                     //详情按钮private GameObject content;private GameObject skillItem;                                       //技能生成的UI预设体private GameObject GoBarContentChooseBtn;                             //选项栏contentprivate GameObject GoBarContent;                                      //角色·技能导航栏contentprivate BarContent barContent;                                        //导航栏类private BarContentChooseBtn barContentChooseBtn;                      //可选按键选项栏类private SkillType curSkillType;                                       //当前技能的类型(1为主动,2为被动)private bool isEquip;                                                 //是否为来自装备的技能/// <summary>/// 技能类型/// 说明:后续扩大可存在GlobalPropertyMgr进行统一管理/// </summary>public enum SkillType{None = 0,ActiveSkill = 1,                      //主动PassiveSkill,                         //被动}/// <summary>/// 窗口初始化/// 说明:主要用于组件初始化/// </summary>protected override void InitCtrl() {btnExit = gameObject.GetChildControl<Button>("btnExit");txtTitleName = gameObject.GetChildControl<Text>("ScrollRect/roleSkillITitle/txtTitleName");goBtnUse = gameObject.GetChildControl<Transform>("BarChooseBtn/content/barUse").gameObject;goBtnDetail = gameObject.GetChildControl<Transform>("BarChooseBtn/content/barDetail").gameObject;content = gameObject.GetChildControl<Transform>("ScrollRect/Content").gameObject;GoBarContent = gameObject.GetChildControl<Transform>("Bar/content").gameObject;GoBarContentChooseBtn = gameObject.GetChildControl<Transform>("BarChooseBtn/content").gameObject;barContent = new BarContent(this);barContentChooseBtn = new BarContentChooseBtn(this);curSkillType = SkillType.ActiveSkill;isEquip = false;curSkillEffect = null;skillItem = SceneMgr.Instance.UIGoRoleSkillItem;playerSkill = PlayerMgr.Instance.ItemView.SkillData.DetailData;listSkillItem = new List<SkillItem>();}/// <summary>/// 窗口打开前/// 说明:主要用于窗口数据设置/// </summary>protected override void OnPreOpen() {//刷新UIRefreshUI();}/// <summary>/// 窗口打开/// </summary>protected override void OnOpen() {}/// <summary>/// 窗口关闭/// </summary>protected override void OnClose() {base.OnClose();ClearAndResetData();}/// <summary>/// 事件注册/// 说明:会在OnOpen前,OnPreOpen后执行/// </summary>protected override void InitMsg(){btnExit.onClick.AddListener(OnClickExit);//注册按钮事件barContent.InitBarButtonsEvent();barContentChooseBtn.InitBarButtonsEvent();}/// <summary>/// 事件反注册/// 说明:会在OnClose() 前执行/// </summary>protected override void ClearMsg(){btnExit.onClick.RemoveListener(OnClickExit);//删除事件barContent.ClearEvent();barContentChooseBtn.ClearEvent();}#region 点击事件private void OnClickExit(){WindowMgr.Instance.CloseWindow<RoleSkillPanel>(true);}#endregionprivate void RefreshUI(){//根据curSkillType切换不同的UI显示ResetUIData();}/// <summary>/// 重设UI数据/// 说明:根据curSkillType。curSkillType默认为1(PlayerActiveSkill)/// </summary>private void ResetUIData(){//根据curSkillType遍历不同的技能表,将其提取初始化显示到UI上foreach (RefSkillEffect item in playerSkill.Values){//寻找SkillType与isEquip都匹配的技能进行显示if (item.SkillType == (int)curSkillType && isEquip == item.isEquip){SkillItem newItem = new SkillItem(this);newItem.Id = item.Id;newItem.RefreshInfo();listSkillItem.Add(newItem);}}//初始content的高度GameToolMgr.CalContentPosByChildren(content.transform, skillItem);//根据curSkillType显示不同的按钮//可以通过dicBarButtons进行或者直接Panel获取目标进行操作。建议Panel直接获取进行操作switch (curSkillType){//主动技能:使用、详情case SkillType.ActiveSkill://barContentChooseBtn.dicBarButtons["barUse"].transform.parent.gameObject.SetActive(true);//barContentChooseBtn.dicBarButtons["barDetail"].transform.parent.gameObject.SetActive(true);goBtnUse.gameObject.SetActive(true);goBtnDetail.gameObject.SetActive(true);break;//被动技能:详情case SkillType.PassiveSkill:goBtnUse.gameObject.SetActive(false);goBtnDetail.gameObject.SetActive(true);break;default:break;}//switch_curSkillType_end}//ResetUIData_end/// <summary>/// 清除与重置数据/// </summary>private void ClearAndResetData(){//移除content的所有子对象GameToolMgr.ClearChild(content.transform);listSkillItem.Clear();}//技能项类//说明:显示在UI上的单一技能项预设体对应的实体类class SkillItem{private GameObject go;private Text txtName;private Image imgIcon;private string strTitle;private string strDesc;private RoleSkillPanel panel;public int Id;                              //当前item的Idprivate Button btnHelp;                     //帮助 按钮private Button btnGo;                       //GameObject对象的btnpublic SkillItem(RoleSkillPanel panel){this.panel = panel;Transform parent = panel.content.transform;//创建预设体this.go = GameObject.Instantiate(panel.skillItem, parent);txtName = go.GetChildControl<Text>("txtName");btnHelp = go.GetChildControl<Button>("btnHelp");btnGo = go.GetChildControl<Button>("btnGo");imgIcon = go.GetChildControl<Image>("icon");btnHelp.onClick.AddListener(OnClickDetailItemHelp);btnGo.onClick.AddListener(OnClickItem);}public void ClearMsg(){btnHelp.onClick.RemoveListener(OnClickDetailItemHelp);btnGo.onClick.RemoveListener(OnClickItem);}private void OnClickDetailItemHelp(){//点击帮助按钮后,出现信息窗口WindowMgr.Instance.OpenWindow<RoleHelpInfoPanel>(true);//发送消息·将显示的信息传给信息窗口。该信息窗口与RoleDetailStatePanel是共用的Send.SendMsg(SendType.SendRoleHelpInfo, strTitle, strDesc);}//OnClickDetailItemHelp_end//点击该技能选项private void OnClickItem(){//设置curSkillEffect为该技能选项Idpanel.curSkillEffect = panel.playerSkill[Id];Debug.Log("当前选中技能:"+Id+"|"+ panel.playerSkill[Id].Name);}public void RefreshInfo(){//根据id,获取数据赋予到UI上显示strTitle = panel.playerSkill[Id].Name;txtName.text = panel.playerSkill[Id].Name;strDesc = panel.playerSkill[Id].Desc;string iconPath = panel.playerSkill[Id].IconPath;if (!string.IsNullOrEmpty(iconPath)){imgIcon.sprite = Resources.Load<Sprite>(iconPath);}}//RefreshInfo_end}//嵌套类:角色·技能导航栏类private class BarContent : TCBarClass{private RoleSkillPanel panel;public BarContent(RoleSkillPanel panel){this.panel = panel;//初始化数据InitDicBarButtonsByGameObj(panel.GoBarContent);}public override void OnClickEvent(string key, Button button){switch (key){case "playerActiveSkill"://玩家主动技能panel.curSkillType = SkillType.ActiveSkill;panel.isEquip = false;panel.txtTitleName.text = "角色主动技能";break;case "playerPassiveSkill"://玩家被动技能panel.curSkillType = SkillType.PassiveSkill;panel.isEquip = false;panel.txtTitleName.text = "角色被动技能";break;case "equipActiveSkill"://装备主动技能panel.curSkillType = SkillType.ActiveSkill;panel.isEquip = true;panel.txtTitleName.text = "来自装备的主动技能";break;case "equipPassiveSkill"://装备被动技能panel.curSkillType = SkillType.PassiveSkill;panel.isEquip = true;panel.txtTitleName.text = "来自装备的被动技能";break;default:return;}//数据清除panel.ClearAndResetData();//刷新UIpanel.RefreshUI();}}//class_BarContent_end//嵌套类:可选按键选项栏类private class BarContentChooseBtn : TCBarClass{private RoleSkillPanel panel;public BarContentChooseBtn(RoleSkillPanel panel){this.panel = panel;//初始化数据InitDicBarButtonsByGameObj(panel.GoBarContentChooseBtn);}public override void OnClickEvent(string key, Button button){switch (key){case "barUse"://玩家主动技能Debug.Log("使用技能");//执行对应主动技能的效果Send.SendMsg(SendType.TriggerEffect, panel.curSkillEffect.Id);break;case "barDetail"://玩家被动技能Debug.Log("技能详情" + panel.curSkillEffect.Name);//点击详情按钮后,出现信息窗口//WindowMgr.Instance.OpenWindow<DetailInfoPanel>(true);//弹出详细信息//Send.SendMsg(SendType.SendObjDetailInfo, this);break;default:break;}}}//class_BarContent_end}//class_end

【游戏面包屑】简单的导航栏设计相关推荐

  1. 2019年最实用的导航栏设计实践和案例分析全解

    我们都知道,用户的浏览习惯是从左到右,从上到下.所以一个网站的导航栏至关重要,用户进入你的网站,首先查找的信息就是从导航栏开始.一个用户体验好的导航栏,会增加网站的转化率和回访率.反之,用户会离开你的 ...

  2. html 导航栏设计,在网页中设计导航菜单的三个原则(附案例)

    导航菜单可能是网页设计中最重要的部分了.每个用户浏览网站时一定有所需,因此导航菜单能够帮助用户寻找信息.好的导航菜单像是导游,告诉用户网站是干什么的,内容分类有哪些,在哪里可以找到什么信息. 而且导航 ...

  3. android仿微信的activity平滑水平切换动画,Android实现简单底部导航栏 Android仿微信滑动切换效果...

    Android实现简单底部导航栏 Android仿微信滑动切换效果 发布时间:2020-10-09 19:48:00 来源:脚本之家 阅读:96 作者:丶白泽 Android仿微信滑动切换最终实现效果 ...

  4. 使用html,css实现简单的导航栏

    标题:使用html,css实现简单的导航栏 一.实现过程 首先通过ul,li实现一个无序列表,添加背景得到如图所示的样式[文档流] 让li浮动,使得垂直排列–>水平排列,[注意需要开启bfc,让 ...

  5. 9.后台管理系统主页面布局以及左侧导航栏设计

    9.后台管理系统主页面布局以及左侧导航栏设计 1.首页布局 步骤: 在views目录下新建Main.vue文件,作为登录之后的布局 参考:element-ui 使用此模块的目的是,当中间内容部分有超出 ...

  6. html+css简单立体导航栏

    html+css简单立体导航栏 一.简单立体导航栏效果 二.代码实现 1.html 2.css 一.简单立体导航栏效果 二.代码实现 1.html 代码如下(示例): <!DOCTYPE htm ...

  7. HTML 制作简单的导航栏

    一个简单的导航栏 <style> ul li {list-style:none; /*去掉li显示的前面的圆点*/width: 120px;text-align: center;float ...

  8. Android开发——底部导航栏设计

    底部导航栏设计 1.依赖配置 2.tabbar的UI实现 3.tabbar的逻辑绑定 4.tabbar的滑动与点击联动 5.tabbar与文本输入的冲突解决方案     其实,常见的Android和微 ...

  9. 简单浮动导航栏(HTML+CSS实现)

    简单浮动导航栏,鼠标移上去自动展开下拉菜单,使用HTML+CSS实现. 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Trans ...

最新文章

  1. Linux性能研究(总)
  2. tms570 can 接收大量数据_CAN通讯系列--AUTOSAR架构的CAN Interface7
  3. 20161104面试题-面试常问问题
  4. pandas(七) -- 数据分组
  5. 关于SAP UI5数据绑定我的一些原创内容
  6. gwt入门和进阶_GWT入门
  7. Pandas索引操作及高级索引——reindex()方法
  8. mysql 模糊查询用法_mysql进阶(六)模糊查询的四种用法介绍
  9. Alibaba之MySQL宝典_阿里巴巴内部 MySQL宝典 意外流出!极致经典,堪称数据库的天花板...
  10. 代码实现tan graph model for classification_几行代码搞定ML模型,低代码机器学习Python库正式开源...
  11. Mac上emacs标记快捷键
  12. Java SSH框架学习
  13. 腾讯微博开放平台API SDK vb版源码发布
  14. element-ui下拉框全选
  15. win11运行gnuplot报错:This application failed to start because no Ot platform plugin could be initialized
  16. 如何解决win7开机提示未能连接一个Windows服务
  17. 计算机二级选择题瞎蒙,一级消防员考试,一级消防员考试题大全
  18. NXP-MPC5748G车载MCU使用(食用)方法(踩坑)实用指南(骗人教程)(二):使用FREERTOS点亮LED
  19. 计算机科学数学科目,计算机科学与技术考研考哪些科目 备考技巧有哪些
  20. SpringBoot2+MybatisPlus3入门手册v2修订版

热门文章

  1. 2020面试自动化测试面试题【含答案】
  2. el-table高亮显示
  3. 哪有那么多BAT的逆袭?
  4. 中国是时候在东亚做老大了?
  5. pytorch数据抽样 随机取样
  6. 从事手机软件开发需要掌握什么知识
  7. 简单方法解决火狐浏览器主页被篡改/挟持,主页变成垃圾网站的问题
  8. 世界最快超级计算机 探秘天河一号
  9. 如何成为一名游戏开发程序员
  10. 怎么把录音转文字?这些方法值得收藏