반응형

2016/01/19 - [unity C#] - [Unity] GUI Infinity Scroll List 무한 리스트 구현 Json 

 

[Unity] GUI Infinity Scroll List 무한 리스트 구현 Json

어떻게 보면 간단한 구현 일 수도 있겠지만 난 어려웠다. ㅠㅠ 그래서 다시 정리하는 차원에서 포스팅 해본다. 먼저 간략하게 요약해보자면… Unity의 기본제공되는 GUI를 사용, 데이터 형태는 Json형태로 만들어..

knightk.tistory.com

이미지가 깨져서 다시 올려봅니다.

 

Hierarchy 구성

Hierarchy
리스트 요소가 될 Item은 Image와 Text 정도만으로 구성

스크립트 구성

스크립트 구성

 

ManagerHandler.cs

using UnityEngine;

public class ManagerHandler : MonoBehaviour {
    public InfiniteScroll infiniteScroll;
    void Start () {
        Application.targetFrameRate = 60;
        initList ();
    }

    void initList () {
        infiniteScroll.ListStart ();
    }
}

 

ModelHandler.cs

using System.Collections;
using System.Collections.Generic;
using LitJson;
using UnityEngine;

public class ModelHandler : MonoBehaviour {
    private JsonData jsonData;
    public List<DataVO> List;
    string jsonString () {
        TextAsset t = (TextAsset) Resources.Load ("data", typeof (TextAsset));
        return t.text;
    }

    void Awake () {
        jsonData = JsonMapper.ToObject (jsonString ());
        parsing ();
    }

    void parsing () {
        for (int i = 0; i < jsonData["music"].Count; i++) {

            ListModel.Instance.dataVO.SongTitle = (string) jsonData["music"][i]["songtitle"];
            ListModel.Instance.dataVO.Singer = (string) jsonData["music"][i]["singer"];
            ListModel.Instance.dataVO.Color = hexToColor ((string) jsonData["music"][i]["color"]);
            ListModel.Instance.dataVO.Genre = (string) jsonData["music"][i]["genre"];
            ListModel.Instance.dataVO.PlayTime = float.Parse ((string) jsonData["music"][i]["playtime"]);

            ListModel.Instance.MusicList.Add (ListModel.Instance.dataVO);
        }
    }

    static Color hexToColor (string hex) {
        hex = hex.Replace ("0x", "");
        hex = hex.Replace ("#", "");
        byte a = 255;
        byte r = byte.Parse (hex.Substring (0, 2), System.Globalization.NumberStyles.HexNumber);
        byte g = byte.Parse (hex.Substring (2, 2), System.Globalization.NumberStyles.HexNumber);
        byte b = byte.Parse (hex.Substring (4, 2), System.Globalization.NumberStyles.HexNumber);
        if (hex.Length == 8) {
            a = byte.Parse (hex.Substring (6, 2), System.Globalization.NumberStyles.HexNumber);
        }
        return new Color32 (r, g, b, a);
    }
}

 

ListModel.cs

using System;
using System.Collections.Generic;
using UnityEngine;

[Serializable]
public struct DataVO {
    public string SongTitle;
    public string Singer;
    public Color32 Color;
    public string Genre;
    public float PlayTime;
}

public class ListModel : MonoBehaviour {
    private static ListModel _instance = null;
    public DataVO dataVO;
    public List<DataVO> MusicList = new List<DataVO> ();
    public static ListModel Instance {
        get {
            if (_instance == null) {
                _instance = (GameObject.Find ("Manager")).AddComponent<ListModel> ();
            }
            return _instance;
        }
    }

}

 

InfiniteScroll.cs

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class InfiniteScroll : MonoBehaviour {
    [SerializeField]
    private RectTransform m_ItemBase;
    [SerializeField]
    int m_instantiateItemCount = 9;
    [SerializeField]
    float m_itemWidth = 1080;
    [SerializeField]
    float m_itemHeight = 200;
    [SerializeField]
    float gap = 10;
    public Direction direction;
    [System.NonSerialized]
    public List<RectTransform> m_itemList = new List<RectTransform> ();
    protected float m_diffPreFramePosition = 0;
    [SerializeField]
    private int m_currentItemNo = 0;
    public ScrollRect scrollRect;
    public List<DataVO> listData;
    public enum Direction {
        Vertical,
        Horizontal,
    }

    // cache component
    public RectTransform m_Content;

    private float AnchoredPosition {
        get {
            return (direction == Direction.Vertical) ?
                -m_Content.anchoredPosition.y :
                m_Content.anchoredPosition.x;
        }
    }
    private float ItemScale {
        get {
            return (direction == Direction.Vertical) ?
                m_itemHeight :
                m_itemWidth;
        }
    }

    void Start () {
        m_itemWidth = Screen.width;
        m_itemHeight = Screen.height / 12;
    }

    public void ListStart () {
        listData = ListModel.Instance.MusicList;

        if (listData.Count < m_instantiateItemCount) {
            m_instantiateItemCount = listData.Count;
        } else {
            m_instantiateItemCount = (direction == Direction.Vertical) ?
                Mathf.RoundToInt (Screen.height / ItemScale) + 3 :
                Mathf.RoundToInt (Screen.width / ItemScale) + 3;
        }

        // create items
        scrollRect.horizontal = direction == Direction.Horizontal;
        scrollRect.vertical = direction == Direction.Vertical;

        if (direction == Direction.Vertical) {
            m_Content.SetSizeWithCurrentAnchors (RectTransform.Axis.Vertical, (ItemScale + gap) * (listData.Count - 1) + gap);
            m_Content.SetSizeWithCurrentAnchors (RectTransform.Axis.Horizontal, m_itemWidth + gap * 2);
        } else {
            m_Content.SetSizeWithCurrentAnchors (RectTransform.Axis.Horizontal, (ItemScale + gap) * (listData.Count - 1) + gap);
            m_Content.SetSizeWithCurrentAnchors (RectTransform.Axis.Vertical, m_itemHeight + gap * 2);
        }

        scrollRect.onValueChanged.AddListener (valueChange);
        Debug.Log (listData.Count);
        m_ItemBase.gameObject.SetActive (false);
        for (int i = 0; i < m_instantiateItemCount; i++) {
            var item = GameObject.Instantiate (m_ItemBase) as RectTransform;
            item.SetParent (transform, false);
            item.name = i.ToString ();

            if (direction == Direction.Vertical) {
                item.SetSizeWithCurrentAnchors (RectTransform.Axis.Horizontal, m_itemWidth - gap * 2);
                item.SetSizeWithCurrentAnchors (RectTransform.Axis.Vertical, m_itemHeight);
            } else {
                item.SetSizeWithCurrentAnchors (RectTransform.Axis.Horizontal, m_itemWidth);
                item.SetSizeWithCurrentAnchors (RectTransform.Axis.Vertical, m_itemHeight);
            }

            item.anchoredPosition =
                (direction == Direction.Vertical) ?
                new Vector2 (gap, -gap - (ItemScale + gap) * i) :
                new Vector2 ((ItemScale + gap) * i + gap, -gap);
            m_itemList.Add (item);

            item.gameObject.SetActive (true);
            item.GetComponent<Item> ().UpdateItem (i);
        }
    }

    private void valueChange (Vector2 _pos) {
        // scroll up, item attach bottom  or  right
        while (AnchoredPosition - m_diffPreFramePosition < -(ItemScale + gap) * 2) {
            m_diffPreFramePosition -= (ItemScale + gap);

            var item = m_itemList[0];
            m_itemList.RemoveAt (0);
            m_itemList.Add (item);

            var pos = (ItemScale + gap) * m_instantiateItemCount + (ItemScale + gap) * m_currentItemNo;
            item.anchoredPosition = (direction == Direction.Vertical) ? new Vector2 (gap, -pos - gap) : new Vector2 (pos + gap, -gap);

            m_currentItemNo++;

            if (m_currentItemNo + m_instantiateItemCount < listData.Count) {
                item.GetComponent<Item> ().UpdateItem (m_currentItemNo + m_instantiateItemCount);
            } else {
                item.GetComponent<Item> ().UpdateItem (-100);
            }
        }

        // scroll down, item attach top  or  left
        while (AnchoredPosition - m_diffPreFramePosition > 0) {
            m_diffPreFramePosition += (ItemScale + gap);

            var itemListLastCount = m_instantiateItemCount - 1;
            var item = m_itemList[itemListLastCount];
            m_itemList.RemoveAt (itemListLastCount);
            m_itemList.Insert (0, item);

            m_currentItemNo--;

            var pos = (ItemScale + gap) * m_currentItemNo + gap;
            item.anchoredPosition = (direction == Direction.Vertical) ? new Vector2 (gap, -pos) : new Vector2 (pos, -gap);

            if (m_currentItemNo > -1) {
                item.GetComponent<Item> ().UpdateItem (m_currentItemNo);
            } else {
                item.GetComponent<Item> ().UpdateItem (-100);
            }
        }
    }
}

 

Item.cs

using UnityEngine;
using UnityEngine.UI;

public class Item : MonoBehaviour {
    public Text m_Text;
    public Image m_Image;
    public void UpdateItem (int count) {
        if (count == -100) {
            m_Text.gameObject.SetActive (false);
            m_Image.gameObject.SetActive (false);
        } else {
            m_Text.gameObject.SetActive (true);
            m_Image.gameObject.SetActive (true);
            m_Text.text = count + 1 + " - " + Screen.width + " x " + Screen.height;
            m_Image.color = ListModel.Instance.MusicList[count].Color;
        }
    }
}

 

Manager 오브젝트에 ManagerHandler.cs / ModelHandler.cs / ListModel.cs 붙여줍니다.

Manager Object

ScrollView를 만들어 다음과같이 세팅해줍니다.

ScrollRect

InfinityContent 오브젝트에 InfinityScroll.cs 를 붙여주고

ScrollRect항목에 위에서 설정한 ScrollRect를 드래그앤 드랍으로 넣어줍니다.

Content항목에 InfinityContent오브젝트를 끌어넣어 연결해줍니다.

InfinityScroll.cs 붙이기

 

Item 오브젝트에 Item.cs를 붙여주고 위에 InfinityScroll 인스펙터에 ItemBase에 드래그앤 드랍으로 넣어줍니다.

Item인스펙터의 Text와 Image를 해당 오브젝트로 연결시켜줍니다.

Item.cs 붙이기

 

data.txt 파일 생성

Resources폴더에 data.txt파일만들어 아래와 같이 데이터를 넣어줍니다. 아래 데이터는 테스트 하기 위해 임의로 생성한 것이고 자신의 리스트에 맞게 수정해서 사용하면 됩니다.

{
  "music":[
    {
      "songtitle" : "Love Will Show You Everything",
      "singer" : "Various Artists",
      "color" : "f98181",
      "genre" : "rock",
      "playtime" : "0"
    },
    {
      "songtitle" : "Love Will Show You Everything",
      "singer" : "Various Artists",
      "color" : "f981bc",
      "genre" : "rock",
      "playtime" : "0"
    }, 
    {
      "songtitle" : "Love Will Show You Everything",
      "singer" : "Various Artists",
      "color" : "f881f9",
      "genre" : "rock",
      "playtime" : "0"
    },
    {
      "songtitle" : "Love Will Show You Everything",
      "singer" : "Various Artists",
      "color" : "d081f9",
      "genre" : "rock",
      "playtime" : "0"
    }, 
    {
      "songtitle" : "Love Will Show You Everything",
      "singer" : "Various Artists",
      "color" : "ab81f9",
      "genre" : "rock",
      "playtime" : "0"
    },
    {
      "songtitle" : "Love Will Show You Everything",
      "singer" : "Various Artists",
      "color" : "8c81f9",
      "genre" : "rock",
      "playtime" : "0"
    }, 
    {
      "songtitle" : "Love Will Show You Everything",
      "singer" : "Various Artists",
      "color" : "8192f9",
      "genre" : "rock",
      "playtime" : "0"
    },
    {
      "songtitle" : "Love Will Show You Everything",
      "singer" : "Various Artists",
      "color" : "81a8f9",
      "genre" : "rock",
      "playtime" : "0"
    }, 
    {
      "songtitle" : "Love Will Show You Everything",
      "singer" : "Various Artists",
      "color" : "81c8f9",
      "genre" : "rock",
      "playtime" : "0"
    },
    {
      "songtitle" : "Love Will Show You Everything",
      "singer" : "Various Artists",
      "color" : "81e4f9",
      "genre" : "rock",
      "playtime" : "0"
    }, 
    {
      "songtitle" : "Love Will Show You Everything",
      "singer" : "Various Artists",
      "color" : "81f9e4",
      "genre" : "rock",
      "playtime" : "0"
    },
    {
      "songtitle" : "Love Will Show You Everything",
      "singer" : "Various Artists",
      "color" : "81f9c5",
      "genre" : "rock",
      "playtime" : "0"
    }, 
    {
      "songtitle" : "Love Will Show You Everything",
      "singer" : "Various Artists",
      "color" : "81f9a3",
      "genre" : "rock",
      "playtime" : "0"
    },
    {
      "songtitle" : "Love Will Show You Everything",
      "singer" : "Various Artists",
      "color" : "81f989",
      "genre" : "rock",
      "playtime" : "0"
    }, 
    {
      "songtitle" : "Love Will Show You Everything",
      "singer" : "Various Artists",
      "color" : "a0f981",
      "genre" : "rock",
      "playtime" : "0"
    },
    {
      "songtitle" : "Love Will Show You Everything",
      "singer" : "Various Artists",
      "color" : "c2f981",
      "genre" : "rock",
      "playtime" : "0"
    }, 
    {
      "songtitle" : "Love Will Show You Everything",
      "singer" : "Various Artists",
      "color" : "e9f981",
      "genre" : "rock",
      "playtime" : "0"
    },
    {
      "songtitle" : "Love Will Show You Everything",
      "singer" : "Various Artists",
      "color" : "f9e981",
      "genre" : "rock",
      "playtime" : "0"
    }, 
    {
      "songtitle" : "Love Will Show You Everything",
      "singer" : "Various Artists",
      "color" : "f9cd81",
      "genre" : "rock",
      "playtime" : "0"
    },
    {
      "songtitle" : "Love Will Show You Everything",
      "singer" : "Various Artists",
      "color" : "f9b181",
      "genre" : "rock",
      "playtime" : "0"
    }, 
    {
      "songtitle" : "Love Will Show You Everything",
      "singer" : "Various Artists",
      "color" : "f99781",
      "genre" : "rock",
      "playtime" : "0"
    }
  ]
}

 

실행화면

실행화면

 

반응형

+ Recent posts