반응형
블로그 이미지
개발자로서 현장에서 일하면서 새로 접하는 기술들이나 알게된 정보 등을 정리하기 위한 블로그입니다. 운 좋게 미국에서 큰 회사들의 프로젝트에서 컬설턴트로 일하고 있어서 새로운 기술들을 접할 기회가 많이 있습니다. 미국의 IT 프로젝트에서 사용되는 툴들에 대해 많은 분들과 정보를 공유하고 싶습니다.
솔웅

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리


반응형

이번에 POC 작업을 하면서 좀 자세히 알아야 되겠다라고 생각한게 ViewPager 기능입니다.
슬라이드 형식으로 좌우로 페이지를 넘기는 건데요.
ViewFlipper가 미리 여러개의 페이지를 ViewFlipper 에 넣은 다음에 페이지 넘김 효과를 주는 것처럼 이 ViewPager도 여러개의 페이지를 ViewPager에 넣어서 페이지 넘김 효과를 줍니다.


다른점은 ViewFlipper는 안드로이드에서 기본적으로 제공하는 API 이고 ViewPager는 기본 API 에 속하지 않은 부속 기능이라서 해당 jar 파일을 이클립스에 plug-in 한 다음에 사용한다는 겁니다.


Java Build Path - Libraries - android-support-v4.jar 등록

그리고 예제를 봤더니 ViewFlipper는 animation xml을 통해서 여러 페이지 넘김 효과를 주는 데 반해 ViewPager는 슬라이드 효과만 주고 있네요.
ViewFlipper가 더 많은 기능을 가지고 있는거 같긴한데.. 


그래도 일단 ViewPager에 대해서 한번 분석해 들어가 보겠습니다.


예제소스는 http://android-town.org/ 로 가면 무료로 제공하고 있으니 필요하신 분들은 받으셔서 보셔도 됩니다.

동영상강좌는 http://www.youtube.com/user/easyspub 에서 제공되고 있습니다.

책을 직접 구입하셔서 보시면 훨씬 더 도움이 될 것 같네요.




ViewPager

안드로이드 개발자 사이트에 소개된 ViewPager 관련 설명은 아래와 같습니다.

안드로이드 Developer 사이트 (API)
   
유저가 페이지를 오른쪽 왼쪽으로 flip 하도록 해 주는 Layout manager. 보여질 view를 generate 하기 위해 PagerAdapter를 import 해 사용해야 한다.
현재 버전은 초기 버전이고 이 후 업데이트에서는 새로운 버전에 맞게 변화가 있게 될 것이다.
viewPager는 Fragment 와 같이 어우러져서 사용된다. 이 Fragment는 각 페이지의 lifecycle을 관리하기 편리하도록 돼 있다.
ViewPager 와 함께 fragment들을 사용하기 위해 standard adapter들이 implement 돼 있다.
FragmentPagerAdaper와 FragmentStatePagerAdapter 클래스들은 full user interface를 아주 간단하게 만들 수 있도록 도와 준다.

그리고 아래 예제를 다룰 때도 설명이 될 텐데요.
ViewPager와 같이 사용되야 할 PagerAdapter 의 주요 메소드를 간단히 살펴 보겠습니다.
   
PagerAdapter API

getCount() : 현재 PagerAdapter 에서 관리할 갯수
instantiateItem() : ViewPager에서 사용할 뷰객체 생성 및 등록
destroyItem() : View 객체를 삭제 한다.
isViewFromObject() :instantiateItem 메소드에서 생성한 객체를 이용할 것인지 여부를 반환한다.
restoreState() : saveState() 상태에서 저장했던 Adapter와 page를 복구한다.
saveState() : 현재 UI 상태를 저장하기 위해 Adapter와 Page 관련 인스턴스 상태를 저장한다.
startUpdate() : 페이지 변경이 시작될 때 호출 된다.
finishUpdate() : 페이지 변경이 완료 됐을 때 호출 된다.


이제 Do it 안드로이드 앱 프로그래밍 책에서 제공하는 SampleViewPager라는 소스를 분석해 보도록 하겠습니다.
먼저 layout xml 파일 부터 분석하겠습니다.

activity_main.xml


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="ViewPager 사용하기"
        />

    <android.support.v4.view.ViewPager
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#ffffffff"
        />
</LinearLayout>



앱을 시작하면 화면을 구성할 첫번째 Layout xml 파일 입니다.
LinearLayout 으로 전체 구성을 잡았고 그 안에 TextView와 ViewPager 를 넣었습니다.
TextView는 좌우로는 화면을 꽉 채우고 높이는 내용만큼만 자리를 차지하도록 했네요.
그 이하 공간은 모두 ViewPager 가 차지할 겁니다.
아마 ViewPager 사용하기라는 글자는 그대로 있으면서 그 아래 ViewPager 공간만 slide 될 것 같습니다.

다음은 자바 파일을 보죠.



public class MainActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // get a ViewPager reference and set adapter for it
        ViewPager pager = (ViewPager) findViewById(R.id.pager);
        ViewPagerAdapter adapter = new ViewPagerAdapter(this);
        pager.setAdapter(adapter);
    }

    public class ViewPagerAdapter extends PagerAdapter {
        // sample names
        private String[] names = { "John", "Mike", "Sean" };
        // sample image resource ids
        private int[] resIds = {R.drawable.dream01, R.drawable.dream02, R.drawable.dream03};
        // sample call numbers
        private String[] callNumbers = {"010-7777-1234", "010-7788-1234", "010-7799-1234"};

        /**
         * Context
         */
        private Context mContext;

        /**
         * Initialize
         *
         * @param context
         */
        public ViewPagerAdapter( Context context ) {
            mContext = context;
        }
        /**
         * Count of pages
         */
        public int getCount() {
            return names.length;
        }
        /**
         * Called before a page is created
         */
        public Object instantiateItem(View pager, int position) {
            // create a instance of the page and set data
            PersonPage page = new PersonPage(mContext);
            page.setNameText(names[position]);
            page.setImage(resIds[position]);
            page.setCallNumber(callNumbers[position]);

            // add to the ViewPager
            ViewPager curPager = (ViewPager) pager;
            curPager.addView(page, position);

            return page;
        }

        /**
         * Called to remove the page
         */
        public void destroyItem(View pager, int position, Object view) {
            ((ViewPager)pager).removeView((PersonPage)view);
        }
        public boolean isViewFromObject(View view, Object object) {
            return view.equals(object);
        }
        public void finishUpdate( View view ) {
        }
        public void restoreState( Parcelable p, ClassLoader c ) {
        }
        public Parcelable saveState() {
            return null;
        }
        public void startUpdate( View view ) {
        }
    }
}


위 이미지는 여기에서 다운 받은 이미지 입니다.


제 Laptop 에 영문 윈도우가 깔려 있어서 한글이 깨지네요.
그래서 한글로 된 주석은 지웠습니다. 이전 글에 있는 링크에서 소스파일을 다운 받아 보시면 한글 주석을 보실 수 있을 겁니다.

우선 맨 먼저 실행될 onCreate() 메소드를 보겠습니다.
activity_main.xml 을 layout을 구성하는 xml로 사용하겠다고 세팅한 라인이 있구요.
바로 그 밑에 ViewPager의 instance를 만들고 거기에 activity_main.xml 에 선언한 id가 pager 인 ViewPager를 대입했습니다.
그리고 ViewPagerAdapter 에 대한 인스턴스도 만들어서 방금전 만들었던 ViewPager 에 이 adapter를 세팅했습니다.

이 ViewPagerAdapter 는 어디서 왔을 까요? 안드로이드에서 제공하는 함수는 아니고 개발자가 만든 클래스 입니다.
바로 아래에 그 클래스가 있습니다.

ViewPagerAdater 클래스는 PagerAdapter를 extends 하네요.
이 PagerAdapter 는 안드로이드에서 제공하는 API 입니다.

이 PagerAdapter에 대해 안드로이드 개발자 페이지 (API) 에서는 아래와 같이 설명했네요.


ViewPager안에 페이지들을 생성하기 위해 Base Class 는 이 adapter를 제공한다. 이것과 관련해 좀 더 특정 implementation을 사용하고 싶어 할 것이다.
예를 들어 FragmentPagerAdapter 나 FragmentStatePagerAdapter 같은....

PagerAdapter를 implement 하면 최소한 다음과 같은 메소드들을 override 해야 한다.



그 다음에도 계속 설명이 나오는데요.
너무 길고.. 나중에 필요하면 따로 정리를 해야겠습니다.

일단 이 PagerAdapter에는 ViewPager에서 사용할 페이지들이 들어가는군요.
이 예제에서는 이 PagerAdapter를 extends 한 ViewPagerAdapter인 클래스를 만들었구요. 여기다가 보일 페이지들을 넣을건가 봅니다.

그러면 이 ViewPagerAdapter 클래스를 살펴 보겠습니다.

처음에는 names, resIds, callNumbers라고 하는 배열들을 만들었습니다.
names에는 사람 이름이 그리고 resIds에는 이미지 resource들이 마지막으로 callNumbers 에는 전화번호들이 들어가는군요.

그 다음에는 Context를 초기화 했습니다.

다음 생성자에서는 Context를 파라미터로 받아서 mContext에 대입했네요.
이 클래스가 호출이 되면 가장 먼저 이 생성자가 실행이 될 겁니다.
그러니까 가장 먼저 일단 context를 세팅한다는 얘기죠.

이 Context는 어플리케이션이 실행되기 위해 기본적으로 필요한 정보나 환경들에 대한 내용인데 안드로이드에서 제공하는 겁니다.
getSystemService() 메소드를 통해서 여러 많은 정보들을 가져다 쓸 수도 있죠.
그리고 Activity가 이 Context를 상속 받았습니다.
그러니까 Activity 를 상속받은 클래스에서는 이 Context를 그냥 this 라는 구문으로 사용할 수 있는 겁니다.
하지만 Activity 가 아닌 다른 Context를 상속받지 않은 클래스에서는 this 라는 것으로 Context를 사용하도록 할 수 없겠죠.
제 기억엔 별도로 만든 클래스에서  Intent 나 뭐 이런걸로 Page 전환 할 때 문제가 발생할 수 있습니다.
모르면 당황할 텐데요. 그냥 View의 객체가 있으면 그 View의 getContext() 를 사용해서 처리하시면 됩니다.
혹은 getApplicationContext() 를 사용하셔도 되구요.
저는 대부분 getApplicationContext()를 사용했던 것 같습니다.

그 다음에는 위에서 설명했던 PagerAdapter API 에 있던 메소드들이 있네요.
getCount() 메소드에는 페이지 수가 들어간다는데 이 예제에서는 names 배열내의 아이템 갯수가 페이지 수가 되도록 했습니다.

그 다음 메소드가 ViewPager에서 사용할 View 객체를 생성하고 등록한다는 instantiateItem() 메소드 입니다.

이 메소드는 View 와 int 형의 position을 파라미터로 받습니다.
그 내용은 우선 PersonPage라는 클래스의 인스턴스를 만드네요. 여기에 mContext를 파라미터로 던지구요.
이 PersonPage는 안드로이드에서 제공하는 API 클래스가 아니니까 아마 개발자가 따로 만들었을 겁니다.
나중에 그 클래스도 분석해 보게 되겠네요.
일단 뭔지는 모르지만 PersonPage의 인스턴스를 만들었고 여기에 names와 resIds와 callNumbers 에 있는 아이템들을 세팅합니다.
보니까 PersonPage 클래스에는 setNameText(), setImage(), setCallNumber() 라는 메소드들이 작성 돼 있나 봅니다.

그 다음에는 ViewPager의 인스턴스를 만들고 이 ViewPager에 이 PersonPage (page)와 position (페이지 번호)를 add 해 줍니다.
그러면 ViewPager에는 해당 페이지의 name과 image와 callNumber들이 들어있을 테고 즉 화면에 그게 display 되겠네요.




다음은 view 객체를 삭제하는 destroyItem() 메소드가 있습니다.
View와 int 형으로 페이지번호와 Object 를 파라미터로 봤습니다.
그리고 그 내용은 해당 view를 remove 합니다.
그 다음 finishUpdate(), restoreState(),startUpdate() 는 모두 내용이 없는 껍데기 메소드들이구요.
즉 다른 특별한 코딩을 하지 않아서 어떤 기능 추가나 변경 없이 그냥 override 만 했을 뿐이네요.
saveState() 메소드에서도 그냥 null을 반환할 뿐입니다.

이렇게 되면 MainActivity.java는 모두 분석했습니다.

ViewPager 를 사용하도록 레이아웃 xml 과 onCreate() 에서 선언을 해주고 ViewPager의 페이지들은 ViewPagerAdapter 클래스에서 만들었습니다.
이 ViewPagerAdapter에는 각 화면들에 들어갈 내용들을 배열에 넣었구요.
그 화면들을 어떻게 구성할 것인지는 PersonPage라는 클래스를 외부에 따로 만들어서 사용하고 있습니다.

반응형