killapp/Assets/Scripts/UI/Components/SelectCountry.cs

251 lines
7.5 KiB
C#
Raw Normal View History

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Kill.Managers;
using Kill.Network;
using Kill.UI;
public class SelectCountry : MonoBehaviour
{
public GameObject countryPrefab;
public Transform countryParent;
public Button submitButton;
public Button backButton;
public InputField searchInput;
public ScrollRect scrollRect;
LanguageManager.Country selectCountry;
private bool _hasSelection;
private string _originalCode;
/// <summary>
/// 未选中 选中
/// </summary>
public Color[] textColors;
private List<SelectCountryItem> _items = new List<SelectCountryItem>();
/// <summary>
/// 确认回调code 为选中的国家代码null 表示返回/取消
/// </summary>
public System.Action<string> onConfirm;
/// <summary>
/// 初始化
/// </summary>
/// <param name="code">当前选中的国家代码</param>
/// <param name="showBackButton">是否显示返回按钮(主页不显示)</param>
public void Init(string code, bool showBackButton = true)
{
_originalCode = code;
countryPrefab.SetActive(false);
// 清理旧 item
foreach (var item in _items)
Destroy(item.gameObject);
_items.Clear();
_hasSelection = false;
// 返回按钮
if (backButton != null)
{
backButton.gameObject.SetActive(showBackButton);
backButton.onClick.RemoveAllListeners();
backButton.onClick.AddListener(OnBack);
if (showBackButton)
UIManager.Instance.RegisterBackAction(OnBack);
}
if (LanguageManager.Instance == null || LanguageManager.Instance.countryList == null)
return;
foreach (var country in LanguageManager.Instance.countryList)
{
var go = Instantiate(countryPrefab, countryParent);
var item = go.AddComponent<SelectCountryItem>();
item.Init(this, country);
_items.Add(item);
item.gameObject.SetActive(true);
}
// 绑定搜索
if (searchInput != null)
{
searchInput.onValueChanged.RemoveAllListeners();
searchInput.onValueChanged.AddListener(OnSearchChanged);
}
// 设置默认选中code 为空时不选中)
if (!string.IsNullOrEmpty(code))
SelectCountryByCode(code);
// 自动滚动到选中项
ScrollToSelected();
UpdateSubmitButton();
}
/// <summary>
/// 返回按钮点击
/// </summary>
private void OnBack()
{
onConfirm?.Invoke(null);
}
/// <summary>
/// 滚动到当前选中的国家项(居中显示)
/// </summary>
private void ScrollToSelected()
{
if (scrollRect == null || !_hasSelection) return;
int index = _items.FindIndex(i => i.Country.code == selectCountry.code);
if (index < 0) return;
Canvas.ForceUpdateCanvases();
var itemRect = _items[index].GetComponent<RectTransform>();
float contentHeight = scrollRect.content.rect.height;
float viewportHeight = scrollRect.viewport.rect.height;
if (contentHeight <= viewportHeight) return;
// 计算目标滚动位置:使选中项居中
float maxScrollY = contentHeight - viewportHeight;
float itemCenterY = Mathf.Abs(itemRect.anchoredPosition.y) + itemRect.rect.height / 2;
float targetScrollY = itemCenterY - viewportHeight / 2;
targetScrollY = Mathf.Clamp(targetScrollY, 0, maxScrollY);
scrollRect.verticalNormalizedPosition = 1f - targetScrollY / maxScrollY;
}
private void OnSearchChanged(string keyword)
{
foreach (var item in _items)
{
item.gameObject.SetActive(item.MatchKeyword(keyword));
}
}
public void SelectCountryByCode(string code)
{
_hasSelection = !string.IsNullOrEmpty(code);
foreach (var item in _items)
{
bool isSelected = _hasSelection && item.Country.code == code;
item.SetSelected(isSelected);
if (isSelected)
selectCountry = item.Country;
}
UpdateSubmitButton();
}
public string GetSelectedCode()
{
return _hasSelection ? selectCountry.code : null;
}
private void UpdateSubmitButton()
{
if (submitButton != null)
{
submitButton.gameObject.SetActive(_hasSelection);
submitButton.onClick.RemoveAllListeners();
submitButton.onClick.AddListener(OnSubmit);
}
}
private async void OnSubmit()
{
if (!_hasSelection) return;
await UpdateCountryCodeAsync(selectCountry.code);
}
/// <summary>
/// 更新用户国家代码
/// </summary>
private async System.Threading.Tasks.Task UpdateCountryCodeAsync(string code)
{
try
{
var requestData = new CountryCodeRequest
{
country_code = code
};
var response = await NetworkCtrl.Instance.Put<NoDataResponse>("/api/v1/user/country-code", requestData);
ResponseCodeHandler.HandleResponse(response,
onSuccess: (data) =>
{
if (DataManager.Instance.userInfo != null)
DataManager.Instance.userInfo.country_code = code;
onConfirm?.Invoke(code);
},
onError: null
);
}
catch (Exception ex)
{
Debug.LogError($"更新国家代码失败: {ex.Message}");
}
}
}
internal class SelectCountryItem : MonoBehaviour
{
public LanguageManager.Country Country { get; private set; }
private SelectCountry _parent;
private Text _nameText;
private GameObject _selectGo;
private Color _selectedColor;
private Color _unselectedColor;
public void Init(SelectCountry parent, LanguageManager.Country country)
{
_parent = parent;
Country = country;
_nameText = transform.Find("name")?.GetComponent<Text>();
_selectGo = transform.Find("选中")?.gameObject;
_selectedColor = parent.textColors.Length > 0 ? parent.textColors[0] : Color.white;
_unselectedColor = parent.textColors.Length > 1 ? parent.textColors[1] : Color.gray;
// 显示国家名称(根据当前语言)
bool isChinese = LanguageManager.Instance != null && LanguageManager.Instance.languageType == LanguageManager.LanguageType.Chinese;
if (_nameText != null)
_nameText.text = isChinese ? country.name_zh : country.name_en;
// 点击事件
var btn = GetComponent<Button>();
if (btn == null)
btn = gameObject.AddComponent<Button>();
btn.onClick.AddListener(OnClick);
}
public void SetSelected(bool selected)
{
if (_nameText != null)
_nameText.color = selected ? _selectedColor : _unselectedColor;
if (_selectGo != null)
_selectGo.SetActive(selected);
}
public bool MatchKeyword(string keyword)
{
if (string.IsNullOrEmpty(keyword))
return true;
var k = keyword.ToLower();
return Country.name_zh.ToLower().Contains(k)
|| Country.name_en.ToLower().Contains(k)
|| Country.code.ToLower().Contains(k);
}
private void OnClick()
{
_parent.SelectCountryByCode(Country.code);
}
}