UGUI实现窗口切换动画

前言

在开发的过程中我们常常需要创建很多UI窗口,如何让这些窗口按照递归的方式而且还是带动画地进行切换呢,本文介绍了一种方法实现这个功能

思路

为了实现这样的效果,需要搭建一个UI框架,原理就是让Animator组件控制红框UI容器移动

在红框容器中再放置两个空物体作为子容器,分别是A和B,A是当前的页面,B是要打开的窗口,而B子容器部分还可再嵌套一个容器,这样移动红框容器,就可以将B部分显示出来

这时如果B部分也是一个容器,那么再移动B部分就能将C显示出来,以此类推

功能实现

首先要实现的就是创建控制父容器的两个动画,移动和恢复,向左移动以显示出B子容器,向右恢复来显示A子容器,使用Ctrl+6 打开动画设置面板,选中红框容器,为其创建一个动画,创建动画的过程在这里就不赘述了,只是简单的移动Anchored Position位置,然后在Animator中为其添加展开和关闭动画,并设置is_Open bool用于值切换动画,一切准备好后,就可以为红框父容器添加一个脚本:Container 代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/// <summary>
/// 红框容器脚本
/// </summary>
public class Container : MonoBehaviour
{
Animator at;
public Container before; //上一个容器
public Button btn_back; //返回上一个容器按钮(关闭当前窗口)

public Transform A; //子容器A
public Transform B; //子容器B

private void Awake()
{
at = GetComponent<Animator>(); // 获取动画组件
A = transform.Find("A"); //获取子容器
B = transform.Find("B");
if(btn_back!=null)
btn_back.onClick.AddListener(Back);//按钮绑定事件
}
//设置当前是否播放动画,参数为true时,切换到B,false时切换回A
public void SwitchWindow(bool b)
{
at.SetBool("isOpen", b);
}
//按下返回按钮
public void Back()
{
before.SwitchWindow(false); //关闭当前窗口时,让父容器切换回A页面
//返回到上一个窗口时,将自身从父容器的B子容器中分离,因为父窗口不一定只会打开这个窗口,可能会有多个分支
transform.parent= null;
gameObject.SetActive(false); //隐藏当前窗口
}
}

这样,只需要调用SwitchWindow(bool b)方法,就能实现切换窗口,接下来要创建打开一个新窗口的脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class OpenWindow : MonoBehaviour
{
Container Con; //当前容器
public Transform win; //下一个窗口
public Button btn; //打开按钮
private void Awake()
{
Con = GetComponent<Container>(); //获取当前容器组件
btn.onClick.AddListener(() =>
{
win.parent = Con.B; //要显示的窗口设置为容器的B
(win as RectTransform).anchoredPosition = Vector3.zero;//恢复0位置,相当于B容器
win.gameObject.SetActive(true); //激活显示要切换的窗口
win.GetComponent<Container>().before = Con; // 将当前容器传递给下一个容器
Con.SwitchWindow(true); //切换到B
});
}
}

将这个脚本赋予给红框容器,然后添加打开下一个页面的按钮和下一个窗口的Transform,默认情况下要打开窗口的GameObject是禁用隐藏的,然后先将它放入当前容器的B子容器中(预备打开),将其位置归零,然后激活这个GameObj,把当前窗口的Container组件传递给新窗口(用于在新窗口关闭时调用),一切都准备就绪后,使用SwitchWindow(true)让当前红框容器动画切换到B子容器,这时控制权为B容器中的内容,是调用Back()方法返回上一个页面,还是再进入新的页面都可以。

结构图

最后Ctrl+D复制几个容器,主容器上添加OpenWindow脚本,把复制出来的容器拖入即可

总结

实现这个技术主要用到了嵌套的模式结合动画来实现这个效果,有点类似于数据结构中的链栈结构,可以不断的打开新的窗口,但回退时必须要原路返回