ModuleViewHorizontal.cs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. using AppUI.Manager.View;
  2. using DG.Tweening;
  3. using TMPro;
  4. using UnityEngine;
  5. using UnityEngine.Events;
  6. using UnityEngine.UI;
  7. namespace AppUI.View.Component
  8. {
  9. /// <summary>
  10. /// 横版 ModuleView:节点在预制体 Inspector 中拖拽绑定。
  11. /// 弹出与关闭参考 <see cref="PopupMgr"/> 的 Tip:Frame 缩放进入,按钮点击后缩放消失再销毁。
  12. /// </summary>
  13. public class ModuleViewHorizontal : MonoBehaviour
  14. {
  15. const float PopInDuration = 0.25f;
  16. const float PopOutDuration = 0.3f;
  17. [Header("布局节点")]
  18. [SerializeField]
  19. RectTransform frame;
  20. [Header("正文")]
  21. [SerializeField]
  22. TMP_Text contentTextTmp;
  23. [SerializeField]
  24. Text contentTextLegacy;
  25. [Header("按钮")]
  26. [SerializeField]
  27. Button btnReject;
  28. [SerializeField]
  29. TMP_Text btnRejectLabel;
  30. [SerializeField]
  31. Button btnAgree;
  32. [SerializeField]
  33. TMP_Text btnAgreeLabel;
  34. public string text;
  35. public string textKey;
  36. public object[] textFormatArgs = { };
  37. public UnityAction onAgree;
  38. public string onAgreeTextKey;
  39. public UnityAction onReject;
  40. public string onRejectTextKey;
  41. /// <summary>为 true(默认)时,点击按钮会先播放收起动画再销毁自身。</summary>
  42. public bool willDestroyAfterClick = true;
  43. bool _dismissing;
  44. Tween _popTween;
  45. public static ModuleViewHorizontal Show()
  46. {
  47. ViewConfig viewConfig = ViewManager.GetConfig(UIPrefabType.ModuleViewHorizontal);
  48. GameObject o = Instantiate(Resources.Load<GameObject>(viewConfig.path));
  49. var view = o.GetComponent<ModuleViewHorizontal>();
  50. if (view == null)
  51. view = o.AddComponent<ModuleViewHorizontal>();
  52. return view;
  53. }
  54. void OnDestroy()
  55. {
  56. _popTween?.Kill();
  57. transform.DOKill(true);
  58. }
  59. void Start()
  60. {
  61. SetupRejectButton();
  62. BindContentText();
  63. BindAgreeButton();
  64. TrySetButtonLabelKey(btnAgreeLabel, onAgreeTextKey);
  65. TrySetButtonLabelKey(btnRejectLabel, onRejectTextKey);
  66. if (frame != null)
  67. LayoutRebuilder.ForceRebuildLayoutImmediate(frame);
  68. PlayPopIn();
  69. }
  70. /// <summary>未设置拒绝回调且无拒绝文案 key 时隐藏拒绝按钮。</summary>
  71. void SetupRejectButton()
  72. {
  73. if (btnReject == null)
  74. return;
  75. bool showReject = onReject != null || !string.IsNullOrEmpty(onRejectTextKey);
  76. btnReject.gameObject.SetActive(showReject);
  77. if (!showReject)
  78. return;
  79. btnReject.onClick.AddListener(OnRejectClicked);
  80. }
  81. void PlayPopIn()
  82. {
  83. if (frame == null)
  84. return;
  85. frame.DOKill();
  86. frame.localScale = Vector3.zero;
  87. _popTween = frame
  88. .DOScale(1f, PopInDuration)
  89. .SetEase(Ease.OutBack)
  90. .SetUpdate(true);
  91. }
  92. /// <summary>缩放 Frame 后销毁(不再次触发按钮回调)。</summary>
  93. public void CloseWithTween()
  94. {
  95. if (_dismissing)
  96. return;
  97. if (!willDestroyAfterClick)
  98. return;
  99. _dismissing = true;
  100. PlayPopOutAndDestroy();
  101. }
  102. void BindAgreeButton()
  103. {
  104. if (btnAgree == null)
  105. return;
  106. btnAgree.onClick.AddListener(OnAgreeClicked);
  107. }
  108. void OnAgreeClicked()
  109. {
  110. if (_dismissing)
  111. return;
  112. onAgree?.Invoke();
  113. if (!willDestroyAfterClick)
  114. return;
  115. _dismissing = true;
  116. PlayPopOutAndDestroy();
  117. }
  118. void OnRejectClicked()
  119. {
  120. if (_dismissing)
  121. return;
  122. onReject?.Invoke();
  123. if (!willDestroyAfterClick)
  124. return;
  125. _dismissing = true;
  126. PlayPopOutAndDestroy();
  127. }
  128. void PlayPopOutAndDestroy()
  129. {
  130. SetButtonsInteractable(false);
  131. if (frame == null)
  132. {
  133. Destroy(gameObject);
  134. return;
  135. }
  136. _popTween?.Kill();
  137. frame.DOKill();
  138. _popTween = frame
  139. .DOScale(0f, PopOutDuration)
  140. .SetEase(Ease.InBack)
  141. .SetUpdate(true)
  142. .OnComplete(() => Destroy(gameObject));
  143. }
  144. void SetButtonsInteractable(bool interactable)
  145. {
  146. if (btnAgree != null)
  147. btnAgree.interactable = interactable;
  148. if (btnReject != null)
  149. btnReject.interactable = interactable;
  150. }
  151. void BindContentText()
  152. {
  153. if (contentTextTmp != null)
  154. {
  155. if (!string.IsNullOrEmpty(textKey))
  156. {
  157. var t2 = contentTextTmp.GetComponent<AppUITextAutoLanguage>();
  158. if (t2 == null)
  159. t2 = contentTextTmp.gameObject.AddComponent<AppUITextAutoLanguage>();
  160. t2.textFormatArgs = textFormatArgs;
  161. t2.SetTextKey(textKey);
  162. }
  163. else
  164. {
  165. contentTextTmp.text = text ?? string.Empty;
  166. }
  167. return;
  168. }
  169. if (contentTextLegacy == null)
  170. return;
  171. if (!string.IsNullOrEmpty(textKey))
  172. {
  173. var t2 = contentTextLegacy.GetComponent<AppUITextAutoLanguage>();
  174. if (t2 == null)
  175. t2 = contentTextLegacy.gameObject.AddComponent<AppUITextAutoLanguage>();
  176. t2.textFormatArgs = textFormatArgs;
  177. t2.SetTextKey(textKey);
  178. }
  179. else
  180. {
  181. contentTextLegacy.text = text ?? string.Empty;
  182. }
  183. }
  184. static void TrySetButtonLabelKey(TMP_Text label, string key)
  185. {
  186. if (label == null || string.IsNullOrEmpty(key))
  187. return;
  188. var t2 = label.GetComponent<AppUITextAutoLanguage>();
  189. if (t2 == null)
  190. t2 = label.gameObject.AddComponent<AppUITextAutoLanguage>();
  191. t2.SetTextKey(key);
  192. }
  193. }
  194. }