您的位置:首页 > 产品设计 > UI/UE

SRPG游戏开发(二十二)第六章 基本框架 - 七 视图(View&UI)

2018-04-02 15:34 253 查看
返回目录

第六章 基本框架(Framework)

七 视图(View&UI)

关于View与UI,一搜一大堆。

我们也不过多介绍了。

我们将使用Stack方式来打开我们的UI。

我们所有的View都存储在一个叫做
ViewDictionary
的字典中,它继承了
IDictionary
。并且主要核心算法(打开,关闭,销毁等)全部都放在它之中。使用名字
string
来作为Key,当然你也可以不使用名字,修改其使用
Enum


而Manager持有一个
ViewDictionary
,作为DontDestroy的父对象。

我们只来简单介绍一下核心部分,打开View,还有关闭中间View的方法。

当然,除了这两个,还有销毁,获取等等一系列,就不在这里说明了。

1 打开(Open View)

1.1 流程图(Flow Chart)



1.2 核心代码块(Main Code)

/// <summary>
/// 获取或实例化view。
/// 实例化时:
/// 1、预制体带组件,直接返回。
/// 2、预制体不带组件,动态添加组件。
/// 错误:
/// 1、找不到组件的类型。
/// 2、组件类型是Abstract。
/// 3、组件类型没有继承自ViewBase。
/// </summary>
/// <param name="viewName"></param>
/// <returns></returns>
protected ViewBase GetOrInstantiateView(string viewName)
{
ViewBase view;
if (!m_ViewDict.TryGetValue(viewName, out view))
{
// 获取Prefab
GameObject prefab = GetOrLoadPrefab(viewName);
if (prefab == null)
{
Debug.LogError("[InstantiateView] Prefab is not found.");
return null;
}

// 实例化并检测组件
GameObject viewGameObject = GameObject.Instantiate(prefab);
view = viewGameObject.GetComponent<ViewBase>();
if (view == null)
{
// 没有找到组件,动态添加
Type type = GetViewComponentType(viewName);
if (type == null || type.IsAbstract || !type.IsSubclassOf(typeof(ViewBase)))
{
Debug.LogErrorFormat(
"[InstantiateView] Get view type error. Type of view name '{0}' is null or is abstract or is not sub class of ViewBase.",
viewName
);
GameObject.Destroy(viewGameObject);
return null;
}
view = viewGameObject.AddComponent(type) as ViewBase;
}

view.LoadViewInternal(viewName);
OnInstantiateView(view);
m_ViewDict.Add(viewName, view);
}

return view;
}

/// <summary>
/// 打开一个View。
/// 如果View已经被打开,且在Stack的中间层,那么将关闭其上方所有View。
/// 如果没有实例化,先实例化再打开。
/// 如果你用来做UIManager,且是Canvas与Panel混用,
/// Canvas的实例化请不要用OpenView,请用OpenViewNotStack,否则会被加入到Stack中。
/// </summary>
/// <param name="viewName"></param>
/// <param name="closeStack"></param>
/// <param name="args"></param>
/// <returns></returns>
public ViewBase OpenView(string viewName, bool closeStack = false, params object[] args)
{
if (string.IsNullOrEmpty(viewName))
{
Debug.LogError("[OpenView] Argument named 'viewName' is null or empty.");
return null;
}

if (closeStack)
{
// 关闭所有Stack中的view
CloseViewsAll(true);
}

// 获取或实例化
ViewBase view = GetOrInstantiateView(viewName);
if (view == null)
{
Debug.LogErrorFormat("[OpenView] View named '{0}' is not found.", viewName);
return null;
}

// 如果已经打开,关闭其上层view
if (m_OpenViews.Contains(view))
{
if (!string.IsNullOrEmpty(view.nextViewNameInternal))
{
CloseView(view.nextViewNameInternal);
}
}
// 如果没有打开,打开并添加进Stack,如果已经打开且没有加入stack,就加入stack
else
{
view.OpenInternal(args);
ViewBase previous = m_OpenViews.Count > 0 ? m_OpenViews.Peek() : null;
m_OpenViews.Push(view);
OnStackViewOpenOrClose(previous, view, true, args);
currentView = view;
}

return view;
}


2 关闭(Close View)

2.1 流程图(Flow Chart)



2.2 核心代码块(Main Code)

/// <summary>
/// 关闭最上层的View。
/// </summary>
public void CloseView()
{
if (m_OpenViews.Count > 0)
{
ViewBase current = m_OpenViews.Pop();
current.CloseInternal();
ViewBase previous = m_OpenViews.Count > 0 ? m_OpenViews.Peek() : null;
OnStackViewOpenOrClose(previous, current, false);
currentView = previous;
}
}

/// <summary>
/// 关闭中间层View和其上层的View或没有加入Stack的View
/// </summary>
/// <param name="viewName"></param>
public void CloseView(string viewName)
{
if (string.IsNullOrEmpty(viewName))
{
Debug.LogError("[CloseView] Argument named 'viewName' is null or empty.");
return;
}

// 没有实例化的View
ViewBase view;
if (!m_ViewDict.TryGetValue(viewName, out view))
{
return;
}

// View没有在Stack
if (!m_OpenViews.Contains(view))
{
view.CloseInternal();
return;
}

while (m_OpenViews.Count > 0)
{
ViewBase current = m_OpenViews.Peek();
CloseView();
if (current == view)
{
break;
}
}
}


3 管理器(Mananger)

namespace DR.Book.SRPG_Dev.Framework
{
/// <summary>
/// 单例,ViewManager基类,核心算法ViewDictionary已被分离成单独的类。
/// 你可以不使用它,而只使用继承的ViewDictionary,自己建立UIManager。
/// 核心算法全部在ViewDictionary中。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TDictionary"></typeparam>
public abstract class ViewManagerBase<T, TDictionary> : UnitySingleton<T>
where T : ViewManagerBase<T, TDictionary>
where TDictionary : ViewDictionary
{
private static TDictionary s_Views;
/// <summary>
/// View核心
/// </summary>
public static TDictionary views
{
get
{
if (s_Views == null)
{
s_Views = instance.CreateViewDictionary();
s_Views.gameObject = instance.gameObject;
s_Views.prefabDirectory = prefabDirectory;
}
return s_Views;
}
}

[SerializeField, Tooltip("Root path of prefab.")]
private string m_PrefabDirectory = "Prefab/UI/";
/// <summary>
/// Prefab根路径
/// </summary>
public static string prefabDirectory
{
get { return instance.m_PrefabDirectory; }
set
{
instance.m_PrefabDirectory = value;
if (s_Views != null)
{
s_Views.prefabDirectory = value;
}
}
}

/// <summary>
/// 创建核心算法的Dictionary
/// </summary>
/// <returns></returns>
protected virtual TDictionary CreateViewDictionary()
{
Type type = typeof(TDictionary);
return Activator.CreateInstance(type) as TDictionary;
}

/// <summary>
/// 释放空间
/// </summary>
protected override void OnDestroy()
{
base.OnDestroy();

if (s_Views != null)
{
s_Views.Dispose();
s_Views = null;
}
}
}
}


4 最后的说明

具体的使用,可以参考事例代码。本章所有事例源代码在带有Example字样的文件夹内。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐