웹사이트 검색

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 프로젝트 다운로드