728x90

NGUI를 이용하여 스크롤뷰를 만들경우에, 보통은 아래 그림과 같은 구조로 간단하게 만들수 있다.


스크롤뷰가 있고, 그 아래엔 오브젝트들 정리를 위한 그리드가 있고, 그리드 밑에는 오브젝트들이 배치가 되는 구조 이다.








스크롤뷰를 구성하기 위해 UIScrollView 컴포넌트를 오브젝트에 붙이면 UI Panel과 UI Scroll View 컴포넌트 2개가 붙게 된다. 


스크롤뷰 컴포넌트를 쓰기위해선 패널 컴포넌트도 무조건 따라오게 되어 있다.
















내가 이번에 테스트겸, 알아보고 싶었던거는 보통 게임들을 보면 스크롤뷰를 사용하되 특히 랭킹 같은 정보의 스크롤뷰를 보면 한번에 100개의 정보가 한번에 다 스크롤뷰에 보여주는 것이 아니라 스크롤 영역을 드래그 하면서 끝부분에 도달하면 이후의 정보들을 서버로부터 더 받아와서 뿌려주는 방식이 대부분이다.


이 판정을 어떻게 하는가에 대해 궁금하여 정리해보았다.



코드를 설명하면

스크롤뷰에 이벤트를 등록시켜준다, 드래그가 끝낫을때 처리하는 이벤트를 등록하고 이벤트 콜백함수는 bbb()라고 임시로 지었다.


이 함수에서 하는 일은 스크롤뷰안에 있는 드래깅 되고있는 패널(scrollView.panel)부분영역을 기준으로 CalculateConstrainOffset이라고하는 함수를 사용하여 매개변수로 스크롤뷰의 바운드(bounds) box 영역을 이루고 있는 최소점과 최대점(Vector) 값을 넘겨주면 스크롤뷰의 패널 영역 기준으로 현재 스크롤뷰 바운드가 얼마만큼의 차이(Offset)값이 났는지에 대한 결과값을 vector 값으로 준다.


이 결과값 vector를 이용해서 우리는 스크롤뷰를 드래그 하고나서 스크롤뷰가 스크롤뷰의 패널영역 어디 부분(y : 위, 아래  x: 왼쪽,오른쪽)에  도달했는지를 알수 있다.











위 그림을 통해서 좀 더 자세히 보면 주황색 영역과 겹쳐진 직사각형의 보라색영역이 스크롤뷰의 패널 영역입니다.(UI Panel) 패널 영역의 크기는 패널 컴포넌트의 Size와 관련이 있다.


그리고 직사각형의 주황색 영역이 스크롤뷰의 바운드(Bounds) 영역입니다. 실제로 스크롤뷰 아래 자식으로 무언가 오브젝트가 없다면 저 영역은 0과 마찬가지다, 사진에만 보이도록 하기 위해 제가 안보이는 오브젝트를 생성해두었다. (스크롤뷰 안에있는 그리드에 자식으로 오브젝트를 추가한것임)


이 바운드 영역은 오브젝트가 추가되고 삭제되고 할때마다 알아서 계산해서 바운드 영역을 잡아 주는것으로 테스트결과로 보았다.



위에서부터 4번째까지가 순서대로


scrollView.bounds.min

scrollView.bounds.max

scrollView.bounds.size.x

scrollView.bounds.size.y


값을 로그로 찍어봣다.

이 4개 값을 그림으로 그려보면 사각형 box가 이루어진다는것을 알수 있다

이 box가 현재 스크롤뷰의 bounds 영역이라는 것이다.


스크롤뷰를 드래그해서 패널 컴포넌트의 offset 값의 변동을 보게 되면, 밑으로 스크롤뷰를 드래그 했을때는 y값이 +가 되는걸 볼수 있고, 위로 드래그 했을대는 y값이 -가 되는걸 볼수 있었다.


즉 CalculateConstrainOffset 을 통해 가져온 값은 스크롤뷰의 패널영역내에서 스크롤뷰의 바운드영역의 현재 위치에 대한 차이값이므로 이 차이값에서 y가 0보다 커지면 밑으로 드래그 할수있는 최대영역에 도달했다는것(스크롤 상단끝에 도달)이고, y가 0보다 작으면 위로 드래그할수있는 최대영역(스크롤 하단끝에 도달)에 도달했다라는걸 알수 있다.


그리고 이러한 모든 처리를 하고나면 스크롤뷰의 포지션을 어떻게 다시 잡아줄거냐도 문제인데 
두가지 함수가 제공된다.

public virtual void SetDragAmount (float x, float y, bool updateScrollbars)
이 함수는 해당 위치로 바로 스크롤뷰를 이동시켜주는 함수다.
x와 y값은 0~1사이의 값을 넣어줘야 한다. 세번째 인자는 정확한 용도는 모르겟지만 이름만 봐서는 스크롤바도 사용하고있다면 이것도 갱신을 해줄지 안해줄지에 대한 bool 변수인듯 하다.

0을 넣으면 처음위치, 0.5는 중간, 1은 끝위치 정도로 생각하면 되겠다.


static public SpringPanel Begin (GameObject go, Vector3 pos, float strength)


이 함수는 해당 위치로 곧바로 이동시키는것이 아니라 애니메이션이 되면서 스무스 하게 스크롤뷰를 이동시켜 준다.


인자는 스크롤뷰를 가지고 있는 게임오브젝트를 넘겨주고 이동할 포지션, 그리고 세번째 인자는 뜻만봐선 힘인데 spring이라는 단어에서 유추할수 있듯이 힘이세면 스프링이 쎄게 팅기는원리처럼 스크롤뷰가 애니메이션으로 움직일때 어느정도의 강도를 줄것이냐 라고 정도로 이해하면 될듯 하다.


특정 아이템이있는 위치로 스크롤뷰를 이동시키고 싶으면 

가로로 움직이는 스크롤뷰이고 아이템이 차례대로 1개씩 정렬되어 있다는 가정하에


float itemWidth = 스크롤뷰.bounds.size.x 를 / 아이템 총 갯수 

로 나누면 아이템 한개당 width(폭)을 알수 있다.


float movePosX = -itemWidth * 위치하고싶은 아이템의 인덱스(스크롤뷰에서 몇번째에 있는지)

로 하면 해당 아이템으로 이동해야할 x 포지션을 구할수 있다.


x는 왼쪽으로 갈수록 -가 되니까 -를 해준거다.


SpringPanel.Begin(스크롤뷰.gameObject, new Vector3(movePos, 스크롤뷰.transform.localPosition.y), 1f);


이런식으로 하면 해당 아이템쪽으로 이동이 되는거다 애니메이션을 하면서.


SetDragAmount 함수에서도 똑같이


위와 같은 과정으로 moxPosX (이동해야할 폭)을 구하고 이 값을 / 스크롤뷰.bounds.size.z로 나누면 

0~1사이의 값으로 나올테니까 똑같이 비율 계산을 통해 이동시켜 줄수 있다.

728x90
Posted by 정망스
,


맨 위로
홈으로 ▲위로 ▼아래로 ♥댓글쓰기 새로고침