323 lines
11 KiB
C#
323 lines
11 KiB
C#
|
|
using System;
|
|||
|
|
using TMPro;
|
|||
|
|
using UnityEngine;
|
|||
|
|
using UnityEngine.UI;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 输入对话框
|
|||
|
|
/// 用于获取用户输入的通用对话框
|
|||
|
|
// // 弹出输入新密码的对话框
|
|||
|
|
// 使用方法:
|
|||
|
|
// InputDialog.Show("重置密码",
|
|||
|
|
// $"请为用户 '{username}' 输入新密码:",
|
|||
|
|
// "新密码",
|
|||
|
|
// (newPassword) => ResetPassword(username, newPassword),
|
|||
|
|
// null, true); // 密码模式
|
|||
|
|
/// </summary>
|
|||
|
|
public class InputDialog : BasePanel
|
|||
|
|
{
|
|||
|
|
[Header("UI组件")]
|
|||
|
|
public TextMeshProUGUI TitleText;
|
|||
|
|
public TextMeshProUGUI MessageText;
|
|||
|
|
public TMP_InputField InputField;
|
|||
|
|
public Button ConfirmButton;
|
|||
|
|
public Button CancelButton;
|
|||
|
|
// public GameObject DialogPanel;
|
|||
|
|
|
|||
|
|
[Header("自定义键盘(可选)")]
|
|||
|
|
public GameObject CustomKeyboardPanel; // 自定义键盘面板(如果为空则动态创建)
|
|||
|
|
// public TextMeshProUGUI DisplayText; // 显示当前输入的文本
|
|||
|
|
public KeyboardLayout KeyboardType = KeyboardLayout.Default;
|
|||
|
|
[Tooltip("如果使用动态键盘,此为键盘面板放置的父物体(例如对话框的主 Panel)")]
|
|||
|
|
public Transform KeyboardPanelParent; // 键盘面板的父物体,用于动态创建
|
|||
|
|
|
|||
|
|
private Action<string> _onConfirm;
|
|||
|
|
private Action _onCancel;
|
|||
|
|
private bool _isPasswordMode;
|
|||
|
|
private string _currentInput = ""; // 当前输入内容
|
|||
|
|
private bool _useCustomKeyboard = false; // 是否使用自定义键盘
|
|||
|
|
private CustomKeyboard _dynamicKeyboard; // 运行时创建的键盘脚本
|
|||
|
|
|
|||
|
|
// private static InputDialog _instance;
|
|||
|
|
|
|||
|
|
public override void Init()
|
|||
|
|
{
|
|||
|
|
InitializeButtons();
|
|||
|
|
// HideDialog();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
protected override void Awake()
|
|||
|
|
{
|
|||
|
|
base.Awake();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void InitializeButtons()
|
|||
|
|
{
|
|||
|
|
// 确保对话框初始状态为隐藏
|
|||
|
|
// if (DialogPanel != null)
|
|||
|
|
// {
|
|||
|
|
// DialogPanel.SetActive(false);
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
// 设置按钮事件
|
|||
|
|
if (ConfirmButton != null)
|
|||
|
|
{
|
|||
|
|
ConfirmButton.onClick.AddListener(OnConfirmClicked);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (CancelButton != null)
|
|||
|
|
{
|
|||
|
|
CancelButton.onClick.AddListener(OnCancelClicked);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 显示输入对话框
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="title">标题</param>
|
|||
|
|
/// <param name="message">消息内容</param>
|
|||
|
|
/// <param name="placeholder">输入框占位符</param>
|
|||
|
|
/// <param name="onConfirm">确认回调</param>
|
|||
|
|
/// <param name="onCancel">取消回调</param>
|
|||
|
|
/// <param name="isPasswordMode">是否为密码模式</param>
|
|||
|
|
public static void Show(string title, string message, string placeholder,
|
|||
|
|
Action<string> onConfirm, Action onCancel = null, bool isPasswordMode = false,
|
|||
|
|
KeyboardLayout keyboardLayout = KeyboardLayout.Default)
|
|||
|
|
{
|
|||
|
|
// if (_instance == null)
|
|||
|
|
// {
|
|||
|
|
// Debug.LogError("InputDialog实例不存在");
|
|||
|
|
// return;
|
|||
|
|
// }
|
|||
|
|
var dialog = EnhancedUIManager.Instance.ShowPanel<InputDialog>(UIPanelType.Dialog, true, false);
|
|||
|
|
if(dialog != null)
|
|||
|
|
dialog.ShowDialog(title, message, placeholder, onConfirm, onCancel, isPasswordMode, keyboardLayout);
|
|||
|
|
else
|
|||
|
|
Debug.LogError("Failed to create InputDialog!");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void ShowDialog(string title, string message, string placeholder,
|
|||
|
|
Action<string> onConfirm, Action onCancel, bool isPasswordMode,
|
|||
|
|
KeyboardLayout keyboardLayout)
|
|||
|
|
{
|
|||
|
|
_onConfirm = onConfirm;
|
|||
|
|
_onCancel = onCancel;
|
|||
|
|
_isPasswordMode = isPasswordMode;
|
|||
|
|
_currentInput = placeholder ?? "";
|
|||
|
|
|
|||
|
|
// 设置文本
|
|||
|
|
if (TitleText != null) TitleText.text = title;
|
|||
|
|
if (MessageText != null) MessageText.text = message;
|
|||
|
|
|
|||
|
|
// 通用策略:如果配置了 CustomKeyboardPanel 则使用自定义键盘(跨平台),避免调出系统键盘
|
|||
|
|
// 如果 CustomKeyboardPanel 为空但 KeyboardPanelParent 已指定,则动态创建键盘
|
|||
|
|
if (CustomKeyboardPanel == null && KeyboardPanelParent != null)
|
|||
|
|
{
|
|||
|
|
CustomKeyboardPanel = CreateDynamicKeyboard();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_useCustomKeyboard = CustomKeyboardPanel != null;
|
|||
|
|
|
|||
|
|
if (_useCustomKeyboard)
|
|||
|
|
{
|
|||
|
|
// 显示自定义键盘区域
|
|||
|
|
CustomKeyboardPanel.SetActive(true);
|
|||
|
|
// 完全禁用 InputField 的交互以避免系统键盘
|
|||
|
|
if (InputField != null)
|
|||
|
|
{
|
|||
|
|
InputField.gameObject.SetActive(true);
|
|||
|
|
InputField.shouldHideMobileInput = true;
|
|||
|
|
InputField.readOnly = true; // 禁用系统输入
|
|||
|
|
InputField.interactable = false; // 禁用交互,避免触发系统键盘
|
|||
|
|
InputField.text = _currentInput;
|
|||
|
|
if (InputField.placeholder != null) InputField.placeholder.GetComponent<TextMeshProUGUI>().text = placeholder;
|
|||
|
|
// 不调用 ActivateInputField()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// if (DisplayText != null)
|
|||
|
|
// {
|
|||
|
|
// DisplayText.text = isPasswordMode ? new string('*', _currentInput.Length) : _currentInput;
|
|||
|
|
// DisplayText.gameObject.SetActive(true);
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
// 初始化 CustomKeyboard 脚本并绑定目标
|
|||
|
|
var ck = CustomKeyboardPanel.GetComponent<CustomKeyboard>();
|
|||
|
|
if (ck == null) ck = _dynamicKeyboard;
|
|||
|
|
if (ck != null)
|
|||
|
|
{
|
|||
|
|
ck.SetTarget(this, keyboardLayout, isPasswordMode);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
// 使用系统/内置 Unity 输入框,但隐藏移动端默认输入(如果需要)并激活输入框
|
|||
|
|
if (CustomKeyboardPanel != null) CustomKeyboardPanel.SetActive(false);
|
|||
|
|
|
|||
|
|
if (InputField != null)
|
|||
|
|
{
|
|||
|
|
InputField.gameObject.SetActive(true);
|
|||
|
|
InputField.shouldHideMobileInput = true;
|
|||
|
|
InputField.readOnly = false;
|
|||
|
|
InputField.text = _currentInput;
|
|||
|
|
if (InputField.placeholder != null) InputField.placeholder.GetComponent<TextMeshProUGUI>().text = placeholder;
|
|||
|
|
InputField.contentType = isPasswordMode ? TMP_InputField.ContentType.Password : TMP_InputField.ContentType.Standard;
|
|||
|
|
InputField.ActivateInputField();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 动态创建键盘面板(包含 CustomKeyboard 脚本、GridLayoutGroup 和容器)
|
|||
|
|
/// </summary>
|
|||
|
|
private GameObject CreateDynamicKeyboard()
|
|||
|
|
{
|
|||
|
|
// 创建键盘面板 GameObject
|
|||
|
|
var panelGO = new GameObject("DynamicKeyboardPanel", typeof(RectTransform));
|
|||
|
|
panelGO.transform.SetParent(KeyboardPanelParent, false);
|
|||
|
|
|
|||
|
|
var panelRT = panelGO.GetComponent<RectTransform>();
|
|||
|
|
// 设置大小和位置(可根据需要调整)
|
|||
|
|
panelRT.sizeDelta = new Vector2(1050, 300);
|
|||
|
|
panelRT.anchoredPosition = new Vector2(50, 0);
|
|||
|
|
|
|||
|
|
// 添加 Image 以显示背景(可选)
|
|||
|
|
var panelImg = panelGO.AddComponent<Image>();
|
|||
|
|
panelImg.color = new Color(0.08f, 0.1f, 0.12f, 0.95f); // 深色背景
|
|||
|
|
|
|||
|
|
// 创建容器(用于 GridLayoutGroup)
|
|||
|
|
var containerGO = new GameObject("KeysContainer", typeof(RectTransform));
|
|||
|
|
containerGO.transform.SetParent(panelGO.transform, false);
|
|||
|
|
var containerRT = containerGO.GetComponent<RectTransform>();
|
|||
|
|
containerRT.anchorMin = Vector2.zero;
|
|||
|
|
containerRT.anchorMax = Vector2.one;
|
|||
|
|
containerRT.offsetMin = new Vector2(10, 10);
|
|||
|
|
containerRT.offsetMax = new Vector2(-10, -10);
|
|||
|
|
|
|||
|
|
// 添加 GridLayoutGroup
|
|||
|
|
var grid = containerGO.AddComponent<GridLayoutGroup>();
|
|||
|
|
grid.cellSize = new Vector2(60, 60);
|
|||
|
|
grid.spacing = new Vector2(6, 6);
|
|||
|
|
|
|||
|
|
// 添加 LayoutElement 以确保 container 大小正确
|
|||
|
|
var containerLE = containerGO.AddComponent<LayoutElement>();
|
|||
|
|
containerLE.preferredWidth = 400;
|
|||
|
|
containerLE.preferredHeight = 300;
|
|||
|
|
|
|||
|
|
// 添加 CustomKeyboard 脚本
|
|||
|
|
_dynamicKeyboard = panelGO.AddComponent<CustomKeyboard>();
|
|||
|
|
_dynamicKeyboard.KeysContainer = containerGO.transform;
|
|||
|
|
_dynamicKeyboard.KeySize = new Vector2(60, 60);
|
|||
|
|
_dynamicKeyboard.KeySpacing = new Vector2(6, 6);
|
|||
|
|
|
|||
|
|
return panelGO;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void OnConfirmClicked()
|
|||
|
|
{
|
|||
|
|
// 统一使用 _currentInput,因为自定义键盘和 InputField 都已同步
|
|||
|
|
string inputValue = _useCustomKeyboard ? _currentInput : (InputField?.text ?? "");
|
|||
|
|
|
|||
|
|
_onConfirm?.Invoke(inputValue);
|
|||
|
|
HideDialog();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void OnCancelClicked()
|
|||
|
|
{
|
|||
|
|
_onCancel?.Invoke();
|
|||
|
|
HideDialog();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void HideDialog()
|
|||
|
|
{
|
|||
|
|
// 清理动态创建的键盘
|
|||
|
|
if (_dynamicKeyboard != null && CustomKeyboardPanel != null)
|
|||
|
|
{
|
|||
|
|
Destroy(CustomKeyboardPanel);
|
|||
|
|
CustomKeyboardPanel = null;
|
|||
|
|
_dynamicKeyboard = null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
EnhancedUIManager.Instance.HidePanel<InputDialog>(true);
|
|||
|
|
_onConfirm = null;
|
|||
|
|
_onCancel = null;
|
|||
|
|
_currentInput = "";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#region 自定义键盘支持方法
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 添加字符到输入内容
|
|||
|
|
/// 供自定义键盘按钮调用
|
|||
|
|
/// </summary>
|
|||
|
|
public void OnKeyPressed(string key)
|
|||
|
|
{
|
|||
|
|
if (string.IsNullOrEmpty(key)) return;
|
|||
|
|
|
|||
|
|
_currentInput += key;
|
|||
|
|
|
|||
|
|
// 同步更新 InputField(即使是只读模式,也可以通过代码修改)
|
|||
|
|
if (InputField != null)
|
|||
|
|
{
|
|||
|
|
InputField.text = _currentInput;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// UpdateDisplay();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 删除最后一个字符
|
|||
|
|
/// </summary>
|
|||
|
|
public void OnBackspacePressed()
|
|||
|
|
{
|
|||
|
|
if (_currentInput.Length > 0)
|
|||
|
|
{
|
|||
|
|
_currentInput = _currentInput.Substring(0, _currentInput.Length - 1);
|
|||
|
|
|
|||
|
|
// 同步更新 InputField
|
|||
|
|
if (InputField != null)
|
|||
|
|
{
|
|||
|
|
InputField.text = _currentInput;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// UpdateDisplay();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 清空输入
|
|||
|
|
/// </summary>
|
|||
|
|
public void OnClearPressed()
|
|||
|
|
{
|
|||
|
|
_currentInput = "";
|
|||
|
|
|
|||
|
|
// 同步更新 InputField
|
|||
|
|
if (InputField != null)
|
|||
|
|
{
|
|||
|
|
InputField.text = _currentInput;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// UpdateDisplay();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 更新显示文本
|
|||
|
|
/// </summary>
|
|||
|
|
// private void UpdateDisplay()
|
|||
|
|
// {
|
|||
|
|
// if (_useCustomKeyboard && DisplayText != null)
|
|||
|
|
// {
|
|||
|
|
// if (_isPasswordMode)
|
|||
|
|
// {
|
|||
|
|
// // 密码模式显示星号
|
|||
|
|
// DisplayText.text = new string('*', _currentInput.Length);
|
|||
|
|
// }
|
|||
|
|
// else
|
|||
|
|
// {
|
|||
|
|
// DisplayText.text = _currentInput;
|
|||
|
|
// }
|
|||
|
|
// }
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
}
|