using TMPro; using UnityEngine; using UnityEngine.Serialization; using UnityEngine.UI; namespace AppUI.Util.Input { /// /// 挂在包含 的物体上(可与输入框同物体或手动引用)。 /// 绑定清空按钮与密码可见切换按钮;可选为按钮上的 Graphic 设置「两种状态」自定义颜色。 /// [DisallowMultipleComponent] public class TMP_InputFieldActionBar : MonoBehaviour { [Header("输入框")] [SerializeField] TMP_InputField inputField; [Header("清空")] [SerializeField] Button clearButton; [Tooltip("用于变色:可为按钮子物体上的 Image / RawImage 等;不填则尝试用 Button.targetGraphic")] [SerializeField] Graphic clearTintTarget; [SerializeField] bool clearUseTwoColors = true; [SerializeField] Color clearWhenEmptyColor = new Color(1f, 1f, 1f, 0.35f); [SerializeField] Color clearWhenHasTextColor = Color.white; [FormerlySerializedAs("hideClearButtonWhenEmpty")] [SerializeField] bool hideClearWhenEmpty; [Header("密码显示/隐藏")] [SerializeField] Button passwordToggleButton; [Tooltip("用于变色:不填则尝试用 Button.targetGraphic")] [SerializeField] Graphic passwordTintTarget; [SerializeField] bool passwordUseTwoColors = true; [SerializeField] Color passwordConcealedColor = Color.white; [SerializeField] Color passwordRevealedColor = new Color(0.4f, 0.75f, 1f, 1f); [Tooltip("绑定密码切换按钮时:进入界面是否强制为密文(默认隐藏密码)。关闭则可沿用输入框上原有的 Content Type")] [SerializeField] bool passwordStartsConcealed = true; bool _passwordRevealed; void Awake() { if (inputField == null) inputField = GetComponent(); } void OnEnable() { if (inputField != null) inputField.onValueChanged.AddListener(OnInputValueChanged); if (clearButton != null) clearButton.onClick.AddListener(OnClearClicked); if (passwordToggleButton != null) passwordToggleButton.onClick.AddListener(OnPasswordToggleClicked); ApplyPasswordInitialState(); RefreshClearUi(); RefreshPasswordTint(); } void OnDisable() { if (inputField != null) inputField.onValueChanged.RemoveListener(OnInputValueChanged); if (clearButton != null) clearButton.onClick.RemoveListener(OnClearClicked); if (passwordToggleButton != null) passwordToggleButton.onClick.RemoveListener(OnPasswordToggleClicked); } void OnInputValueChanged(string _) { RefreshClearUi(); } void OnClearClicked() { if (inputField == null) return; inputField.text = string.Empty; inputField.ActivateInputField(); RefreshClearUi(); } void OnPasswordToggleClicked() { if (inputField == null || passwordToggleButton == null) return; _passwordRevealed = !_passwordRevealed; ApplyPasswordContentType(); inputField.ForceLabelUpdate(); RefreshPasswordTint(); } void ApplyPasswordInitialState() { if (inputField == null) return; if (passwordToggleButton == null) return; if (passwordStartsConcealed) { _passwordRevealed = false; ApplyPasswordContentType(); inputField.ForceLabelUpdate(); } else SyncPasswordStateFromField(); } void SyncPasswordStateFromField() { if (inputField == null) return; _passwordRevealed = inputField.contentType != TMP_InputField.ContentType.Password; } void ApplyPasswordContentType() { inputField.contentType = _passwordRevealed ? TMP_InputField.ContentType.Standard : TMP_InputField.ContentType.Password; } void RefreshClearUi() { if (inputField == null) return; bool hasText = !string.IsNullOrEmpty(inputField.text); if (hideClearWhenEmpty && clearButton != null) clearButton.gameObject.SetActive(hasText); if (clearUseTwoColors) ApplyTint(GetClearTintGraphic(), hasText ? clearWhenHasTextColor : clearWhenEmptyColor); } void RefreshPasswordTint() { if (!passwordUseTwoColors || passwordToggleButton == null) return; ApplyTint(GetPasswordTintGraphic(), _passwordRevealed ? passwordRevealedColor : passwordConcealedColor); } Graphic GetClearTintGraphic() { if (clearTintTarget != null) return clearTintTarget; return clearButton != null ? clearButton.targetGraphic : null; } Graphic GetPasswordTintGraphic() { if (passwordTintTarget != null) return passwordTintTarget; return passwordToggleButton != null ? passwordToggleButton.targetGraphic : null; } static void ApplyTint(Graphic g, Color c) { if (g != null) g.color = c; } #if UNITY_EDITOR void OnValidate() { if (inputField == null) inputField = GetComponent(); } #endif } }