297 lines
9.7 KiB
C#
297 lines
9.7 KiB
C#
using System;
|
||
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
using TMPro;
|
||
|
||
namespace DefaultNamespace.Component
|
||
{
|
||
/// <summary>
|
||
/// 自动调整Image高度的组件
|
||
/// 监听子对象中的TMP_Text组件,根据文本高度自动调整Image的高度
|
||
/// </summary>
|
||
public class AutoResizeImage : MonoBehaviour
|
||
{
|
||
[Header("UI组件引用")]
|
||
[SerializeField] private Image targetImage; // 目标Image组件
|
||
[SerializeField] private TMP_Text targetText; // 目标TMP_Text组件
|
||
|
||
[Header("高度调整设置")]
|
||
[SerializeField] private float topPadding = 10f; // 顶部边距
|
||
[SerializeField] private float bottomPadding = 10f; // 底部边距
|
||
[SerializeField] private float minHeight = 50f; // 最小高度
|
||
[SerializeField] private bool enableDebugLog = true; // 是否启用调试日志
|
||
|
||
[Header("更新设置")]
|
||
[SerializeField] private bool updateOnStart = true; // 启动时是否更新
|
||
[SerializeField] private bool updateOnTextChange = true; // 文本变化时是否更新
|
||
|
||
// 私有字段
|
||
private RectTransform imageRectTransform; // Image的RectTransform引用
|
||
private RectTransform textRectTransform; // Text的RectTransform引用
|
||
private float lastTextHeight = -1f; // 上次的文本高度,用于避免重复更新
|
||
|
||
/// <summary>
|
||
/// 初始化组件
|
||
/// </summary>
|
||
private void Awake()
|
||
{
|
||
InitializeComponents();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 组件启用时的处理
|
||
/// </summary>
|
||
private void OnEnable()
|
||
{
|
||
RegisterTextEvents();
|
||
|
||
if (updateOnStart)
|
||
{
|
||
// 延迟一帧更新,确保所有组件都已初始化
|
||
Invoke(nameof(UpdateImageHeight), 0.1f);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 组件禁用时的处理
|
||
/// </summary>
|
||
private void OnDisable()
|
||
{
|
||
UnregisterTextEvents();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 初始化组件引用
|
||
/// </summary>
|
||
private void InitializeComponents()
|
||
{
|
||
try
|
||
{
|
||
// 获取Image组件
|
||
if (targetImage == null)
|
||
{
|
||
targetImage = GetComponent<Image>();
|
||
if (targetImage == null)
|
||
{
|
||
LogDebug("未找到Image组件,请手动指定或确保脚本挂载在Image对象上");
|
||
return;
|
||
}
|
||
}
|
||
|
||
imageRectTransform = targetImage.GetComponent<RectTransform>();
|
||
if (imageRectTransform == null)
|
||
{
|
||
LogDebug("Image组件没有RectTransform,无法调整高度");
|
||
return;
|
||
}
|
||
|
||
// 获取TMP_Text组件
|
||
if (targetText == null)
|
||
{
|
||
targetText = GetComponentInChildren<TMP_Text>();
|
||
if (targetText == null)
|
||
{
|
||
LogDebug("未找到TMP_Text组件,请手动指定或确保子对象中有TMP_Text组件");
|
||
return;
|
||
}
|
||
}
|
||
|
||
textRectTransform = targetText.GetComponent<RectTransform>();
|
||
if (textRectTransform == null)
|
||
{
|
||
LogDebug("TMP_Text组件没有RectTransform,无法获取高度");
|
||
return;
|
||
}
|
||
|
||
LogDebug("组件初始化完成");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogDebug($"初始化组件时发生异常: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 注册文本变化事件
|
||
/// </summary>
|
||
private void RegisterTextEvents()
|
||
{
|
||
try
|
||
{
|
||
if (targetText != null && updateOnTextChange)
|
||
{
|
||
// 监听文本变化事件
|
||
targetText.RegisterDirtyVerticesCallback(OnTextChanged);
|
||
LogDebug("文本变化事件已注册");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogDebug($"注册文本事件时发生异常: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 取消注册文本变化事件
|
||
/// </summary>
|
||
private void UnregisterTextEvents()
|
||
{
|
||
try
|
||
{
|
||
if (targetText != null)
|
||
{
|
||
targetText.UnregisterDirtyVerticesCallback(OnTextChanged);
|
||
LogDebug("文本变化事件已取消注册");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogDebug($"取消注册文本事件时发生异常: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 文本变化时的回调
|
||
/// </summary>
|
||
private void OnTextChanged()
|
||
{
|
||
if (updateOnTextChange)
|
||
{
|
||
UpdateImageHeight();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新Image高度
|
||
/// </summary>
|
||
public void UpdateImageHeight()
|
||
{
|
||
try
|
||
{
|
||
if (imageRectTransform == null || textRectTransform == null)
|
||
{
|
||
LogDebug("RectTransform引用为空,无法更新高度");
|
||
return;
|
||
}
|
||
|
||
// 强制更新文本布局
|
||
Canvas.ForceUpdateCanvases();
|
||
|
||
// 获取文本的实际高度
|
||
float textHeight = GetTextHeight();
|
||
|
||
// 检查是否需要更新
|
||
if (Mathf.Abs(textHeight - lastTextHeight) < 0.1f)
|
||
{
|
||
LogDebug($"文本高度未变化 ({textHeight:F2}),跳过更新");
|
||
return;
|
||
}
|
||
|
||
// 计算新的Image高度
|
||
float newHeight = textHeight + topPadding + bottomPadding;
|
||
newHeight = Mathf.Max(newHeight, minHeight);
|
||
|
||
// 更新Image高度
|
||
Vector2 sizeDelta = imageRectTransform.sizeDelta;
|
||
sizeDelta.y = newHeight;
|
||
imageRectTransform.sizeDelta = sizeDelta;
|
||
|
||
lastTextHeight = textHeight;
|
||
|
||
LogDebug($"Image高度已更新: {newHeight:F2} (文本高度: {textHeight:F2}, 边距: {topPadding + bottomPadding:F2})");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogDebug($"更新Image高度时发生异常: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取文本的实际高度
|
||
/// </summary>
|
||
/// <returns>文本高度</returns>
|
||
private float GetTextHeight()
|
||
{
|
||
try
|
||
{
|
||
if (targetText == null)
|
||
{
|
||
LogDebug("TMP_Text组件为空");
|
||
return 0f;
|
||
}
|
||
|
||
// 强制重新计算文本布局
|
||
targetText.ForceMeshUpdate();
|
||
|
||
// 获取文本的实际高度
|
||
float textHeight = targetText.preferredHeight;
|
||
|
||
LogDebug($"获取到文本高度: {textHeight:F2}");
|
||
return textHeight;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogDebug($"获取文本高度时发生异常: {ex.Message}");
|
||
return 0f;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 记录调试日志
|
||
/// </summary>
|
||
/// <param name="message">日志消息</param>
|
||
private void LogDebug(string message)
|
||
{
|
||
if (enableDebugLog)
|
||
{
|
||
Debug.Log($"[AutoResizeImage] {message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 手动设置目标组件(供外部调用)
|
||
/// </summary>
|
||
/// <param name="image">目标Image组件</param>
|
||
/// <param name="text">目标TMP_Text组件</param>
|
||
public void SetTargetComponents(Image image, TMP_Text text)
|
||
{
|
||
targetImage = image;
|
||
targetText = text;
|
||
InitializeComponents();
|
||
LogDebug("目标组件已手动设置");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置边距参数
|
||
/// </summary>
|
||
/// <param name="top">顶部边距</param>
|
||
/// <param name="bottom">底部边距</param>
|
||
public void SetPadding(float top, float bottom)
|
||
{
|
||
topPadding = top;
|
||
bottomPadding = bottom;
|
||
LogDebug($"边距已设置: 顶部={top}, 底部={bottom}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置最小高度
|
||
/// </summary>
|
||
/// <param name="minHeight">最小高度</param>
|
||
public void SetMinHeight(float minHeight)
|
||
{
|
||
this.minHeight = minHeight;
|
||
LogDebug($"最小高度已设置: {minHeight}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 启用或禁用调试日志
|
||
/// </summary>
|
||
/// <param name="enable">是否启用</param>
|
||
public void SetDebugLog(bool enable)
|
||
{
|
||
enableDebugLog = enable;
|
||
LogDebug($"调试日志已{(enable ? "启用" : "禁用")}");
|
||
}
|
||
}
|
||
}
|