using AppUI.Manager.View; using DG.Tweening; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; namespace AppUI.View.Component { /// /// 横版 ModuleView:节点在预制体 Inspector 中拖拽绑定。 /// 弹出与关闭参考 的 Tip:Frame 缩放进入,按钮点击后缩放消失再销毁。 /// public class ModuleViewHorizontal : MonoBehaviour { const float PopInDuration = 0.25f; const float PopOutDuration = 0.3f; [Header("布局节点")] [SerializeField] RectTransform frame; [Header("正文")] [SerializeField] TMP_Text contentTextTmp; [SerializeField] Text contentTextLegacy; [Header("按钮")] [SerializeField] Button btnReject; [SerializeField] TMP_Text btnRejectLabel; [SerializeField] Button btnAgree; [SerializeField] TMP_Text btnAgreeLabel; public string text; public string textKey; public object[] textFormatArgs = { }; public UnityAction onAgree; public string onAgreeTextKey; public UnityAction onReject; public string onRejectTextKey; /// 为 true(默认)时,点击按钮会先播放收起动画再销毁自身。 public bool willDestroyAfterClick = true; bool _dismissing; Tween _popTween; public static ModuleViewHorizontal Show() { ViewConfig viewConfig = ViewManager.GetConfig(UIPrefabType.ModuleViewHorizontal); GameObject o = Instantiate(Resources.Load(viewConfig.path)); var view = o.GetComponent(); if (view == null) view = o.AddComponent(); return view; } void OnDestroy() { _popTween?.Kill(); transform.DOKill(true); } void Start() { SetupRejectButton(); BindContentText(); BindAgreeButton(); TrySetButtonLabelKey(btnAgreeLabel, onAgreeTextKey); TrySetButtonLabelKey(btnRejectLabel, onRejectTextKey); if (frame != null) LayoutRebuilder.ForceRebuildLayoutImmediate(frame); PlayPopIn(); } /// 未设置拒绝回调且无拒绝文案 key 时隐藏拒绝按钮。 void SetupRejectButton() { if (btnReject == null) return; bool showReject = onReject != null || !string.IsNullOrEmpty(onRejectTextKey); btnReject.gameObject.SetActive(showReject); if (!showReject) return; btnReject.onClick.AddListener(OnRejectClicked); } void PlayPopIn() { if (frame == null) return; frame.DOKill(); frame.localScale = Vector3.zero; _popTween = frame .DOScale(1f, PopInDuration) .SetEase(Ease.OutBack) .SetUpdate(true); } /// 缩放 Frame 后销毁(不再次触发按钮回调)。 public void CloseWithTween() { if (_dismissing) return; if (!willDestroyAfterClick) return; _dismissing = true; PlayPopOutAndDestroy(); } void BindAgreeButton() { if (btnAgree == null) return; btnAgree.onClick.AddListener(OnAgreeClicked); } void OnAgreeClicked() { if (_dismissing) return; onAgree?.Invoke(); if (!willDestroyAfterClick) return; _dismissing = true; PlayPopOutAndDestroy(); } void OnRejectClicked() { if (_dismissing) return; onReject?.Invoke(); if (!willDestroyAfterClick) return; _dismissing = true; PlayPopOutAndDestroy(); } void PlayPopOutAndDestroy() { SetButtonsInteractable(false); if (frame == null) { Destroy(gameObject); return; } _popTween?.Kill(); frame.DOKill(); _popTween = frame .DOScale(0f, PopOutDuration) .SetEase(Ease.InBack) .SetUpdate(true) .OnComplete(() => Destroy(gameObject)); } void SetButtonsInteractable(bool interactable) { if (btnAgree != null) btnAgree.interactable = interactable; if (btnReject != null) btnReject.interactable = interactable; } void BindContentText() { if (contentTextTmp != null) { if (!string.IsNullOrEmpty(textKey)) { var t2 = contentTextTmp.GetComponent(); if (t2 == null) t2 = contentTextTmp.gameObject.AddComponent(); t2.textFormatArgs = textFormatArgs; t2.SetTextKey(textKey); } else { contentTextTmp.text = text ?? string.Empty; } return; } if (contentTextLegacy == null) return; if (!string.IsNullOrEmpty(textKey)) { var t2 = contentTextLegacy.GetComponent(); if (t2 == null) t2 = contentTextLegacy.gameObject.AddComponent(); t2.textFormatArgs = textFormatArgs; t2.SetTextKey(textKey); } else { contentTextLegacy.text = text ?? string.Empty; } } static void TrySetButtonLabelKey(TMP_Text label, string key) { if (label == null || string.IsNullOrEmpty(key)) return; var t2 = label.GetComponent(); if (t2 == null) t2 = label.gameObject.AddComponent(); t2.SetTextKey(key); } } }