195 lines
7.8 KiB
C#
195 lines
7.8 KiB
C#
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
using Logic;
|
||
using RuntimeData;
|
||
using Animancer;
|
||
using Logic.Config;
|
||
using UnityEngine.UI;
|
||
using Logic.Multilingual;
|
||
using TMPro;
|
||
using UI.Core;
|
||
using System.Linq;
|
||
using UnityEngine.EventSystems; // 引入LINQ以便更方便地操作
|
||
|
||
namespace UI
|
||
{
|
||
public class BoardingUI : CommonUI
|
||
{
|
||
private Transform _versionLabelList;
|
||
private Transform _versionContent;
|
||
// 新增:用于持有右侧详情描述文本的引用
|
||
private TextMeshProUGUI _versionDescriptionText;
|
||
|
||
public BoardingUI(GameObject UIObject, GameObject CloseButton) : base(UIObject, CloseButton)
|
||
{
|
||
InitData();
|
||
|
||
}
|
||
|
||
protected override void UpdateData()
|
||
{
|
||
//默认选中一个第一个
|
||
TriggerFirstVersionLabelClick();
|
||
}
|
||
|
||
private void TriggerFirstVersionLabelClick()
|
||
{
|
||
// 健壮性检查 #1: 确保列表Transform存在且有子节点
|
||
if (_versionLabelList == null || _versionLabelList.childCount == 0)
|
||
{
|
||
Debug.LogWarning("BoardingUI: _versionLabelList is empty, cannot trigger first item's click.");
|
||
return;
|
||
}
|
||
|
||
// step #1 获取第一个子节点的Transform
|
||
Transform firstChild = _versionLabelList.GetChild(0);
|
||
|
||
// step #2 从子节点上获取Button组件
|
||
Button firstButton = firstChild.GetComponent<Button>();
|
||
|
||
// 健壮性检查 #2: 确保Button组件存在
|
||
if (firstButton != null)
|
||
{
|
||
// step #3 调用onClick事件的Invoke方法,执行所有绑定的监听器
|
||
firstButton.onClick.Invoke();
|
||
EventSystem.current.SetSelectedGameObject(firstButton.gameObject);
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning($"BoardingUI: The first child '{firstChild.name}' of _versionLabelList does not have a Button component.", firstChild);
|
||
}
|
||
}
|
||
|
||
|
||
private void InitData()
|
||
{
|
||
// step #0 找到labellist列表对象,找到content对象
|
||
|
||
_versionLabelList = UIObject.transform.Find("VersionLabelList/Viewport/Content");
|
||
_versionContent = UIObject.transform.Find("VersionContent/Viewport/Content");
|
||
|
||
|
||
// 健壮性检查
|
||
if (_versionLabelList == null)
|
||
{
|
||
Debug.LogError("BoardingUI: Can't find 'VersionLabelList/Viewport/Content' object.");
|
||
return;
|
||
}
|
||
if (_versionContent == null)
|
||
{
|
||
Debug.LogError("BoardingUI: Can't find 'VersionContent/Viewport/Content' object.");
|
||
return;
|
||
}
|
||
|
||
// 新增:在Content中找到用于显示描述的TextMeshProUGUI组件
|
||
_versionDescriptionText = _versionContent.GetComponentInChildren<TextMeshProUGUI>();
|
||
if (_versionDescriptionText == null)
|
||
{
|
||
Debug.LogError("BoardingUI: Can't find TextMeshProUGUI component in children of 'VersionContent'.");
|
||
return;
|
||
}
|
||
|
||
|
||
// step #1 清空versionLabelList (使用更安全的方式清空)
|
||
for (int i = _versionLabelList.childCount - 1; i >= 0; i--)
|
||
{
|
||
GameObject.Destroy(_versionLabelList.GetChild(i).gameObject);
|
||
}
|
||
|
||
// step #2 获取数据和预制体
|
||
var pref = Resources.Load<GameObject>("Prefab/UI/VersionLabelListItem");
|
||
if (pref == null)
|
||
{
|
||
Debug.LogError("BoardingUI: Failed to load prefab 'Prefab/UI/VersionLabelListItem'");
|
||
return;
|
||
}
|
||
var vers = ConfigManager.Instance.VersionCfg.Versions;
|
||
|
||
// 如果没有任何版本信息,则清空描述并返回
|
||
if (vers == null || vers.Count == 0)
|
||
{
|
||
UpdateContent(null); // 清空右侧内容
|
||
return;
|
||
}
|
||
|
||
// 新增:创建一个变量,用于存储第一个需要被选中的按钮
|
||
Button firstButtonToSelect = null;
|
||
// step #3 新建每一个versionlabel,绑定点击事件
|
||
for (int i = vers.Count - 1; i >= 0; i--)
|
||
{
|
||
// 【重要】捕获当前循环的变量,防止C#闭包陷阱
|
||
var versionInfo = vers[i];
|
||
|
||
GameObject instance = GameObject.Instantiate(pref, _versionLabelList);
|
||
var versionLabelMono = instance.GetComponent<VersionLabelMono>();
|
||
var txt = instance.transform.Find("Text")?.GetComponent<TextMeshProUGUI>();
|
||
|
||
// 新增:获取按钮组件并绑定事件
|
||
var button = instance.GetComponent<Button>();
|
||
|
||
if (versionLabelMono == null || txt == null || button == null)
|
||
{
|
||
Debug.LogError($"Prefab 'VersionLabelListItem' is incomplete. Check for VersionLabelMono, Text child, and Button component on instance {instance.name}", instance);
|
||
continue; // 跳过这个不完整的项
|
||
}
|
||
|
||
versionLabelMono.VersionId = versionInfo.VersionId;
|
||
|
||
// 使用字符串插值,代码更清晰
|
||
txt.text = $"Demo V{versionInfo.MajorVersion}.{versionInfo.MinorVersion}.{versionInfo.PatchVersion}";
|
||
|
||
// 为按钮添加点击监听器
|
||
button.onClick.AddListener(() =>
|
||
{
|
||
// 当按钮被点击时,调用UpdateContent方法,并传入这个按钮对应的versionInfo
|
||
UpdateContent(versionInfo);
|
||
});
|
||
|
||
// 默认选中第一个生成的标签(即最新的版本)
|
||
if (i == 0)
|
||
{
|
||
UpdateContent(versionInfo);
|
||
firstButtonToSelect = button; // 记录下这个按钮
|
||
}
|
||
|
||
|
||
// 新增:在所有标签都创建完毕后,正式设置选中状态
|
||
if (firstButtonToSelect != null && EventSystem.current != null)
|
||
{
|
||
// 使用EventSystem来程序化地“选中”一个UI元素
|
||
// 这会触发按钮的 "Selected" 状态,显示高亮颜色或更换图片
|
||
EventSystem.current.SetSelectedGameObject(firstButtonToSelect.gameObject);
|
||
}
|
||
|
||
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据传入的VersionInfo更新右侧内容面板
|
||
/// </summary>
|
||
/// <param name="info">版本信息,如果为null,则清空内容</param>
|
||
private void UpdateContent(VersionInfo info)
|
||
{
|
||
if (_versionDescriptionText == null) return;
|
||
|
||
if (info != null)
|
||
{
|
||
// 将描述信息设置到文本组件上
|
||
MultilingualManager.Instance.SetUIText(_versionDescriptionText,info.Description); // 假设字段名为 Description
|
||
}
|
||
else
|
||
{
|
||
// 如果没有信息传入,则显示空或默认提示
|
||
_versionDescriptionText.text = "No version selected.";
|
||
}
|
||
// --- 就下面这两行 ---
|
||
// 步骤1: 强制刷新Content的布局,确保获取到正确的高度
|
||
LayoutRebuilder.ForceRebuildLayoutImmediate(_versionContent.GetComponent<RectTransform>());
|
||
|
||
// 步骤2: 将滚动位置设置到最顶部 (1 = Top, 0.5 = Center, 0 = Bottom)
|
||
UIObject.transform.Find("VersionContent").GetComponent<ScrollRect>().verticalNormalizedPosition = 1f;
|
||
}
|
||
}
|
||
}
|