반응형

앞선 포스트에서

간단한 ActionBar Tab을 구현해봤습니다.

ActionBar에 Tab을 만드는 방법을 알아보기 위한 예제이기에

각 Tab마다 보이는 View의 변경을

setContentView()메소드를 이용했습니다.


하지만

실제 이런 류의 액션바 탭(ActionBar Tab)을 구현한 앱들을 보면

Tab의 선택으로 뷰가 바뀌기도 하지만


Tab에 따라 보여지는 View를 옆으로 드래그해서

넘기는 경우가 많습니다.

즉, 마치 Page를 넘기듯 화면상의 View를 변경하며

변경되는 View에 맞추어 Tab도 자동으로 바뀌도록 되어 있죠.


여러분이 스마트폰으로 인터넷을 보실 때

화면을 옆으로 드래그 하면 해당 View의 색션이 자동으로 바뀌는 것을 자주

보셨을 겁니다.


그래서

이번 포스트는 Tab의 선택으로도 뷰가 변경되고

View의 Page를 넘기듯 하여 Tab을 변경하도록도 하는 예제를 만들어보겠습니다.


이미 ActionBar에 Tab을 추가하는 예제도 소개했으며

View를 Page 넘기듯 변경하는 ViewPager 예제도 소개했었습니다.


이번 예제는 이 둘을 연결하는 예제입니다.

앞선 포스트의 내용을 참고하시면 이해하시는데 도움이 되시리라 봅니다.


먼저 실행화면부터 소개하겠습니다.


탭(Tab) 선택으로 View변경하기

  



View를 페이지 넘기듯 하여 현재 Tab의 선택 변경하기

   

   

   


각 Tab의 선택에 따라 다른 View가 보이기도 하며

View를 드래그하여 Tab이 변경되는 것도 가능합니다.


실행결과를 보시면 어렵지 않게 어떤 어플인지 인지하실겁니다.



자 그럼

위의 동작이 되도록 ViewPager를 이용한 ActionBar Tab을 만들어보겠습니다.


먼저 Tab은 ActionBar에 추가할 것이므로

레이아웃 파일(activity_main.xml)에는 특별히 작업할 내용이 없지만


Tab에 의해 보여지는 View를 만들어내는

ViewPager를 레이아웃 파일안에 추가하겠습니다.


우선 메인 레이아웃파일입니다.

 

 activity_main.xml

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

    tools:context="${relativePackage}.${activityClass}" >


    <android.support.v4.view.ViewPager

        android:id="@+id/pager"

        android:layout_width="match_parent"

        android:layout_height="match_parent">

        

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


</RelativeLayout>

보시다 시피 단순히 ViewPager 하나가 추가되어 있습니다.


ViewPager에 대한 설명은 ViewPager(뷰페이저) 포스트를 참고하시기 바랍니다.


이제 각 Tab이 선택했을 때 보여질 View의 레이아웃파일을 만들어보겠습니다.

이 레이아웃 xml파일들은 ViewPager가 차례로 View 객체로 만들게 됩니다.


res폴더 >> layout 폴더안에 

3개의 서로 다른 레이아웃 xml 파일을 만들겠습니다.


첫번째 탭(Tab)에 의해 보여질 View 레이아웃 파일입니다.

파일 이름은 'layout_tab_0.xml' 입니다.

 

 layout_tab_0.xml

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

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

    android:layout_width="match_parent"

    android:layout_height="match_parent" >

    

    <AnalogClock 

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_centerInParent="true"/>    


</RelativeLayout>


두번째 탭(Tab)에 의해 보여질 View 레이아웃 파일입니다.

파일 이름은 'layout_tab_1.xml' 입니다.

 

 layout_tab_1.xml

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

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

    android:layout_width="match_parent"

    android:layout_height="match_parent" >

    

    <DigitalClock 

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_centerInParent="true"/>    


</RelativeLayout>


세번째 탭(Tab)에 의해 보여질 View 레이아웃 파일입니다.

파일 이름은 'layout_tab_2.xml' 입니다.

 

 layout_tab_2.xml

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

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

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:padding="15dp" >

    

    <CalendarView 

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:layout_centerInParent="true"/>   


</RelativeLayout>


각 View 마다 서로 다른 Widget를 넣었기에

구별하는데 어렵지 않으리라 봅니다. 

이미 이전 포스트에서도 만들어봤던 파일들입니다.


 

다음으로

MainActivity 자바파일을 만들기 전에

ViewPager가 View를 옆으로 드래그(페이지를 넘기듯)했을 때

보여질 View들을 만들어 내는 CustomAdapter를 만들겠습니다.

(앞선 ViewPager 포스트를 참고하시기 바랍니다.)


코드의 의미는 주석으로 설명합니다.


 

CustomAdapter.java

public class CustomAdapter extends PagerAdapter {

LayoutInflater inflater;

public CustomAdapter(LayoutInflater inflater) {

// TODO Auto-generated constructor stub

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

this.inflater=inflater;

}


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

//Tab에 따른 View를 보여줘야 하므로 Tab의 개수인 3을 리턴..

@Override

public int getCount() {

// TODO Auto-generated method stub

return 3; //보여줄 View의 개수 리턴(Tab이 3개라서 3을 리턴)

}

//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;//현재 position에서 보여줘야할 View를 생성해서 리턴...

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

//position마다 다른 View를 생성

//만들어질 View의 설계는 res폴더>>layout폴더안에 3개의 레이아웃 파일 사용

switch( position ){

case 0: //첫번째 Tab을 선택했을때 보여질 뷰

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

break;

case 1: //두번째 Tab을 선택했을때 보여질 뷰

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

break;

case 2: //세번째 Tab을 선택했을때 보여질 뷰

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

break;

}

//ViewPager에 위에서 만들어 낸 View 추가

if(view != null) container.addView(view);

//세팅된 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;

}


}



이제 이 CustomAdapter ViewPager에 적용하고

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


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

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

다시 말하지만 주석을 제외하면 코드가 별로 길지 않습니다.

미리 겁먹지 않으시길 바랍니다.

 

 MainActivity.java

public class MainActivity extends Activity {

ViewPager pager; //ViewPager 참조변수

ActionBar actionBar;  //ActionBar 참조변수


@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

//Activity 객체는 이미 ActionBar를 가지고 있으므로

//이미 존해하는 ActionBar 객체를 얻어오기.(API 10버전 이상)

actionBar= getActionBar();

//ActionBar가 Tab를 보여줄 수 있는 모양이 되도록 설정

actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

//ViewPager 객체 참조

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);

//ViewPager에게 Page의 변경을 인지하는 Listener 세팅.

//마치 클릭상황을 인지하는 OnClickListener와 같은 역할..

pager.setOnPageChangeListener(new OnPageChangeListener() {

//Page가 일정부분 넘겨져서 현재 Page가 바뀌었을 때 호출

//이전 Page의 80%가 이동했을때 다음 Page가 현재 Position으로 설정됨.

//파라미터 : 현재 변경된 Page의 위치

@Override

public void onPageSelected(int position) {

// TODO Auto-generated method stub

//ViewPager는 3개의 View를 가지고 있도록 설계하였으므로.

//Position도 역시 가장 왼쪽 처음부터(0,1,2 순으로 되어있음)

//현재 전면에 놓여지는 ViewPager의 Page에 해당하는 Position으로

//ActionBar의 Tab위치를 변경.

actionBar.setSelectedNavigationItem(position);

}

@Override

public void onPageScrolled(int arg0, float arg1, int arg2) {

// TODO Auto-generated method stub

}

@Override

public void onPageScrollStateChanged(int arg0) {

// TODO Auto-generated method stub

}

});

//ActionBar에 추가 될 Tab 참조변수

Tab tab=null;

//첫번째 Tab 객체 생성 및 ActionBar에 추가하기

tab= actionBar.newTab(); //ActionBar에 붇는 Tab객체 생성

tab.setText("Analog");    //Tab에 보여지는 글씨

//Tab의 선택이 변경되는 것을 인지하는 TabListener 설정(아래쪽 객체 생성 코드 참고)

tab.setTabListener(listener); 

//ActionBar에 Tab 추가

actionBar.addTab(tab);

//두번째 Tab 객체 생성 및 ActionBar에 추가하기

tab= actionBar.newTab(); //ActionBar에 붇는 Tab객체 생성

tab.setText("Digital");     //Tab에 보여지는 글씨

//Tab의 선택이 변경되는 것을 인지하는 TabListener 설정(아래쪽 객체 생성 코드 참고)

tab.setTabListener(listener);

//ActionBar에 Tab 추가

actionBar.addTab(tab);

//세번째 Tab 객체 생성 및 ActionBar에 추가하기

tab= actionBar.newTab(); //ActionBar에 붇는 Tab객체 생성

tab.setText("Calendar");   //Tab에 보여지는 글씨

//Tab의 선택이 변경되는 것을 인지하는 TabListener 설정(아래쪽 객체 생성 코드 참고)

tab.setTabListener(listener); 

//ActionBar에 Tab 추가

actionBar.addTab(tab);

}//onCreate Method...

//ActionBar의 Tab 선택에 변화가 생기는 것을 인지하는 리스너(Listener)

TabListener listener= new TabListener() {

//Tab의 선택이 벗어날 때 호출

//첫번째 파라미터 : 선택에서 벗어나는 Tab 객체

//두번째 파라미터 : Tab에 해당하는 View를 Fragment로 만들때 사용하는 트랜젝션.(여기서는 사용X)

@Override

public void onTabUnselected(Tab tab, FragmentTransaction ft) {

// TODO Auto-generated method stub

}

//Tab이 선택될 때 호출

//첫번째 파라미터 : 선택된 Tab 객체

//두번째 파라미터 : Tab에 해당하는 View를 Fragment로 만들때 사용하는 트랜젝션.(여기서는 사용X)

@Override

public void onTabSelected(Tab tab, FragmentTransaction ft) {

// TODO Auto-generated method stub

//선택된 Tab객체의 위치값(왼족 처음부터 0,1,2....순으로 됨)

int position = tab.getPosition();

//Tab의 선택 위치에 따라 ViewPager에서 보여질 Item(View)를 설정

//첫번째 파라미터: ViewPager가 현재 보여줄 View의 위치

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

pager.setCurrentItem(position,true);

}

//Tab이 재 선택될 때 호출

//첫번째 파라미터 : 재 선택된 Tab 객체

//두번째 파라미터 : Tab에 해당하는 View를 Fragment로 만들때 사용하는 트랜젝션.(여기서는 사용X)

@Override

public void onTabReselected(Tab tab, FragmentTransaction ft) {

// TODO Auto-generated method stub

}

};

}


여기까지 ViewPager를 이용한 ActionBarTab을 구현해보았습니다.


사실 이번 예제소스는 단순히 Tab에 의해 다른 레이아웃의 View가 보여지기만 할 뿐

각 레이아웃의 View들을 제어하고 있지는 않습니다.


하지만 실제 어플에서는 이 View들을 제어하는 경우가 많습니다.

이번에 소개한 예제는 그 작업을 하기에는 별로 효율적이지 않은 예제 소스입니다.


다음번 포스트에서 이를 해결하기 위해

Fragment를 사용한 ViewPager ActionBar Tab을 만들어보겠습니다.


반응형

+ Recent posts