Android TabLayout 및 ViewPager
이 튜토리얼에서는 이 튜토리얼에서 이미 구현한 TabLayout 아래에 ViewPager를 구현할 것입니다.
Android TabLayout ViewPager 개요
ViewPager는 데이터 페이지를 스와이프하는 데 사용됩니다. 일반적으로 조각과 함께 사용됩니다. 이전 튜토리얼에서 아래와 같이 레이아웃을 수정해 봅시다. activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.journaldev.tablayoutviewpager.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/AppTheme.PopupOverlay" />
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
style="@style/MyStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabGravity="fill"
app:tabMode="fixed" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
android:src="@android:drawable/ic_dialog_email" />
</android.support.design.widget.CoordinatorLayout>
MainActivity에 ViewPager를 추가하기 전에 어댑터를 설정하겠습니다.
public class ViewPagerAdapter extends FragmentPagerAdapter {
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
Fragment fragment = null;
if (position == 0)
{
fragment = new FragmentA();
}
else if (position == 1)
{
fragment = new FragmentB();
}
else if (position == 2)
{
fragment = new FragmentC();
}
return fragment;
}
@Override
public int getCount() {
return 3;
}
@Override
public CharSequence getPageTitle(int position) {
String title = null;
if (position == 0)
{
title = "Tab-1";
}
else if (position == 1)
{
title = "Tab-2";
}
else if (position == 2)
{
title = "Tab-3";
}
return title;
}
}
위의 ViewPagerAdapter는 FragmentPagerAdapter를 확장합니다. 각 페이지에 하나씩 세 개의 Fragment를 호출합니다. 각 프래그먼트는 fragment_list.xml
아래에 표시된 대로 ListView를 보유합니다.
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/list"/>
FragmentA(/B/C).java는 다음과 같습니다.
public class FragmentA extends Fragment {
ListView list;
public FragmentA() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment, container, false);
list = (ListView) view.findViewById(R.id.list);
ArrayList stringList= new ArrayList();
stringList.add("Item 1A");
stringList.add("Item 1B");
stringList.add("Item 1C");
stringList.add("Item 1D");
stringList.add("Item 1E");
stringList.add("Item 1F");
stringList.add("Item 1G");
stringList.add("Item 1H");
stringList.add("Item 1I");
stringList.add("Item 1J");
stringList.add("Item 1K");
stringList.add("Item 1L");
stringList.add("Item 1M");
stringList.add("Item 1N");
stringList.add("Item 1O");
stringList.add("Item 1P");
stringList.add("Item 1Q");
stringList.add("Item 1R");
stringList.add("Item 1S");
stringList.add("Item 1T");
stringList.add("Item 1U");
stringList.add("Item 1V");
stringList.add("Item 1W");
stringList.add("Item 1X");
stringList.add("Item 1Y");
stringList.add("Item 1Z");
CustomAdapter adapter = new CustomAdapter(stringList,getActivity());
list.setAdapter(adapter);
return view;
}
}
위의 ListView에 대한 CustomAdapter.java 클래스는 다음과 같습니다.
public class CustomAdapter extends ArrayAdapter {
private ArrayList dataSet;
Context mContext;
// View lookup cache
private static class ViewHolder {
TextView txtName;
}
public CustomAdapter(ArrayList data, Context context) {
super(context, R.layout.row_item, data);
this.dataSet = data;
this.mContext = context;
}
@Nullable
@Override
public String getItem(int position) {
return dataSet.get(position);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder; // view lookup cache stored in tag
if (convertView == null) {
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.row_item, parent, false);
viewHolder.txtName = (TextView) convertView.findViewById(R.id.name);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.txtName.setText(getItem(position));
// Return the completed view to render on screen
return convertView;
}
}
MainActivity.java 클래스는 다음과 같습니다.
public class MainActivity extends AppCompatActivity {
TabLayout tabLayout;
ViewPager viewPager;
ViewPagerAdapter viewPagerAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
viewPager = (ViewPager) findViewById(R.id.viewPager);
viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(viewPagerAdapter);
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
}
}

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ListView xmlns:android="https://schemas.android.com/apk/res/android"
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.v4.widget.NestedScrollView>

Android TabLayout ViewPager 프로젝트 구조

Android TabLayout ViewPager 예제 코드
activity_main.xml, MainActivity.java 및 ViewPagerAdapter.java 클래스는 변경되지 않습니다. 이제 프래그먼트를 살펴보겠습니다. 조각의 레이아웃은 다음과 같습니다. fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="https://schemas.android.com/apk/res/android" />
FragmentA(/B/C).java
는 다음과 같습니다.
package com.journaldev.tablayoutviewpager;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class FragmentA extends Fragment {
RecyclerView recyclerView;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(
R.layout.fragment, container, false);
return rootView;
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
String[] items = getResources().getStringArray(R.array.tab_A);
RecyclerViewAdapter adapter = new RecyclerViewAdapter(items);
recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
}
}
표시할 데이터를 strings.xml 파일로 옮겼습니다. 거기에 다음과 같이 정의되어 있습니다.
<resources>
<string name="app_name">TabLayoutViewPager</string>
<string name="action_settings">Settings</string>
<string-array name="tab_A">
<item>Item 1A</item>
<item>Item 1B</item>
</string-array>
<string-array name="tab_B">
<item>Item 2A</item>
</string-array>
</resources>
참고: 어댑터를 채우고 보기가 생성되면 표시하도록 조각 코드 논리를 최적화했습니다. RecyclerViewAdapter.java
에는 인수로 문자열 배열이 있습니다. 이에 대한 코드는 다음과 같습니다.
public class RecyclerViewAdapter extends RecyclerView.Adapter {
String[] items;
public RecyclerViewAdapter(String[] items) {
this.items = items;
}
@Override
public TextItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_view_list_item, parent, false);
return new TextItemViewHolder(view);
}
@Override
public void onBindViewHolder(TextItemViewHolder holder, int position) {
holder.bind(items[position]);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getItemCount() {
return items.length;
}
}
위의 코드에서 목록 항목과 유사한 레이아웃을 가진 사용자 지정 RecyclerViewHolder 클래스를 추가했습니다. TextItemViewHolder.java
클래스는 아래와 같습니다.
public class TextItemViewHolder extends RecyclerView.ViewHolder {
private TextView textView;
public TextItemViewHolder(View itemView) {
super(itemView);
textView = (TextView) itemView.findViewById(R.id.list_item);
}
public void bind(String text) {
textView.setText(text);
}
}
위 사용자 지정 ViewHolder의 레이아웃은 recycler_view_list_item.xml
입니다.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/list_item"
android:textSize="18sp"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingRight="8dp"
android:paddingLeft="8dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<View
android:id="@+id/separator"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#858585" />
</LinearLayout>

- 2개의 메뉴 아이콘 드로어블 가져오기 및 추가
onCreateOptionsMenu()
의 MainActivity.java에서 팽창합니다.\n- colorPrimary 및 colorPrimaryDark를 각각 #00897B 및 #00796B로 변경
메뉴 레이아웃을 확장하려면 MainActivity.java에 다음 메서드를 추가합니다.
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return super.onCreateOptionsMenu(menu);
}
menu_main.xml은 다음과 같습니다.
<menu xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
tools:context="com.journaldev.tablayoutviewpager.MainActivity">
<item
android:id="@+id/action_settings"
android:orderInCategory="100"
android:title="@string/action_settings"
app:showAsAction="never" />
<item
android:id="@+id/action_search"
android:orderInCategory="100"
android:title="@string/action_settings"
android:icon="@drawable/search"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_add"
android:orderInCategory="100"
android:title="@string/action_settings"
android:icon="@drawable/add"
app:showAsAction="ifRoom" />
</menu>

Android TabLayout ViewPager 프로젝트 다운로드