TMP_InputFieldActionBar.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. using TMPro;
  2. using UnityEngine;
  3. using UnityEngine.Serialization;
  4. using UnityEngine.UI;
  5. namespace AppUI.Util.Input
  6. {
  7. /// <summary>
  8. /// 挂在包含 <see cref="TMP_InputField"/> 的物体上(可与输入框同物体或手动引用)。
  9. /// 绑定清空按钮与密码可见切换按钮;可选为按钮上的 Graphic 设置「两种状态」自定义颜色。
  10. /// </summary>
  11. [DisallowMultipleComponent]
  12. public class TMP_InputFieldActionBar : MonoBehaviour
  13. {
  14. [Header("输入框")]
  15. [SerializeField]
  16. TMP_InputField inputField;
  17. [Header("清空")]
  18. [SerializeField]
  19. Button clearButton;
  20. [Tooltip("用于变色:可为按钮子物体上的 Image / RawImage 等;不填则尝试用 Button.targetGraphic")]
  21. [SerializeField]
  22. Graphic clearTintTarget;
  23. [SerializeField]
  24. bool clearUseTwoColors = true;
  25. [SerializeField]
  26. Color clearWhenEmptyColor = new Color(1f, 1f, 1f, 0.35f);
  27. [SerializeField]
  28. Color clearWhenHasTextColor = Color.white;
  29. [FormerlySerializedAs("hideClearButtonWhenEmpty")]
  30. [SerializeField]
  31. bool hideClearWhenEmpty;
  32. [Header("密码显示/隐藏")]
  33. [SerializeField]
  34. Button passwordToggleButton;
  35. [Tooltip("用于变色:不填则尝试用 Button.targetGraphic")]
  36. [SerializeField]
  37. Graphic passwordTintTarget;
  38. [SerializeField]
  39. bool passwordUseTwoColors = true;
  40. [SerializeField]
  41. Color passwordConcealedColor = Color.white;
  42. [SerializeField]
  43. Color passwordRevealedColor = new Color(0.4f, 0.75f, 1f, 1f);
  44. [Tooltip("绑定密码切换按钮时:进入界面是否强制为密文(默认隐藏密码)。关闭则可沿用输入框上原有的 Content Type")]
  45. [SerializeField]
  46. bool passwordStartsConcealed = true;
  47. bool _passwordRevealed;
  48. void Awake()
  49. {
  50. if (inputField == null)
  51. inputField = GetComponent<TMP_InputField>();
  52. }
  53. void OnEnable()
  54. {
  55. if (inputField != null)
  56. inputField.onValueChanged.AddListener(OnInputValueChanged);
  57. if (clearButton != null)
  58. clearButton.onClick.AddListener(OnClearClicked);
  59. if (passwordToggleButton != null)
  60. passwordToggleButton.onClick.AddListener(OnPasswordToggleClicked);
  61. ApplyPasswordInitialState();
  62. RefreshClearUi();
  63. RefreshPasswordTint();
  64. }
  65. void OnDisable()
  66. {
  67. if (inputField != null)
  68. inputField.onValueChanged.RemoveListener(OnInputValueChanged);
  69. if (clearButton != null)
  70. clearButton.onClick.RemoveListener(OnClearClicked);
  71. if (passwordToggleButton != null)
  72. passwordToggleButton.onClick.RemoveListener(OnPasswordToggleClicked);
  73. }
  74. void OnInputValueChanged(string _)
  75. {
  76. RefreshClearUi();
  77. }
  78. void OnClearClicked()
  79. {
  80. if (inputField == null)
  81. return;
  82. inputField.text = string.Empty;
  83. inputField.ActivateInputField();
  84. RefreshClearUi();
  85. }
  86. void OnPasswordToggleClicked()
  87. {
  88. if (inputField == null || passwordToggleButton == null)
  89. return;
  90. _passwordRevealed = !_passwordRevealed;
  91. ApplyPasswordContentType();
  92. inputField.ForceLabelUpdate();
  93. RefreshPasswordTint();
  94. }
  95. void ApplyPasswordInitialState()
  96. {
  97. if (inputField == null)
  98. return;
  99. if (passwordToggleButton == null)
  100. return;
  101. if (passwordStartsConcealed)
  102. {
  103. _passwordRevealed = false;
  104. ApplyPasswordContentType();
  105. inputField.ForceLabelUpdate();
  106. }
  107. else
  108. SyncPasswordStateFromField();
  109. }
  110. void SyncPasswordStateFromField()
  111. {
  112. if (inputField == null)
  113. return;
  114. _passwordRevealed = inputField.contentType != TMP_InputField.ContentType.Password;
  115. }
  116. void ApplyPasswordContentType()
  117. {
  118. inputField.contentType = _passwordRevealed
  119. ? TMP_InputField.ContentType.Standard
  120. : TMP_InputField.ContentType.Password;
  121. }
  122. void RefreshClearUi()
  123. {
  124. if (inputField == null)
  125. return;
  126. bool hasText = !string.IsNullOrEmpty(inputField.text);
  127. if (hideClearWhenEmpty && clearButton != null)
  128. clearButton.gameObject.SetActive(hasText);
  129. if (clearUseTwoColors)
  130. ApplyTint(GetClearTintGraphic(), hasText ? clearWhenHasTextColor : clearWhenEmptyColor);
  131. }
  132. void RefreshPasswordTint()
  133. {
  134. if (!passwordUseTwoColors || passwordToggleButton == null)
  135. return;
  136. ApplyTint(GetPasswordTintGraphic(), _passwordRevealed ? passwordRevealedColor : passwordConcealedColor);
  137. }
  138. Graphic GetClearTintGraphic()
  139. {
  140. if (clearTintTarget != null)
  141. return clearTintTarget;
  142. return clearButton != null ? clearButton.targetGraphic : null;
  143. }
  144. Graphic GetPasswordTintGraphic()
  145. {
  146. if (passwordTintTarget != null)
  147. return passwordTintTarget;
  148. return passwordToggleButton != null ? passwordToggleButton.targetGraphic : null;
  149. }
  150. static void ApplyTint(Graphic g, Color c)
  151. {
  152. if (g != null)
  153. g.color = c;
  154. }
  155. #if UNITY_EDITOR
  156. void OnValidate()
  157. {
  158. if (inputField == null)
  159. inputField = GetComponent<TMP_InputField>();
  160. }
  161. #endif
  162. }
  163. }