2012.05.17 19:23

ViewPager 효과 내기

*ADT 17 버전 부터는 라이브러리 파일을 프로젝트 내 libs 폴더에 넣어야 제대로 인식한다.

 빌드패스를 따로 잡아주지 않아도 자동으로 인식한다.

 샘플 소스는 libs 폴더에 넣지 않았기 때문에 ADT 17버전에서는 실행시 Exception이 발생한다.

 libs 폴더로 jar 파일을 이동시키고 빌드패스를 수정하면 된다.



지난번 ViewPager에 대해서 간단한 예제를 만들어봤다. 이번에는 ViewPager에서 사용하는 다른 Adapter 및 다른 기능에 대해서 조금 설명하고자 한다.


1. Fragment를 사용하는adapter

Fragment는 Android 3.0 (허니콤)부터 추가된 기능이다. Fragment를 잘 모르시는 분이라면 조금만 검색하면 개념적인 내용은 알 수 있다.

개념적 설명 : http://androidhuman.tistory.com/469

실 사용 설명 : http://android-developers.blogspot.com/2011/02/android-30-fragments-api.html



 Fragment를 사용하는 Adapter를 쓴다면 3.0 이전의 버전에서 개발하는 앱에서는 사용을 못하는 것인가? 결론부터 말하면 그렇지 않다. ViewPager를 사용하기 위해 받은 Support Package에는 v4와 v13 2개의 라이브러리가 있다. v4는 api 버전 4. 즉 1.6 도넛 부터 사용할 수 있게 만든 라이브러리 이다. 3.0 이전의 버전에서는 이 라이브러리를 통해서 FragmentPagerAdapter와 FragmentStatePagerAdapter를 사용할 수 있다.


2. FragmentPagerAdapter와 FragmentStatePagerAdapter

Fragment를 처리하는 PagerAdapter는 두 가지 Class가 존재한다. 하나는 FragmentPagerAdapter 이고 다른 하나는 FragmentStatePagerAdapter이다. FragmentPagerAdapter의 경우, 사용자가 ViewPager에서 좌/우로 스크롤(플링)하여 화면 전환을 하여 다음 Fragment가 표시되면 이전 Fragment를 메모리 상에 저장해 만일 사용자가 화면을 반대로 이동하면 메모리 상에 저장되어있는 Fragment를 사용하게된다.

 2번째 FragmentStatePagerAdapter는 ViewPager의 페이지를 이동하여 다음 Fragment가 표시되면 이전 Fragment는 메모리 상에서 제거된다. 사용자가 화면을 다시 반대로 전환하면 기존에 저장된 상태값(state)을 기반으로 재생성합니다.

 그러므로 페이지 수가 정해져 있고 그 수가 많지 않다면 FragmentPagerAdapter를 사용하는 편이 좋고 반대로 페이지 수를 알 수 없거나 많다면 FragmentStatePagerAdapter를 사용하는 것이 좋다.


3. 사용방법

FragmentPagetAdapter나 FragmentStatePagerAdapter 생성자의 파라미터로 FragmentManager를 넘겨주어야 한다. 3.0 이전 버전에서 사용하려면 Activity 대신에 Support Package에 있는 FragmentActivity를 상속받아야 한다.


*Activity의 onCreate 메소드

public class FragmentPagerAdapterSampeActivity extends FragmentActivity {

/** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.viewpager);
        mPager = (ViewPager)findViewById(R.id.pager);
        mPager.setAdapter(new BkFragmentAdapter(getSupportFragmentManager()));
    }

}


FragmentPagerAdapter나 FragmentStatePagerAdapter나 실제 구현하는 소스 부분은 똑같다. 상속받는 클래스명만 바꿔주면 된다.


    //FragmentPager 구현
    private class BkFragmentAdapter extends FragmentPagerAdapter{
        //생성자
        public BkFragmentAdapter(FragmentManager fm) {super(fm);}

        /**
         * 실제 뷰페이저에서 보여질 fragment를 반환.
         * 일반 아답터(갤러리, 리스트뷰 등)의 getView와 같은 역할
         * @param position - 뷰페이저에서 보여저야할 페이지 값( 0부터 )
         * @return 보여질 fragment
         */
        @Override public Fragment getItem(int position) {
            return ArrayFragment.newInstance(position);
        }

        //뷰페이저에서 보여질 총 페이지 수
        @Override public int getCount() { return COUNT; }
    }


일반적인 리스트뷰나 갤러리의 아답터와 비슷하다. 다만 getItem 부분에 Fragment를 반환해야 한다. 여기서 ArrayFragment는 Fragment를 상속받아 실제 fragment를 구현하는 부분이다. 이 부분은 실제 예제를 다운받아 소스를 보면서 이해하는 것이 빠를 것 같아 글로 올리지는 않습니다.


4. ViewPager에서 꼭 알아야 하는 기능

* 현재 페이지 표시하기

좌우로 화면이 전환되는 앱을 보면 상단이나 하단에 현재 페이지가 몇 번째 페이지 인지 표시하는 기능이 있다. 예를 들면 아이폰의 바탕화면 하단에 있는 것이나 고런처의 페이지 표시 같은 기능 말이다.



 


이 기능은 ViewPager의 setOnPageChangeListener 메소드를 통해 OnPageChangeListener를 구현하면 사용할 수 있다.


mPager.setOnPageChangeListener(new OnPageChangeListener() {    //아이템이 변경되면
      //아이템이 선택이 되었으면
     @Override public void onPageSelected(int position) {

         //이전 페이지에 해당하는 페이지 표시 이미지 변경
         mPageMark.getChildAt(mPrevPosition).setBackgroundResource(R.drawable.page_not);


         //현재 페이지에 해당하는 페이지 표시 이미지 변경   
         mPageMark.getChildAt(position).setBackgroundResource(R.drawable.page_select);
         mPrevPosition = position;                //이전 포지션 값을 현재로 변경
     }
    @Override public void onPageScrolled(int position, float positionOffest, int positionOffsetPixels) {}
    @Override public void onPageScrollStateChanged(int state) {}
});

 

 

 



* 특정 페이지로 이동하기

특정 이벤트가 발생했을 때 사용자가 직접 화면 페이지 이동을 하지 않아도 자동으로 페이지가 넘어가야하는 경우가 필요하다. 잡지 앱의 경우 목차에서 페이지를 선택하면 바로 해당 페이지로 이동하는 기능 같은 것 말이다.


이 기능은 ViewPager의 setCurrentItem(int item, boolean smoothScroll) 메소드를 이용하면 간단히 구현 가능하다. Gallery의 setSelection(int position, boolean animate)와 같은 기능이다. Gallery에서 animate가 true던, false던 애니메이션이 동작하지 않는다. 페이지 이동 시 그냥 바로 페이지가 바뀐다.

하지만 ViewPager에서는 이 기능을 완벽히 지원한다. setCurrentItem(int item, boolean smoothScroll) 메소드의 smoothScroll이 false이면 애니메이션 없이 바로 페이지 이동을 하고 smoothScroll이 true이면 애니메이션이 동작하면서 페이지가 자연스럽게 이동한다.


    @Override
    public void onClick(View v) {
        int view = v.getId();
        if(view == R.id.prev){        //이전 버튼
            int cur = mPager.getCurrentItem();    //현재 아이템 포지션
            if(cur > 0)                //첫 페이지가 아니면
                mPager.setCurrentItem(cur-1, isAnimated);    //이전 페이지로 이동
            else                        //첫 페이지 이면
                Toast.makeText(getApplicationContext(), "맨 처음 페이지 입니다.",

                                      Toast.LENGTH_SHORT).show();
        }
        else if(view == R.id.next){    //다음 버튼
            int cur = mPager.getCurrentItem();    //현재 아이템 포지션
            if(cur < COUNT-1)        //마지막 페이지가 아니면
                mPager.setCurrentItem(cur+1, isAnimated);    //다음 페이지로 이동
            else                        //마지막 페이지 이면
                Toast.makeText(getApplicationContext(), "맨 마지막 페이지 입니다.",

                                       Toast.LENGTH_SHORT).show();    //메시지 출력
        }
    }

소스 첨부

출처 : http://blog.daum.net/mailss/16

Trackback 0 Comment 0