[안드로이드] TabLayout과 ViewPager (Material Design)
TabLayout과 ViewPager (Material Design)
AndroidX의 ViewPager를 이용하면 스와이프 기능으로 화면 이동을 할 수 있습니다.
또한 TabLayout 과 결합하여 이동된 화면 위치를 직관적으로 알 수 있고, Tab을 클릭하여 화면이동을 할 수도 있습니다.
예제에서는 아래와 같은 화면구성을 만들어 보도록 하겠습니다.
1. gradle 설정
먼저 Material Components를 사용할수 있도록 gradle에 추가해줍니다.
현재 최신버전은 1.2.0-alpha06 이네요
dependencies {
...
implementation 'com.google.android.material:material:1.2.0-alpha06'
}
2. styles.xml 수정
ActionBar 영역을 사용하기 위해 기본 ActionBar 부분을 NoActionBar로 변경해 줍니다.
res -> values -> styles.xml 에서 parent="" 부분을 parent="Theme.MaterialComponents.Light.NoActionBar" 로 변경합니다.
- styles.xml
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
</resources>
3. 화면을 구성할 Fragment 생성
각 화면을 나타낼 3개의 Fragment(FirstFragment, SecondFragment, ThirdFragment)를 생성해줍니다.
여기서는 최소한의 코드로 구성된 Fragment를 만들어 주도록 하겠습니다.
(Fragment 사용법은 다음에 글을 작성하도록 하겠습니다.)
ex) FirstFragment예제 (SecondFragment와 ThirdFragment도 이름만 바꿔서 동일하게 만들어 주면됩니다.)
- FirstFragment.java
public class FirstFragment extends Fragment {
public FirstFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_first, container, false);
return view;
}
}
- fragment_first.xml
<FrameLayout 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=".FirstFragment">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="First Fragment"
android:textSize="16dp"/>
</FrameLayout>
4. MainActivity 화면구성
MainActivity화면 구성을 Toolbar, TabLayout, Viewpager 영역을 아래와 같이 설정해줍니다.
최상위 Layout은 CoordinatorLayout 대신에 LinearLayout 등을 사용해도 상관없습니다.
- activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@android:color/white" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:background="@android:color/white"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</com.google.android.material.tabs.TabLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
5. ViewPagerAdapter.class 생성
위에 작성된 ViewPager에 하위 View를 삽입하기 위해서는 PagerAdapter와의 연결이 필요합니다.
PagerAdapter는 두가지가 있는데
1) FragmentPagerAdapter는 사용될 Fragment가 적고 그 수가 정해져있을때 사용하고
2) FragmentStatePagerAdapter는 사용될 Fragment 수가 유동적이거나 많아서 메모리 사용을 효율적으로 사용하고 싶을 때 사용합니다.
대신 메모리 관리를 위해서 페이지를 탐색할때 Fragment를 삭제하고 생성하게 됨으로 주의해야할 부분이 있습니다.
이때 setOffscreenPageLimit()을 사용하면 미리 로딩하여 유지할 페이지 수를 지정할 수 있습니다.
예제에서는 FragmentStatePagerAdapter를 사용하도록 하겠습니다.
- ViewPagerAdapter.java
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
private ArrayList<Fragment> fragmentList = new ArrayList<>();
private ArrayList<String> fragmentTitle = new ArrayList<>();
public ViewPagerAdapter(@NonNull FragmentManager fm, int behavior) {
super(fm, behavior);
}
@NonNull
@Override // 화면의 실제 Fragment를 반환한다.
public Fragment getItem(int position) {
return fragmentList.get(position);
}
@Override // Page수
public int getCount() {
return fragmentList.size();
}
@Nullable
@Override // 제목
public CharSequence getPageTitle(int position) {
return fragmentTitle.get(position);
}
public void addFragment (Fragment fragment, String title) {
fragmentList.add(fragment);
fragmentTitle.add(title);
}
}
6. Icon으로 사용할 Drawable 이미지 생성
res -> drawable 폴더 우클릭 -> New -> Vector Asset 에서 본인이 원하는 이미지를 세개 준비한다.
(예제에서는 icon_1.xml, icon_2.xml, icon_3.xml 로 파일이름을 설정하였음)
7. MainActivity 작성
위에 만들어둔 코드 재료들을 아래와 같이 조합하도록 합니다.
- MainActivity.java
public class MainActivity extends AppCompatActivity {
private Toolbar toolbar;
private TabLayout tabLayout;
private ViewPager viewPager;
private FirstFragment firstFragment;
private SecondFragment secondFragment;
private ThirdFragment thirdFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// toolbar 설정
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// ViewPager 설정
viewPager = findViewById(R.id.view_pager);
viewPager.setOffscreenPageLimit(3); //페이지 유지 개수
// tabLayout에 ViewPager 연결
tabLayout = findViewById(R.id.tab_layout);
tabLayout.setupWithViewPager(viewPager);
// Fragment 생성
firstFragment = new FirstFragment();
secondFragment = new SecondFragment();
thirdFragment = new ThirdFragment();
// ViewPagerAdapter를 이용하여 Fragment 연결
ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager(), 0);
viewPagerAdapter.addFragment(firstFragment, "First");
viewPagerAdapter.addFragment(secondFragment, "Second");
viewPagerAdapter.addFragment(thirdFragment, "Third");
viewPager.setAdapter(viewPagerAdapter);
// tabLayout에 아이콘 설정 부분
tabLayout.getTabAt(0).setIcon(R.drawable.icon_1);
tabLayout.getTabAt(1).setIcon(R.drawable.icon_2);
tabLayout.getTabAt(2).setIcon(R.drawable.icon_3);
// 세번째 화면에 Badge 달기
BadgeDrawable badgeDrawable = tabLayout.getTabAt(2).getOrCreateBadge();
badgeDrawable.setVisible(true);
badgeDrawable.setNumber(7);
}
}
8. 실행하기
실행하면 다음과 같은 화면을 보실수 있습니다.
이제부터는 각 Fragment에 본인이 원하는 컨텐츠를 채우시면 되겠습니다.