GameObject go = new GameObject("Panels",typeof(RectTransform));
第一个参数是名字,第二个后面的是要给空物体添加的组件,这里天剑RectTransform,RectTransform就会替代Transform组件。
如果单单的调用点击的方法,按钮被点击的效果是不会被看到的。
private void OnGUI() { if (GUILayout.Button("Button Click")) { // ExecuteEvents.Execute<IPointerClickHandler>(button.gameObject, new PointerEventData(EventSystem.current), ExecuteEvents.pointerClickHandler); //会有按钮点击的效果出现 ExecuteEvents.Execute<ISubmitHandler>(button.gameObject , new PointerEventData(EventSystem.current), ExecuteEvents.submitHandler); } if (GUILayout.Button("Image Click")) { //单单就是触发点击事件,添加了EventTrigger的Image ExecuteEvents.Execute<IPointerClickHandler>(img.gameObject , new PointerEventData(EventSystem.current), ExecuteEvents.pointerClickHandler); } }
ExecuteEvents等类都是在UnityEngine.EventSystems命名空间中
EventTrigger组件类在UnityEngine.EventSystems命名空间中
using UnityEngine; using UnityEngine.UI; using UnityEngine.EventSystems; using UnityEngine.Events; public Image img; void Start () { EventTrigger trigger = img.GetComponent<EventTrigger>(); trigger.triggers = new List<EventTrigger.Entry>(); EventTrigger.Entry entry = new EventTrigger.Entry(); entry.eventID = EventTriggerType.PointerClick; UnityAction<BaseEventData> action = new UnityAction<BaseEventData>(OnImageClick); entry.callback.AddListener(action); trigger.triggers.Add(entry); } private void OnImageClick(BaseEventData data) { Debug.Log("图片点击"); }
可以看出,EventTrigger可以有一个List的触发器,每一个触发器Entry都有它的类型eventID,和被触发后的回调方法callback
回调方法是一个unity的委托方法(在UnityEngine.Events命名空间),参数必须是BaseEventData
如果要使被遮挡的按钮都可以点击触发事件的发生。
可以将遮挡的元素设置为按钮的子元素,但是整个被遮挡的物体都会被当成了按钮了。
在遮挡的元素上添加Canvas Group组件,取消勾选Blocks Raycasts,忽略射线检测。
在遮挡元素上添加UIFilter,重写过滤射线检测。
using UnityEngine; public class UIFilter : MonoBehaviour, ICanvasRaycastFilter { public bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera) { return false; } }
通过属性horizontalNormalizedPosition和verticalNormalizedPosition可以知道滑动到的区域。
范围都是[0,1],就是将垂直或则水平可滑动的区域划分为[0,1],0为开始,1为结束
可以用来将区域划分为页,注意1表示的是最后一页,所以每页的长度其实是1/(总页数-1),也就是把1-0的区域划分为(总页数-1)页。
Scroll添加上Scroll Rect的脚本,设置其的content为Content,Viewport设置为view
view就是遮罩层,添加Mask,能够看到东西的区域,主要的位置自适应都通过设置它来解决。
Content就是要存放物体的区域了。必须大过view层才有实际滑动的需要。主要要关注的就是长度和起点的位置了,起点设置好view层并将Content放置在view的区域就行了,长度的话可以根据类容来设置,没有长度是划不动的。
启动:调用单例模式的UIManager的Init()方法。初始化三个字典,存放panel路径,panel实例,正在显示的panel,都为空。调用解析json方法,json存储了panelPrefab的路径,存储到panel路径字典中。初始化panel的父节点和Menu,生成一个存放panel实例的父节点,添加脚本Menu,Menu会通过panel的名字加上特定的规范去搜索打开这个panel的按钮,如果找到了,添加监听事件。
Panel的打开,Panel需要一个Panel类需要继承自BasePanel的,Menu类已经为特定的按钮添加了打开Panel的事件,此时,直接点击按钮,就会调用UIManager的PushPanel方法,这个方法首先去panel实例中获取panel,获取到panle后,判断它是否在显示,如果在显示,则调用BasePanel的OnFocus方法,将它放到最前面,如果没有显示,则调用OnEnter方法,表示出来(可以做动画)。
Panel的关闭,照理说每个Panel都会有一个关闭按钮,在子物体里面命名为CloseBtn,BasePanel会自动的找到它,并添加关闭事件OnExit,实现关闭。
Panel的层次和拖拽,BasePanel实现了UGUI的事件接口,继承自BasePanel都可以自由的拖拽,点击选择到最上层。
public class BasePanel : IDragHandler,IBeginDragHandler { private Vector2 prePosition; public void OnDrag (PointerEventData eventData){ Vector2 offset = eventData.position - prePosition; this.transform.localPosition += new Vector3(offset.x,offset.y,0f); prePosition = eventData.position; } public void OnBeginDrag (PointerEventData eventData){ prePosition = eventData.position; } }
通过两次拖拽位置作比较,算出偏移多少,直接让目标对象也偏移多少,当然是本地坐标作移动
IScrollHandler-OnScroll,鼠标滚轮滚动事件
ISelectHandler-OnSelect,物体被选择时调用
IDeselectHandler-OnDeselect,物体取消被选择时调用
IInitializePotentialDrawHandler-OnInitializePotentialDrag,在被拖动的物体被找到时调用
IBeginDragHandler-OnBeginDrag,开始拖动时调用
IDragHandler-OnDrag,拖动时调用
IEndDragHandler-OnEndDrag,拖动结束时调用
IDropHandler-OnDrop,拖拽结束调用(?)