TopMenu 개발 완료
This commit is contained in:
136
Assets/Scripts/UVC/UI/ToolBar/View/ToggleGroupManager.cs
Normal file
136
Assets/Scripts/UVC/UI/ToolBar/View/ToggleGroupManager.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace UVC.UI.Toolbar.View
|
||||
{
|
||||
/// <summary>
|
||||
/// 툴바 내의 라디오 버튼 그룹(UnityEngine.UI.ToggleGroup)을 생성하고 관리하는 헬퍼 클래스입니다.
|
||||
/// ToolbarView로부터 ToggleGroup 관련 로직을 위임받아 처리함으로써 ToolbarView의 복잡도를 낮추고 역할을 분리합니다.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 주요 역할:
|
||||
/// - ToggleGroup 동적 생성: 라디오 버튼 모델의 GroupName을 기반으로 해당하는 ToggleGroup을 찾거나 새로 생성합니다.
|
||||
/// - 리소스 관리: 생성된 ToggleGroup GameObject들을 내부적으로 관리하며, 툴바가 정리될 때 함께 파괴하여 메모리 누수를 방지합니다.
|
||||
/// - 레이아웃 독립성: 생성된 ToggleGroup GameObject가 툴바의 UI 레이아웃에 영향을 주지 않도록 LayoutElement 컴포넌트를 추가하고 `ignoreLayout`을 true로 설정합니다.
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// // 이 클래스는 ToolbarView 내부에서 다음과 같이 사용됩니다.
|
||||
///
|
||||
/// // 1. ToolbarView의 Awake 메서드에서 ToggleGroupManager 인스턴스 생성
|
||||
/// // public class ToolbarView : MonoBehaviour
|
||||
/// // {
|
||||
/// // public Transform toolbarContainer;
|
||||
/// // private ToggleGroupManager _toggleGroupManager;
|
||||
/// //
|
||||
/// // void Awake()
|
||||
/// // {
|
||||
/// // _toggleGroupManager = new ToggleGroupManager(toolbarContainer);
|
||||
/// // }
|
||||
/// // // ...
|
||||
/// // }
|
||||
///
|
||||
/// // 2. 라디오 버튼(RadioButton)의 UI 프로세서에서 `GetOrCreateToggleGroup` 호출
|
||||
/// // public class ToolbarRadioButtonViewProcessor : IButtonViewProcessor
|
||||
/// // {
|
||||
/// // public void SetupButtonInteractions(ToolbarButtonBase buttonModel, GameObject buttonUIObject, ToolbarView viewContext)
|
||||
/// // {
|
||||
/// // ToolbarRadioButton radioModel = buttonModel as ToolbarRadioButton;
|
||||
/// // Toggle uiToggle = buttonUIObject.GetComponent<Toggle>();
|
||||
/// // if (uiToggle != null)
|
||||
/// // {
|
||||
/// // // viewContext의 GetOrCreateToggleGroup을 호출하면 내부적으로 ToggleGroupManager의 메서드가 실행됩니다.
|
||||
/// // uiToggle.group = viewContext.GetOrCreateToggleGroup(radioModel.GroupName);
|
||||
/// // }
|
||||
/// // }
|
||||
/// // }
|
||||
///
|
||||
/// // 3. 툴바를 정리(Clear)할 때 Manager의 Clear 메서드 호출
|
||||
/// // public class ToolbarView : MonoBehaviour
|
||||
/// // {
|
||||
/// // protected virtual void ClearToolbar()
|
||||
/// // {
|
||||
/// // // ... 다른 UI 요소 정리 ...
|
||||
/// // _toggleGroupManager.Clear(); // 생성된 모든 토글 그룹 GameObject들을 파괴
|
||||
/// // }
|
||||
/// // }
|
||||
/// </code>
|
||||
/// </example>
|
||||
public class ToggleGroupManager
|
||||
{
|
||||
private readonly Transform _container;
|
||||
private readonly Dictionary<string, ToggleGroup> _toggleGroups = new Dictionary<string, ToggleGroup>();
|
||||
|
||||
/// <summary>
|
||||
/// ToggleGroupManager의 새 인스턴스를 초기화합니다.
|
||||
/// </summary>
|
||||
/// <param name="container">생성될 ToggleGroup GameObject들이 자식으로 추가될 부모 Transform입니다. 보통 툴바의 컨테이너를 지정합니다.</param>
|
||||
public ToggleGroupManager(Transform container)
|
||||
{
|
||||
_container = container;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 지정된 그룹 이름에 해당하는 UnityEngine.UI.ToggleGroup을 가져오거나, 없으면 새로 생성합니다.
|
||||
/// </summary>
|
||||
/// <param name="groupName">찾거나 생성할 토글 그룹의 이름입니다.</param>
|
||||
/// <returns>요청된 이름에 해당하는 ToggleGroup 컴포넌트입니다.</returns>
|
||||
public ToggleGroup GetOrCreateToggleGroup(string groupName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(groupName))
|
||||
{
|
||||
Debug.LogError("ToggleGroupManager: GetOrCreateToggleGroup - groupName이 null이거나 비어있습니다.");
|
||||
// 그룹 이름이 없는 비정상적인 경우를 위해 임시 그룹을 생성하여 반환합니다.
|
||||
GameObject tempGroupObj = new GameObject($"ToggleGroup_UnnamedDynamic");
|
||||
tempGroupObj.transform.SetParent(_container, false);
|
||||
return tempGroupObj.AddComponent<ToggleGroup>();
|
||||
}
|
||||
|
||||
// 캐시된 딕셔너리에서 그룹 이름으로 ToggleGroup을 찾아봅니다.
|
||||
if (!_toggleGroups.TryGetValue(groupName, out ToggleGroup group))
|
||||
{
|
||||
// 해당하는 ToggleGroup이 없으면 새로 생성합니다.
|
||||
GameObject groupObj = new GameObject($"ToggleGroup_{groupName}");
|
||||
groupObj.transform.SetParent(_container);
|
||||
|
||||
// RectTransform을 추가하고 크기를 0으로 설정하여 레이아웃에 영향을 주지 않도록 합니다.
|
||||
RectTransform groupRect = groupObj.AddComponent<RectTransform>();
|
||||
groupRect.sizeDelta = Vector2.zero;
|
||||
groupRect.anchoredPosition = Vector2.zero;
|
||||
groupRect.anchorMin = Vector2.zero;
|
||||
groupRect.anchorMax = Vector2.one;
|
||||
|
||||
// ToggleGroup 컴포넌트를 추가합니다.
|
||||
group = groupObj.AddComponent<ToggleGroup>();
|
||||
group.allowSwitchOff = false; // 라디오 버튼 그룹은 일반적으로 항상 하나가 선택된 상태를 유지해야 하므로, 선택 해제를 허용하지 않습니다.
|
||||
|
||||
// LayoutElement를 추가하고 ignoreLayout을 true로 설정하여 부모의 LayoutGroup 계산에서 이 GameObject를 무시하도록 합니다.
|
||||
LayoutElement element = groupObj.AddComponent<LayoutElement>();
|
||||
element.ignoreLayout = true;
|
||||
|
||||
// 새로 생성된 그룹을 딕셔너리에 추가하여 다음 요청 시 재사용할 수 있도록 합니다.
|
||||
_toggleGroups.Add(groupName, group);
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 이 매니저를 통해 생성된 모든 ToggleGroup GameObject들을 파괴하고 내부 캐시를 비웁니다.
|
||||
/// 툴바가 다시 렌더링되거나 파괴될 때 호출하여 메모리 누수를 방지합니다.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
if (_toggleGroups == null) return;
|
||||
foreach (var groupObj in _toggleGroups.Values)
|
||||
{
|
||||
if (groupObj != null && groupObj.gameObject != null)
|
||||
{
|
||||
// 생성했던 GameObject를 파괴합니다.
|
||||
Object.Destroy(groupObj.gameObject);
|
||||
}
|
||||
}
|
||||
_toggleGroups.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user