이전 포스트에서 소개한

ViewFlipper

대량의 이미지나 텍스트를

하나씩 변경하면서 소개하는

'슬라이드 보기' 같은

기능에 적합합니다.


이번에 소개할 예제소스는

'만화보기'처럼

Page를 넘겨가면서

보는데 적합한 예제입니다.


마치 Page를 넘기듯이

손가락으로 드래그해서

좌우로 넘기는 UI를 보신적이 있을 겁니다.


안드로이드의 기본 api에는 제공되지 않지만

Support Library에 포함되어 있는 녀석입니다.


ViewPager 라는 이름을 가지고 있으며

이름으로도 연상이 되듯이 View들을 Page를 넘기듯

보여주는 AdapterView의 일종입니다.


AdapterView의 대표적인 종류인

ListView와 매우 비슷하게 제작됩니다.


ListView의 CustomAdapter를 구현할 수 있다면

어렵지 않게 이해하실 수 있습니다.


혹시 잘 모르시는 분은


[안드로이드 Android] 리스트 뷰(ListView) 6. Custom ListView(사용자 정의 리스트 뷰) - BaseAdapter


포스트를 참고하세요.



이번에 소개할 ViewPager예제는

많은 양의 이미지를 한장씩 Page를 넘기면서

볼 수있는 예제입니다.


이미지는 10장만 쓰겠습니다.


손가락으로 넘길 수도 있으며

위의 버튼을 이용해서 앞뒤장을 넘어갈 수도 있게 하겠습니다.


먼저 결과화면을 그림 여러장으로 보여드리겠습니다.


시작화면-첫번째 페이지



두번째 Page로 드래그해서 넘기기

  


세번째 Page로 드래그해서 넘기기

  


Next버튼으로 넘기기

  


Previous 버튼으로 앞장으로 넘기기

 


사진으로도 충분히 이해가 가능하리라 판단되어

gif 파일로 보여드리지는 않습니다.


자. 이제 결과화면을 봤으니

만들어 보겠습니다.


먼저 그림에 사용할 이미지 10장은

첨부파일에서 다운받으시기 바랍니다.



게임타이틀 이미지.zip



가장 먼저 Main 레이아웃 파일입니다.

ListView와 매우 흡사합니다.

가장 주의할 것은 ViewPager를 기본 api가 아니므로

android.support.v4.view  패키지명을 앞에 표기해야 한다는 겁니다.

자동으로 작성되지 않으므로 철자에 주의해서 작성 하셔야 합니다.

 

 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">

    

    <LinearLayout 

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:orientation="horizontal"

        android:padding="3dp">

        

        <Button android:id="@+id/btn_previous"

            android:layout_width="0dp"

            android:layout_height="wrap_content"

            android:layout_weight="1"

            android:text="PREVIOUS"

            android:textSize="12sp"

            android:onClick="mOnClick"/>

        

        <Button android:id="@+id/btn_next"

            android:layout_width="0dp"

            android:layout_height="wrap_content"

            android:layout_weight="1"

            android:text="Next"

            android:textSize="12sp"

            android:onClick="mOnClick"/>

        

    </LinearLayout>

    

    <android.support.v4.view.ViewPager

        android:id="@+id/pager"

        android:layout_width="match_parent"

        android:layout_height="match_parent">

        

    </android.support.v4.view.ViewPager>    


</LinearLayout>



굵은 글씨의 ViewPager는 AdapterView 입니다.


Adapter란,

대량의 Data(여기서는 Image들)들

보여주기 위해 View를 여러개 만들어서 ViewGroup에 추가해줘야 하는데

이 작업을 Data의 순서에 맞게 적절한 View로 만들어 주는 클래스 객체를 말합니다.

(Custom ListView 참조)


이 ViewPager에 붙일 Adapter는

위 설명처럼 Image를 보여주기 위한 ImageView를 만들어 내는 기능이 있어야 합니다.


그래서 우선 만들어낼 ImageView의 모양을 설정하는 Layout 파일부터 만들겠습니다.


 

 viewpager_childview.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical" >

    

    <ImageView 

        android:id="@+id/img_viewpager_childimage"

        android:layout_width="match_parent"

        android:layout_height="match_parent"/>    


</LinearLayout>


ViewPager가 만들어낼 한 Page의 모양이 이렇게 생길 것이다 라는 것이죠.

이 예제에서는 ImageView 하나를 화면에 꽉 차게 만들겠다는 거죠.


이제 이 레이아웃 파일을 실제

View 객체로 만들어서 해당하는 순번에 따라 적절한 Image를 보여주는

Adapter를 만들어 보겠습니다.


이전에 소개한 Custom ListView의 예제와 같은 작업인데

그때는 BaseAdapter를 상속받아 만들었습니다.


이번 Adapter는 PagerAdapter를 상속받아 만든다는 것이 다르며

안에 오버라이드해서 만들 메소드도 약간 차이가 있습니다.


세부 설명은 주석으로 표기했습니다.

지면상 간략한 설명이어서 이해하기 어려울 수도 있으니

코드를 보고 해석할 수 있는 부분까지 해석해서

활용하시고 좀더 깊은 이해는 다른 자료들을 서베이 하시기 바랍니다.


PagerAdapter를 상속받은 CustomAdapter 클래스를 설계합니다.


만드는 과정은 그림으로 보여드립니다.


  


이렇게 만드시면 자동으로 2개의 메소드가 오버라이드(override) 되어 있을 겁니다.

getCount(), isViewFromObject()


추가적으로 필요한 2개의 메소드를 오버라이드 합니다.

instantiateItem(), destroyItem()

파라미터 중 첫번째가 ViewGroup인것을 오버라이드합니다.

View인 것은 deprecated 되었습니다.


커스텀 아답터(Custom Adapter) 소스 파일입니다.

 

 CustomAdapter.java

public class CustomAdapter extends PagerAdapter {

LayoutInflater inflater;

public CustomAdapter(LayoutInflater inflater) {

// TODO Auto-generated constructor stub

//전달 받은 LayoutInflater를 멤버변수로 전달

this.inflater=inflater;

}


//PagerAdapter가 가지고 잇는 View의 개수를 리턴

//보통 보여줘야하는 이미지 배열 데이터의 길이를 리턴

@Override

public int getCount() {

// TODO Auto-generated method stub

return 10; //이미지 개수 리턴(그림이 10개라서 10을 리턴)

}

//ViewPager가 현재 보여질 Item(View객체)를 생성할 필요가 있는 때 자동으로 호출

//쉽게 말해, 스크롤을 통해 현재 보여져야 하는 View를 만들어냄.

//첫번째 파라미터 : ViewPager

//두번째 파라미터 : ViewPager가 보여줄 View의 위치(가장 처음부터 0,1,2,3...)

@Override

public Object instantiateItem(ViewGroup container, int position) {

// TODO Auto-generated method stub

View view=null;

//새로운 View 객체를 Layoutinflater를 이용해서 생성

//만들어질 View의 설계는 res폴더>>layout폴더>>viewpater_childview.xml 레이아웃 파일 사용

view= inflater.inflate(R.layout.viewpager_childview, null);

//만들어진 View안에 있는 ImageView 객체 참조

//위에서 inflated 되어 만들어진 view로부터 findViewById()를 해야 하는 것에 주의.

ImageView img= (ImageView)view.findViewById(R.id.img_viewpager_childimage);

//ImageView에 현재 position 번째에 해당하는 이미지를 보여주기 위한 작업

//현재 position에 해당하는 이미지를 setting

img.setImageResource(R.drawable.gametitle_01+position);

//ViewPager에 만들어 낸 View 추가

container.addView(view);

//Image가 세팅된 View를 리턴

return view;

}

//화면에 보이지 않은 View는파쾨를 해서 메모리를 관리함.

//첫번째 파라미터 : ViewPager

//두번째 파라미터 : 파괴될 View의 인덱스(가장 처음부터 0,1,2,3...)

//세번째 파라미터 : 파괴될 객체(더 이상 보이지 않은 View 객체)

@Override

public void destroyItem(ViewGroup container, int position, Object object) {

// TODO Auto-generated method stub

//ViewPager에서 보이지 않는 View는 제거

//세번째 파라미터가 View 객체 이지만 데이터 타입이 Object여서 형변환 실시

container.removeView((View)object);

}

//instantiateItem() 메소드에서 리턴된 Ojbect가 View가  맞는지 확인하는 메소드

@Override

public boolean isViewFromObject(View v, Object obj) {

// TODO Auto-generated method stub

return v==obj;

}


}


ListView의 CustomAdapter와 방법은 다소 다르지만

해야하는 작업은 같습니다.



이제 이 CustomAdapter를 ViewPager에 적용하고

버튼으로 제어하는 작업을 하겠습니다.


메인 액티비티 소스파일입니다.

설명은 주석을 참고하세요.


 

 MainActivity.java

public class MainActivity extends Activity {

ViewPager pager;


@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

pager= (ViewPager)findViewById(R.id.pager);

//ViewPager에 설정할 Adapter 객체 생성

//ListView에서 사용하는 Adapter와 같은 역할.

//다만. ViewPager로 스크롤 될 수 있도록 되어 있다는 것이 다름

//PagerAdapter를 상속받은 CustomAdapter 객체 생성

//CustomAdapter에게 LayoutInflater 객체 전달

CustomAdapter adapter= new CustomAdapter(getLayoutInflater());

//ViewPager에 Adapter 설정

pager.setAdapter(adapter);

}

//onClick속성이 지정된 View를 클릭했을때 자동으로 호출되는 메소드

public void mOnClick(View v){

int position;

switch( v.getId() ){

case R.id.btn_previous://이전버튼 클릭

position=pager.getCurrentItem();//현재 보여지는 아이템의 위치를 리턴

//현재 위치(position)에서 -1 을 해서 이전 position으로 변경

//이전 Item으로 현재의 아이템 변경 설정(가장 처음이면 더이상 이동하지 않음)

//첫번째 파라미터: 설정할 현재 위치

//두번째 파라미터: 변경할 때 부드럽게 이동하는가? false면 팍팍 바뀜

pager.setCurrentItem(position-1,true);

break;

case R.id.btn_next://다음버튼 클릭

position=pager.getCurrentItem();//현재 보여지는 아이템의 위치를 리턴

//현재 위치(position)에서 +1 을 해서 다음 position으로 변경

//다음 Item으로 현재의 아이템 변경 설정(가장 마지막이면 더이상 이동하지 않음)

//첫번째 파라미터: 설정할 현재 위치

//두번째 파라미터: 변경할 때 부드럽게 이동하는가? false면 팍팍 바뀜

pager.setCurrentItem(position+1,true);

break;

}

}

}


코드는 엄처 간단하죠.


실제로 매우 사용성이 높은 View이니 만큼 여러분이

제작하고자 하는 앱에 적절히 활용할 수 있기를 바랍니다.

Posted by KiteSoft OopsAndroid