[Android] TabLayout과 ViewPager 함께 사용하는 방법 (Fragment)
ViewPager(화면을 좌우로 밀어서 이동) 설정 방법
상단 혹은 하단의 탭레이아웃(TabLayout)를 사용시 사용자의 편의성을 추가하기위해 ViewPager(화면을 좌우로 밀어서 이동이 가능하다) 를 설정하는 방법에 대한 코드는 다음과 같다. 화면 레이아웃에 탭레이아웃과 뷰페이저 레이아웃을 추가 후 onCreate()메소드에서 선언해준다.
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager viewPager = findViewById(R.id.viewpager);
TabLayout tabLayout = findViewById(R.id.tablayout);
}
[activity_main.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">
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tablayout"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</com.google.android.material.tabs.TabLayout>
</LinearLayout>
FragmentStatePagerAdapter 혹은 FragmentPagerAdapter를 상속받아서 뷰페이저 클래스를 하나 생성한다. FragmentStatePagerAdapter사용을 추천한다. 뷰페이저로 사용되는 페이지수가 적다면 FragmentPagerAdapter를 사용해도 무방하다. 그 이유는 아래 영문 내용을 참고하자.
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import androidx.fragment.app.FragmentStatePagerAdapter;
import java.util.ArrayList;
import java.util.List;
public class MyViewPagerAdapter extends FragmentStatePagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
@Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
@Override
public int getCount() {
return mFragmentList.size();
}
@Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
//프레그먼트 추가
public void addFrag(Fragment fragment) {
mFragmentList.add(fragment);
mFragmentTitleList.add("");
}
//프레그먼트 추가
public void addFrag(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
}
MyViewPagerAdapter를 사용하여 Fragment를 추가해준다.
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager viewPager = findViewById(R.id.viewpager);
TabLayout tabLayout = findViewById(R.id.tablayout);
//어댑터 할당
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentViewPagerAdapter = new MyViewPagerAdapter(fragmentManager);
//프레그먼트 추가
fragmentViewPagerAdapter.addFrag(new HomeFragment(), "홈");
fragmentViewPagerAdapter.addFrag(new SettingsFragment(), "설정");
fragmentViewPagerAdapter.addFrag(new NotiFragment(), "알림");
// 뷰페이저에 어댑터 설정
viewPager.setAdapter(fragmentViewPagerAdapter);
//탭레이아웃에 뷰페이저 설정
tabLayout.setupWithViewPager(viewPager);
}
탭레이아웃에 아이콘 추가하는 방법
tabLayout.getTabAt(0).setIcon(R.drawable.home_icon);
tabLayout.getTabAt(1).setIcon(R.drawable.settings_icon);
tabLayout.getTabAt(2).setIcon(R.drawable.noti_icon);
페이지가 변경(선택)되었을 때 액션바 타이틀 변경하는 방법
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
getSupportActionBar().setTitle(fragmentViewPagerAdapter.getPageTitle(position));
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
[HomeFragment]
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class HomeFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_home, container, false);
}
}
[fragment_home.xml]
<?xml version="1.0" encoding="utf-8"?>
<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=".HomeFragment">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="홈" />
</FrameLayout>
[SettingsFragment]
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class SettingsFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_setting, container, false);
}
}
[fragment_setting.xml]
<?xml version="1.0" encoding="utf-8"?>
<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=".SettingsFragment">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="설정" />
</FrameLayout>
[NotiFragment]
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class NotiFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_noti, container, false);
}
}
[fragment_noti.xml]
<?xml version="1.0" encoding="utf-8"?>
<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=".NotiFragment">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="알림" />
</FrameLayout>
[FragmentPagerAdapter와 FragmentStatePagerAdapter의 차이점]
What is the difference between FragmentPagerAdapter and FragmentStatePagerAdapter?
About FragmentPagerAdapter Google’s guide says:
This version of the pager is best for use when there are a handful of typically more static fragments to be paged through, such as a set of tabs. The fragment of each page the user visits will be kept in memory, though its view hierarchy may be destroyed when not visible. This can result in using a significant amount of memory since fragment instances can hold on to an arbitrary amount of state. For larger sets of pages, consider FragmentStatePagerAdapter.
And about FragmentStatePagerAdapter:
This version of the pager is more useful when there are a large number of pages, working more like a list view. When pages are not visible to the user, their entire fragment may be destroyed, only keeping the saved state of that fragment. This allows the pager to hold on to much less memory associated with each visited page as compared to FragmentPagerAdapter at the cost of potentially more overhead when switching between pages.
[연관]