新的思路
注册流程的第二种实现。
通过仔细思考,设置用户个人信息的几个界面,没有再从别的接口进入的情况;
上一步一定是选择 “Google" "facebook"等 邮箱号登录,且发现是第一次登录的情况。
那么,其实可以不用栈来保持上一步的操作。
自然而然地,我也就摒弃了使用双向队列+栈这组数据结构了;
可以试着让问题简单化一点
可以把【显示页面作为一个操作】,将不同页面需要加载的数据,【差异化的数据】用数据结构存储起来,公共的内容,先在基类里。
每个界面的加载逻辑的瀑布流是确定的,写成基类的虚方法。
在初始化阶段,将数据结构实例化,这样就拿到了实例化后的不同界面需要加载的内容。
然后一次存入列表
【下一步】其实就是【显示Index+1】的界面
【返回】就是【显示index-1】界面
protected void CommitAffair()
{
JumpToProcess(_nextProcessIndex++);
}
private void OnClickBackBtn()
{
JumpToProcess(--_nextProcessIndex);
}
代码部分
先给出基类界面,是一些子类用到的公共逻辑,主要是确定各子类界面的加载流程。
返回按钮的监听、skip跳过按钮的监听(绿框的按钮)等等。
UIBase
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using UnityEngine;
using UnityEngine.UI;
using TEngine;
using UnityEngine.PlayerLoop;
namespace GameLogic.UI
{
[Window(UILayer.UI)]
public class LoginSettingUIBase : UIWindow
{
protected int _nextProcessIndex;
protected List<LoginPointWidget> _pointWidgetsList;
#region 脚本工具生成的代码
protected Button m_btnBack;
private Button m_btnSkip;
private GameObject m_goPointRoot;
public override void ScriptGenerator()
{
m_btnBack = FindChildComponent<Button>("m_btnBack");
m_btnSkip = FindChildComponent<Button>("m_btnSkip");
m_goPointRoot = FindChild("Panel/m_goPointRoot").gameObject;
m_btnBack.onClick.AddListener(OnClickBackBtn);
m_btnSkip.onClick.AddListener(OnClickSkipBtn);
}
#endregion
public override void RegisterEvent()
{
base.RegisterEvent();
AddUIEvent(CommonWidgetDefine.ExcuteRegisterAffair,CommitAffair);
}
public override void OnCreate()
{
base.OnCreate();
Init(); //初始化过程
CommitAffair(); //刷新第一个页面 processIndex = 0(执行事务)
}
protected virtual void JumpToProcess(int id)
{
}
protected virtual void Init()
{
_pointWidgetsList = new List<LoginPointWidget>();
}
protected void CommitAffair()
{
JumpToProcess(_nextProcessIndex++);
}
protected void CreateBottomPoints(int count)
{
for (int i = 0; i < count ; i++)
{
var curWidget = CreateWidgetByPath<LoginPointWidget>(m_goPointRoot.transform, "LoginPointWidget");
_pointWidgetsList.Add(curWidget);
}
}
#region 事件
private void OnClickBackBtn()
{
JumpToProcess(--_nextProcessIndex);
}
private void OnClickSkipBtn()
{
GameModule.UI.CloseWindow<LoginSettingUI_Oversea>();
GameModule.UI.ShowUI<LoginLoadSuccessUI_Oversea>();
}
#endregion
}
}
子界面
差异化存储的数据结构
//存放右值的数据结构
public class ConfigData
{
//选项个数
public int OptCounts;
//选项内容
public string[] OptArray;
public bool IsDisplayBackBtn = true;
public bool IsDisplayMidReminder;
public bool IsSetName;
//进度点已完成个数
public int PointVisitedCounts;
//生成数据的父节点
public Transform RootTransform;
public string TopReminder;
public string MidReminder;
}
显示界面的方法【从实例化后的数据结构中读数据】
private void DisplayPage(ConfigData data)
{
// clear display
ClearWidgetsBuffer();
if (!_graphicRaycaster.enabled)
{
_graphicRaycaster.enabled = true;
}
m_btnBack.gameObject.SetActive(data.IsDisplayBackBtn);
var midReminderObj = m_btnReminderMid.gameObject;
midReminderObj.SetActive(data.IsDisplayMidReminder);
if (midReminderObj.activeInHierarchy)
{
m_textReminderMid.text = data.MidReminder;
}
m_textReminderTop.text = data.TopReminder;
//设置底部进度点
var visitedCounts = data.PointVisitedCounts;
for (int i = 0; i < TotalProcess; i++)
{
if (i <= visitedCounts)
{
_pointWidgetsList[i].DisplayVisitedColor();
}
else
{
_pointWidgetsList[i].DisplayDefaultColor();
}
}
//设置姓名
if (data.IsSetName)
{
var curWidget = CreateWidgetByPath<LoginNameSettings>(m_goNameRoot.transform, "LoginNameSettings");
_uiWidgetsBuffer.Add(curWidget);
return;
}
//设置年、月
var optCounts = data.OptCounts;
var parentTransform = data.RootTransform;
var contentArray = data.OptArray;
for (int i = 0; i < optCounts; i++)
{
var curWidget = CreateWidgetByPath<LoginOptWidget>(parentTransform, "LoginOptWidget");
_uiWidgetsBuffer.Add(curWidget);
curWidget.DataInitialize(contentArray[i]);
}
}
具体化操作流程
protected override void JumpToProcess(int id)
{
base.JumpToProcess(id);
DisplayPage(_dataList[id]);
}
protected override void Init()
{
base.Init();
PrepareData();
_dataList = new List<ConfigData>(TotalProcess);
_dataList.Add(DisplayYearPage());
_dataList.Add(DisplayMonthPage());
_dataList.Add(DisplayNamePage());
_graphicRaycaster = gameObject.GetComponent<GraphicRaycaster>();
CreateBottomPoints(TotalProcess);
}
LoginSettingUI_Oversea
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TEngine;
namespace GameLogic.UI
{
[Window(UILayer.UI)]
public class LoginSettingUI_Oversea : LoginSettingUIBase
{
private const int YearItemCounts = 8;
private const int MonthItemCounts = 12;
private const int TotalProcess = 3;
public string UserYear,UserMonth,UserName;
private List<UIWidget> _uiWidgetsBuffer;
private GraphicRaycaster _graphicRaycaster;
private Dictionary<int, string> _monthDic;
private List<ConfigData> _dataList;
//存放右值的数据结构
public class ConfigData
{
//选项个数
public int OptCounts;
//选项内容
public string[] OptArray;
public bool IsDisplayBackBtn = true;
public bool IsDisplayMidReminder;
public bool IsSetName;
//进度点已完成个数
public int PointVisitedCounts;
//生成数据的父节点
public Transform RootTransform;
public string TopReminder;
public string MidReminder;
}
#region 脚本生成
private Text m_textReminderTop;
private GameObject m_goYearRoot;
private GameObject m_goMonthRoot ;
private GameObject m_goNameRoot;
private Button m_btnReminderMid;
private Text m_textReminderMid;
public override void ScriptGenerator()
{
base.ScriptGenerator();
m_textReminderTop = FindChildComponent<Text>("Panel/m_textReminderTop");
m_goYearRoot = FindChild("Panel/m_goYearRoot").gameObject;
m_goMonthRoot = FindChild("Panel/m_goMonthRoot ").gameObject;
m_goNameRoot = FindChild("Panel/m_goNameRoot").gameObject;
m_btnReminderMid = FindChildComponent<Button>("Panel/m_btnReminderMid");
m_textReminderMid = FindChildComponent<Text>("Panel/m_btnReminderMid/m_textReminderMid");
m_btnReminderMid.onClick.AddListener(OnClickReminderMidBtn);
}
#endregion
public override void RegisterEvent()
{
base.RegisterEvent();
AddUIEvent<string>(CommonWidgetDefine.LoginOptMsg,UpLoadOptMsg);
AddUIEvent(CommonWidgetDefine.ClickLocked, () =>
{
_graphicRaycaster.enabled = false;
});
}
protected override void JumpToProcess(int id)
{
base.JumpToProcess(id);
DisplayPage(_dataList[id]);
}
protected override void Init()
{
base.Init();
PrepareData();
_dataList = new List<ConfigData>(TotalProcess);
_dataList.Add(DisplayYearPage());
_dataList.Add(DisplayMonthPage());
_dataList.Add(DisplayNamePage());
_graphicRaycaster = gameObject.GetComponent<GraphicRaycaster>();
CreateBottomPoints(TotalProcess);
}
private void PrepareData()
{
_monthDic ??= new Dictionary<int, string>(MonthItemCounts)
{
{1,"Jan"},
{2,"Feb"},
{3,"Mar"},
{4,"Apr"},
{5,"May"},
{6,"Jun"},
{7,"Jul"},
{8,"Aug"},
{9,"Sept"},
{10,"Oct"},
{11,"Nov"},
{12,"Dec"},
};
_uiWidgetsBuffer = new List<UIWidget>();
}
private void DisplayPage(ConfigData data)
{
// clear display
ClearWidgetsBuffer();
if (!_graphicRaycaster.enabled)
{
_graphicRaycaster.enabled = true;
}
m_btnBack.gameObject.SetActive(data.IsDisplayBackBtn);
var midReminderObj = m_btnReminderMid.gameObject;
midReminderObj.SetActive(data.IsDisplayMidReminder);
if (midReminderObj.activeInHierarchy)
{
m_textReminderMid.text = data.MidReminder;
}
m_textReminderTop.text = data.TopReminder;
//设置底部进度点
var visitedCounts = data.PointVisitedCounts;
for (int i = 0; i < TotalProcess; i++)
{
if (i <= visitedCounts)
{
_pointWidgetsList[i].DisplayVisitedColor();
}
else
{
_pointWidgetsList[i].DisplayDefaultColor();
}
}
//设置姓名
if (data.IsSetName)
{
var curWidget = CreateWidgetByPath<LoginNameSettings>(m_goNameRoot.transform, "LoginNameSettings");
_uiWidgetsBuffer.Add(curWidget);
return;
}
//设置年、月
var optCounts = data.OptCounts;
var parentTransform = data.RootTransform;
var contentArray = data.OptArray;
for (int i = 0; i < optCounts; i++)
{
var curWidget = CreateWidgetByPath<LoginOptWidget>(parentTransform, "LoginOptWidget");
_uiWidgetsBuffer.Add(curWidget);
curWidget.DataInitialize(contentArray[i]);
}
}
private void ClearWidgetsBuffer()
{
if (_uiWidgetsBuffer.Count != 0)
{
foreach (var item in _uiWidgetsBuffer)
{
DestroyUIWidget(item);
}
_uiWidgetsBuffer.Clear();
}
}
private ConfigData DisplayYearPage()
{
ClearWidgetsBuffer();
ConfigData data = new ConfigData();
data.OptArray = new string[YearItemCounts];
data.OptCounts = YearItemCounts;
int year = DateTime.Now.Year;
for (int j = 0; j < YearItemCounts; j++)
{
data.OptArray[j] = year.ToString();
year -= 1;
}
data.IsDisplayBackBtn = false;
data.IsDisplayMidReminder = true;
data.MidReminder = String.Format("{0} or before", year-1);
data.TopReminder = "Please select your child's birth year";
data.RootTransform = m_goYearRoot.transform;
data.IsSetName = false;
data.PointVisitedCounts = 0;
return data;
}
private ConfigData DisplayMonthPage()
{
ClearWidgetsBuffer();
ConfigData data = new ConfigData();
data.OptArray = new string[MonthItemCounts];
data.OptCounts = MonthItemCounts;
for (int j = 0; j < MonthItemCounts; j++)
{
data.OptArray[j] = _monthDic[j+1];
}
data.IsDisplayBackBtn = true;
data.TopReminder = "Please select your child's birth month";
data.RootTransform = m_goMonthRoot.transform;
data.IsSetName = false;
data.PointVisitedCounts = 1;
return data;
}
private ConfigData DisplayNamePage()
{
ClearWidgetsBuffer();
ConfigData data = new ConfigData();
data.IsDisplayBackBtn = true;
data.TopReminder = "May I ask your child's name is ......";
data.RootTransform = m_goNameRoot.transform;
data.IsSetName = true;
data.PointVisitedCounts = 2;
return data;
}
#region 事件
private void OnClickReminderMidBtn()
{
UpLoadOptMsg(m_textReminderMid.text);
CommitAffair();
}
private void UpLoadOptMsg(string message)
{
switch (_nextProcessIndex)
{
case 1:
UserYear = message;
break;
case 2:
UserMonth = message;
break;
case 3:
UserName = message;
break;
}
//Upload the message to Server.
}
#endregion
}
}