ButtonWrapper
Класс-обёртка для удобства использования UI.Button.
Мне для игры понадобилось программно сделать кнопки с номерами уровней.
Сделал GridLayout, в который добавлял кнопки, создавая их из префаба.
Возникла проблема с событием onClick.
Код:
PHP код:
void InitLevelTasks() { levelChooser = new LevelChooser(imageForLevelTask); Transform root = PanelLevelsList; foreach (Transform child in root) { Destroy(child.gameObject); } int count = 48; for (int k = 0; k < count; ++k) { var clone = GameObject.Instantiate(buttonPrefab); clone.transform.SetParent(root); clone.transform.localScale = Vector3.one;
var button = clone.GetComponent<Button>();
text = button.transform.Find("Text").GetComponent<Text>(); text.text = ""+k;
UnityAction act = new UnityAction (() => SelectLevel_Start (k)); button.onClick.AddListener(act); } }
Любая кнопка при нажатии стартует уровень 48 - т.е. это значение К при выходе из цикла.
Я с ходу не понял, как можно впихнуть корректный параметр, и сделал обёртку для кнопки.
PHP код:
/* ButtonEventArgs */
public class ButtonEventArgs<TValue> : EventArgs {
public TValue Value { get; private set; }
public ButtonEventArgs(TValue value) { Value = value; }
}
/* ButtonWrapper */
public class ButtonWrapper<TParam> {
public event EventHandler<ButtonEventArgs<TParam>> OnClick; public GameObject gameObject;
Text text; Button button; TParam value;
public ButtonWrapper(string caption, TParam value, GameObject buttonPrefab, Transform parent) {
this.value = value;
gameObject = GameObject.Instantiate(buttonPrefab); gameObject.transform.SetParent(parent); gameObject.transform.localScale = Vector3.one;
button = gameObject.GetComponent<Button>(); UnityAction act = new UnityAction(Clicked); button.onClick.AddListener(act);
text = button.transform.Find("Text").GetComponent<Text>(); text.text = caption;
}
public void SetColor(string hex) { if (!hex.StartsWith("#")) hex = "#" + hex; Color c; ColorUtility.TryParseHtmlString(hex, out c); button.GetComponent<Image>().color = c; }
private void Clicked () { if (OnClick != null) OnClick(this, new ButtonEventArgs<TParam>(value)); }
}
Что имеем?
1. Событие onClick в виде привычного с# event'a, на которое можно подписаться через +=
2. При клике - событие может содержать любой тип данных, какой мы укажем при создании враппера - достаём данные из параметра ButtonEventArgs.
Итоговый код создания кнопок (добавлена раскраска - 4 разных цвета по 12 кнопок в каждом блоке)
PHP код:
void InitLevelTasks() { levelChooser = new LevelChooser(imageForLevelTask); Transform root = PanelLevelsList; foreach (Transform child in root) { Destroy(child.gameObject); } int count = 48; for (int k = 0; k < count; ++k) { ButtonWrapper<int> wrap = new ButtonWrapper<int>((k + 1).ToString(), k, prefabButtonLevelNum, root); wrap.OnClick += (sender, e) => { SelectLevel_Start(e.Value); }; int v = k / 12; string color; if (v == 0) color = "41C64E"; else if (v == 1) color = "F9FF67"; else if (v == 2) color = "3381FF"; else color = "FF4B3E"; wrap.SetColor(color); } }
|