ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • ViewPager와 PageAdapter
    개발/안드로이드 2019. 3. 5. 23:38


    0. ViewPager와 PagerAdapter


    ViewPager와 PagerAdapter는 아래 네이버 앱의 뉴스, 연애 스포츠 탭처럼 큰 화면 안에서 여러 개의 작은 화면을 좌우로 움직이는 UI를 구성할 때 사용하는 안드로이드 라이브러리다. ViewPager는 TextView, Button과 같이 화면의 인터페이스로 사용자가 조작할 수 있는 컴포넌트고 PagerAdapter는 ViewPager가 생성한 공간을 채우는 데이터 공간으로 보면 된다. 


    특별히 화면에 이펙트를 넣을 생각이 없으면 ViewPager는 안드로이드에서 제공하는 라이브러리를 그대로 쓰고 내가 넣고 싶은 화면을 담은 별도의 PagerAdapter를 만들어서 ViewPager에 연결 시키면 된다.


    이버의 뉴스, 연예, 스포츠 탭은 ViewPager와 PagerAdapter로 만들었을 것 같다. (아닐수도 있고)


    1. Fragment + PagerAdapter 


    큰 화면의 단위는 Activity이고 작은 화면의 단위는 주로 Fragment를 사용하기 때문에 안드로이드에서는 PagerAdater를 Fragment를 사용해서 구현하기 쉽도록 FragmentPagerAdatper를 만들어 뒀다. 이것과 이름이 비슷한 FragmentStatePagerAdapter가 있는데 Fragment 메모리 관리를 어떤식으로 할 것인가에 따라서 조금 차이가 난다. 깊게 들어가면 어려울 수 있으니 간단하게 ViewPager가 관리하는 페이지가 얼마 되지 않는 경우에는 FragmentPagerAdapter를, 많으면 FragmentStatePagerAdapter를 사용하도록 하자. 이 둘로 나눴지만 상속해서 작성하게될 Custom FragmentPagerAdatper의 코드상의 차이는 거의 없다.


    2. Custom FragmentPagerAdapter


    앞서 말한대로 여러 개의 화면을 좌우로 슬라이드 할 수 있는 화면을 만들기 위해선 별도의 PageAdapter가 필요하다. 안드로이드에서 FragmentPagerAdapter 클래스를 만들어 뒀으니 이를 상속해서 Custom PageAdapter를 만들 수 있다. 몇가지 오버라이드 함수들만 살펴보자.


    public Fragment getItem(int position)


    n번째 포지션의 Fragment Item 오브젝트 정보를 리턴한다. 채울 화면의 순서를 변경하고 싶다면 여기서 return 하는 Fragment 객체를 position 에 따라서 변경하면 된다. 반드시 구현해야하는 함수다.

        @Override
        public Fragment getItem(int position) {
            Fragment tab = null;
    
            switch (position) {
            case 0:
                tab = new PreviewTab();
                break;
            case 1:
                tab = new CodeTab();
                break;
            }
    
            return tab;
        }
    


    public int getCount()


    ViewPager에 넣을 화면의 개수를 리턴하는 함수다. 이것도 반드시 구현해야 하는 함수다.

        @Override
        public int getCount() {
            return this.mNumOfTabs;
        }
    
        @Override
        public CharSequence getPageTitle(int position) {
            return mTitles[position];
        }


    public Object instantiateItem


    View에 넣을 Page 객체를 리턴해주는 작업. 이미 FragmentPagerAdapter에서 구현을 해뒀기 때문에 따로 오버라이드 할 필요는 없다. 커스텀한 fragment를 사용할 수도 있긴 할텐데 가능하면 부모 함수를 바로 쓰는 것을 추천한다.

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            Fragment fragment = (Fragment) super.instantiateItem(container, position);
            registeredTabs.put(position, (IMarkdownTab)fragment);
            return fragment;
        }
    


    public void destroyItem


    생성한 Fragment를 제거하는 작업이다. instantiateItem 함수에서 부모 함수를 이용했다면 destroyItem 에서도 부모 함수를 이용해서 처리하는 것이 좋다. 그래야만 부모 함수의 변수들과 싱크를 맞출 수 있으니까. 마찬가지로 가능하면 부모 함수를 바로 쓰는 것을 추천한다.

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            super.destroyItem(container, position, object);
        }
    


    전체 코드는 여기서 볼 수 있다.


    3. ViewPager + Custom PageAdapter 


    이제 만든 CustomPageAdapter를 xml의 ViewPager과 연결하면 된다. 아래와 같이 adapter 객체를 선언해준 후 ViewPager의 setAdapter 함수를 통해 연결 해줄 수 있다. 직관적인 코드라 이해하는데 별로 어렵지 않을 것 같다


    adapter = new MarkdownPagerAdapter(getSupportFragmentManager(), Titles,
            selectedImgSrc, unselectedImgSrc, Titles.length);
    viewPager = findViewById(R.id.view_pager);
    viewPager.setAdapter(adapter);
    


    4. ViewPager 페이지 선택 콜백함수


    ViewPager 객체 내에 PageChange 리스너를 등록해서 페이지가 변경 될 때마다 특정한 작업을 하도록 만들 수 있다.


    viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        }
    
        @Override
        public void onPageSelected(int curPosition) {
            IMarkdownTab curImt = adapter.getRegisteredTab(curPosition);
            IMarkdownTab preImt = adapter.getRegisteredTab(prePosition);
    
            if (curPosition == prePosition || curImt == null)
                return;
    
            if (preImt!=null)
                preImt.cbPageUnSelected();
    
            curImt.cbPageSelected();
            prePosition = curPosition;
        }
    
        @Override
        public void onPageScrollStateChanged(int state) {
    
        }
    });
    


    이또한 함수명으로 충분히 언제 불리는지 이해할 수 있을 것 같다. onPageSelected 함수에 넣은 코드는 사용자가 선택한 페이지의 화면을 새로고침 하도록 만든 작업이다.  상황에 맞춰서 커스터마이즈하면 된다. 아 그리고 리스너는 여러 개를 등록 할 수 있다. 난 이 점을 이용해 아래 그림처럼 화면 포커스를 바꿀 때 새로고침과 동시에 바의 위치와 그림을 바꾸기도 했다.      

         

       

    리스너를 이용해 화면 포커스가 바뀔 때 그림 이미지와 바의 위치를 변경 할 수 있었다

    '개발 > 안드로이드' 카테고리의 다른 글

    안드로이드 Service  (0) 2019.03.19
    AsyncTask  (0) 2019.03.13
    px, dp, sp 개념 정리  (0) 2019.02.16
    Device screen dpi 값에 따라 처리하기  (0) 2019.02.16
    안드로이드 선 추가하기  (0) 2019.01.26

    댓글

Designed by Tistory.