Unity之NGUIUIButton点击事件的带参传递

来源:互联网 发布:sgd算法 矩阵分解 编辑:程序博客网 时间:2024/05/01 00:09

最近写的游戏中UI部分用的NGUI,感觉NGUI真心没UGUI好用啊,功能封装的不全,想要什么功能还得去翻源码。比如PopList加滑动。。。

今天说说UIButton的点击事件,最简单的拖动就不说了,功能很鸡肋,一是不好维护,而是很多情况下我们要动态生成一些button并且对这些button回调,NGUI中封装了一个EventDelegate类用来添加回调函数,再把很多个EventDelegate封装成一个List委托链实现一对多的观察者模式。所以如果我们想让UIButton带参传递,关键是如何向EventDelegate中封装参数。

我们先看看EventDelegate的执行方法,核心代码就一句:

mMethod.Invoke(mTarget, mArgs);

显然我们在实例化EventDelegate时,至少给他一个方法名,让他的mMethod可以通过反射找到方法,至少给他一个类实例,让他知道执行哪个实例中的方法,mTarget在声明时规定MonoBehavior类型,显然我们还要给他一个组件实例,正好对应我们想要接受回调函数的那个实例。而第二个参数mArgs正是我们需要的回调参数,那我们再看看EventDelegate中是否有参数传递的相关属性或者方法。

幸运的是EventDelegate类中封装了参数类,类似通知模式通过强转Object可以传递各种类型的参数。

[System.Serializable]public class Parameter{public Object obj;public string field;public Parameter () { }public Parameter (Object obj, string field) { this.obj = obj; this.field = field; }public Parameter (object val) { mValue = val; }[System.NonSerialized] object mValue;#if REFLECTION_SUPPORT[System.NonSerialized]public System.Type expectedType = typeof(void);// Cached values[System.NonSerialized] public bool cached = false;[System.NonSerialized] public PropertyInfo propInfo;[System.NonSerialized] public FieldInfo fieldInfo;/// <summary>/// Return the property's current value./// </summary>public object value{get{if (mValue != null) return mValue;if (!cached){cached = true;fieldInfo = null;propInfo = null;if (obj != null && !string.IsNullOrEmpty(field)){System.Type type = obj.GetType();#if NETFX_COREpropInfo = type.GetRuntimeProperty(field);if (propInfo == null) fieldInfo = type.GetRuntimeField(field);#elsepropInfo = type.GetProperty(field);if (propInfo == null) fieldInfo = type.GetField(field);#endif}}if (propInfo != null) return propInfo.GetValue(obj, null);if (fieldInfo != null) return fieldInfo.GetValue(obj);if (obj != null) return obj;#if !NETFX_COREif (expectedType != null && expectedType.IsValueType) return null;#endifreturn System.Convert.ChangeType(null, expectedType);}set{mValue = value;}}/// <summary>/// Parameter type -- a convenience function./// </summary>public System.Type type{get{if (mValue != null) return mValue.GetType();if (obj == null) return typeof(void);return obj.GetType();}}#else // REFLECTION_SUPPORTpublic object value { get { if (mValue != null) return mValue; return obj; } } #if UNITY_EDITOR || !UNITY_FLASHpublic System.Type type { get { if (mValue != null) return mValue.GetType(); return typeof(void); } } #elsepublic System.Type type { get { if (mValue != null) return mValue.GetType(); return null; } } #endif#endif}
根据源代码可知EventDelegate中的内部类实例化需要一个参数,一个字符串,这个字符串干什么用的没看懂,估计和生成对用的哈希值有关系,但根据逻辑能判断不同参数对应的字符串不能相等,估计是为了生成完全不同的哈希值吧,这样简单了,我们只需要实例化一个参数类放进实例化的EventDelegate实例就好了。可这时编辑器报错了,显示EventDelegate中的mParameter只读,翻翻源代码发现了一下几行代码:

public Parameter[] parameters{get{#if UNITY_EDITORif (!mCached || !Application.isPlaying) Cache();#elseif (!mCached) Cache();#endifreturn mParameters;}}
NGUI并没有提供参数的Set方法,至于为什么我也不清楚。。。但为了我们能使用,我们就加上set方法好啦,很简单,get下面加上set {mParameters = value;}就好了。

剩下的工作就简单了,将这个EventDelegate放进委托链里就好了,而这个委托链则是你要添加的某个按钮甚至各种各样UI组件的监听事件里,就能实现带参传递了。

0 0
原创粉丝点击