2025/Unity

[Unity] tool 만들기 아코디언 메뉴

rimugiri 2025. 3. 1. 15:34
728x90

전에 script로 구현해 놓았던 아코디언 메뉴를 바로바로 사용하기 편하도록 Editor를 만들어 보았다

 

 

[Unity] UI - 아코디언 메뉴 만드는 방법 <펼치고 접기>

접기/펼치기 토글로 내용이 스르륵 나타났다 사라지는 메뉴, 흔히 '아코디언 메뉴'라고 불리는 UI를 직접 구현해봤습니다.굳이 에셋을 사거나 별도 트윈 시스템을 구현하는 게 귀찮아서, 그냥 간

rimugiri.tistory.com

 

1. 코드

#if UNITY_EDITOR
using TMPro;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;

public static class AccordionEditor
{
    [MenuItem("GameObject/UI/Accordion", false, 10)]
    public static void CreateAccordion()
    {
        Canvas root = GameObject.FindObjectOfType<Canvas>();
        if(root == null)
        {
            GameObject canvas = new GameObject("Canvas", typeof(Canvas), typeof(CanvasScaler), typeof(GraphicRaycaster));
            canvas.GetComponent<Canvas>().renderMode = RenderMode.ScreenSpaceOverlay;
            root = canvas.GetComponent<Canvas>();
        }

        GameObject panel = new GameObject("AccordionPanel", typeof(RectTransform), typeof(VerticalLayoutGroup), typeof(AccordionPanel), typeof(ContentSizeFitter));
        var layoutGroup = panel.GetComponent<VerticalLayoutGroup>();
        var contentSizeFitter = panel.GetComponent<ContentSizeFitter>();

        layoutGroup.childForceExpandHeight = false;
        layoutGroup.childForceExpandWidth = false;

        layoutGroup.childControlHeight = true;
        contentSizeFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;

        
        panel.transform.SetParent(root.gameObject.transform, false);
       

        for (int i = 0; i < 2; i++)
        {
            CreateAccordionItem(panel.transform, $"AccordionItem_{i + 1}");
        }

        Undo.RegisterCreatedObjectUndo(panel, "Create Accordion");
        Selection.activeGameObject = panel;
    }

    private static void CreateAccordionItem(Transform parent, string name)
    {
        GameObject item = new GameObject(name, typeof(RectTransform), typeof(VerticalLayoutGroup), typeof(LayoutElement), typeof(AccordionItem));

        var layoutGroup = item.GetComponent<VerticalLayoutGroup>();
        var accordionItem = item.GetComponent<AccordionItem>();

        layoutGroup.childForceExpandHeight = false;
        layoutGroup.childForceExpandWidth = false;
        layoutGroup.childScaleHeight = true;

        // Header
        GameObject header = new GameObject("Header", typeof(RectTransform));
        header.transform.SetParent(item.transform, false);
        var headerRect = header.GetComponent<RectTransform>();
        headerRect.sizeDelta = new Vector2(0, 50); 

        GameObject hText = new GameObject("Text", typeof(RectTransform), typeof(TextMeshProUGUI));
        hText.transform.SetParent(header.transform, false);
        hText.GetComponent<RectTransform>().localPosition = new Vector3(108, 0, 0);


        var hContentText = hText.GetComponent<TextMeshProUGUI>();
        hContentText.text = "Header";

        GameObject hButton = new GameObject("Button", typeof(RectTransform), typeof(Button), typeof(Image));
        hButton.transform.SetParent(header.transform, false);
        hButton.GetComponent<RectTransform>().localPosition = new Vector3(-62, 0, 0);

        // Content
        GameObject content = new GameObject("Content", typeof(RectTransform), typeof(VerticalLayoutGroup), typeof(LayoutElement));
        content.transform.SetParent(item.transform, false);

        var clayoutGroup = content.GetComponent<VerticalLayoutGroup>();

        clayoutGroup.childForceExpandHeight = false;
        clayoutGroup.childForceExpandWidth = false;
        clayoutGroup.childControlHeight = true;

        GameObject cText = new GameObject("Text", typeof(RectTransform), typeof(TextMeshProUGUI));
        cText.transform.SetParent(content.transform, false);

        var cContentText = cText.GetComponent<TextMeshProUGUI>();
        cContentText.text = "Whatever you want you can add content";

        //accordionItem
        accordionItem.SetHeader(headerRect);
        accordionItem.SetContent(content.GetComponent<RectTransform>());
        accordionItem.SetToggleButton(hButton.GetComponent<Button>());

        // 부모에 붙이기
        item.transform.SetParent(parent, false);
    }
}
#endif

 

2. 사용

 

 

처음 모습은 이상하지만 실행해보면 사이즈가 자동으로 조정되어 잘 작동한다.

세부조정은 버튼의 이미지를 바꾸거나 layout의 값들을 조정하면서 예쁘게 만들어보자

728x90