﻿## 打开、关闭界面

我们运行 UIBasicPanel 是通过 UIPanelTester 实现的。

UIPanelTester 是一个 UI 界面的测试器，它只能在编辑器环境下运行。

真正打开一个 UI 界面，是通过 UIKit.OpenPanel 这个 API 完成的。

只需要写如下代码即可:

```csharp
UIKit.OpenPanel<UIBasicPanel>();
```

代码非常简单。

而我们要关闭掉一个 UI 界面也比较容易，代码如下:

```csharp
UIKit.ClosePanel<UIBasicPanel>();
```

如果是在一个界面内部关掉自己的话，代码如下:

```csharp
this.CloseSelf(); // this 继承自 UIPanel 
```

OK，到此我们接触了 3 个 API：

* UIKit.OpenPanel\<T\>();
* UIKit.ClosePanel\<T\>();
* UIPanel.CloseSelf();

后边的两个没什么好讲的，很简单，但是第一个 API 比较重要，因为它有一些参数我们可以填。

## UIKit.OpenPanel

UIKit.OpenPanel 的参数定义及重载如下：

```csharp
public static T OpenPanel<T>(UILevel canvasLevel = UILevel.Common, IUIData uiData = null,
            string assetBundleName = null,
            string prefabName = null) where T : UIPanel
{
	...
}

public static T OpenPanel<T>(IUIData uiData, PanelOpenType panelOpenType = PanelOpenType.Single,
            string assetBundleName = null,
            string prefabName = null) where T : UIPanel
{
	...
}

public static UIPanel OpenPanel(string panelName, UILevel level = UILevel.Common, string assetBundleName = null)
{
	...
}
```



所有参数如下：

* canvasLevel：界面在哪个层级打开
  * 默认值：Common
* uiData：打开时可以给界面传的初始数据
  * 默认值：null
* assetBundleName：界面资源所在的 assetBundle 名
  * 默认值：null
* prefabName：如果界面名字和 prefab 名字不同，则以这个参数为准去加载界面资源
  * 默认值：null

都有默认值，所以这四个参数都可以不用传。

不过这四个 API 在某种情况下非常实用。

下边举一些例子。

```csharp
// 在 Forward 层级打开
UIKit.OpenPanel<UIBasicPanel>(UILevel.Forward);

// 传递初始数据给 UIHomePanel
UIKit.OpenPanel<UIBasicPanel>(new UIHomePanelData()
{
    Coin = 10
});
            
// 从 UIHomePanelTest.prefab 加载界面 
UIKit.OpenPanel<UIBasicPanel>(prefabName: "UIBasicPanel");
```

都比较容易理解。

有的童鞋可能会问，我们给 UIHomePanel 传递的  UIHomePanelData，在哪里使用呢？

答案是在，OnInit 和 OnOpen 中，如下所示:

```csharp
namespace QFramework.Example
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using UnityEngine;
    using UnityEngine.UI;
    
    
    public class UIBasicPanelData : QFramework.UIPanelData
    {
        public int Coin;
    }
    
    public partial class UIBasicPanel : QFramework.UIPanel
    {
        protected override void OnInit(QFramework.IUIData uiData)
        {
            mData = uiData as UIBasicPanelData ?? new UIBasicPanelData();
            // please add init code here
            
            // 外边传进来的，第一次初始化的时候使用
            Debug.Log(mData.Coin);
        }
        
        protected override void OnOpen(QFramework.IUIData uiData)
        {
            // 每次 OpenPanel 的时候使用
            Debug.Log((uiData as UIBasicPanelData).Coin);
        }
        
        protected override void OnShow()
        {

        }
        
        protected override void OnHide()
        {
        }
        
        protected override void OnClose()
        {
        }
    }
}

```

为什么要这样做呢？

笔者认为，界面有两种显示数据的用法，一种是有的界面是需要从外边填充的，比如警告、弹框、或者道具信息页面等。另一种界面是需要自己获取数据并展示的，比如游戏中的主角金币、等级、经验值等。



如果界面的数据都从外边填充，那么这个界面会拥有更好的可复用性。



当然需要一个可复用性的界面还是需要一个普通界面就看大家的需求了，并不是说有可复用性的界面就是好的。

本文由 QFramework 教程年会员赞助，地址：[https://www.gamepixedu.com/goods/show/55](https://www.gamepixedu.com/goods/show/55)

* QFramework 主页：[qframework.cn](https://qframework.cn)
* QFramework 交流群: 541745166
* QFramework Github 地址: <https://github.com/liangxiegame/qframework>
* QFramework Gitee 地址：<https://gitee.com/liangxiegame/QFramework>
