WX-Game1/Assets/Scripts/Component/AutoResizeImage.cs

297 lines
9.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 ? "" : "")}");
}
}
}