ViewPager & Fragment
Fragment를 사용하는 것 중에 하나가 ViewPager와 같이 사용하는 것이다.
(보통 TabLayout과 같이 사용하는데 이번에는 TabLayout는 다루지 않는다.)
기본 예제(Basic)
- activity_basic.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
- fragment_basic.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.AppCompatTextView
android:id="@+id/history"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="1"
android:textColor="@android:color/black"
android:gravity="center"
style="@style/TextAppearance.AppCompat.Small"/>
</LinearLayout>
- BasicActivity
public class BasicActivity extends FragmentActivity {
protected void onCreate( Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_basic);
ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);
// getSupportFragmentManager를 넘겨줘야 한다
viewPager.setAdapter(new BasicFragmentAdapter(getSupportFragmentManager()));
}
class BasicFragmentAdapter extends FragmentPagerAdapter {
private ArrayList<Fragment> mFragment = new ArrayList<>();
// fragment의 background에 색을 주기 위한 것이므로 없어도 상관없음.
private String[] colors = getResources().getStringArray(R.array.default_preview);
public BasicFragmentAdapter(FragmentManager fm) {
super(fm);
for(int i=0; i<5; i++) {
mFragment.add(BasicFragment.newInstance("Fragment " + String.valueOf(i+1), colors[i]));
}
}
public Fragment getItem(int position) {
return mFragment.get(position);
}
public int getCount() {
return mFragment.size();
}
}
}
- BasicFragment
public class BasicFragment extends Fragment {
private final static String PARAMS_TITLE = "params_title";
private final static String PARAMS_BACKGROUND_COLOR = "params_background_color";
private String title = "";
private String colorResId;
public static Fragment newInstance(String title, String color) {
Bundle args = new Bundle();
args.putString(PARAMS_TITLE, title);
args.putString(PARAMS_BACKGROUND_COLOR, color);
Fragment fragment = new BasicFragment();
fragment.setArguments(args);
return fragment;
}
public void onCreate( Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle bundle = getArguments();
title = bundle.getString(PARAMS_TITLE, "");
colorResId = bundle.getString(PARAMS_BACKGROUND_COLOR, "");
Log.i(title, "onCreate()");
}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.i(title, "onCreateView()");
return inflater.inflate(R.layout.fragment_basic, container, false);
}
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Log.i(title, "onViewCreated()");
view.setBackgroundColor(Color.parseColor(colorResId));
TextView tvHistory = (TextView) view.findViewById(R.id.history);
tvHistory.setText(title);
}
public void setUserVisibleHint(boolean isVisibleToUser) {
Log.i(title, "setUserVisibleHint(" + (isVisibleToUser ? "true" : "false") + ")");
super.setUserVisibleHint(isVisibleToUser);
}
}
위 예제를 실행하면 아래와 같이 나오게 된다.
결과 화면
setOffscreenPageLimit
- 위 예제의 로그를 살펴보면 swipe 될 때마다 미리 만들어지지 않는 fragment들은 onCreate()부터 다시 호출되는 것이 보인다.
이유는 예를 들어 5개 페이지가 있다고 가정 했을 때 현재 페이지가 3 페이지이면 아래와 같이 나타나게 된다.
1 -> |offset| 2 -> (3) -> 4 -> |offset| 5
기본 미리 호출되는 limit이 좌우 1개씩이기 때문에 2와 4만 미리 세팅된다. 따라서 1과 5는 만들어 지게 된다.
5 페이지를 모두 다 처음에 부르고 싶다면 java 코드에서
mViewPager.setOffscreenPageLimit(5)
로 설정하면 처음에 다 settting 되고 다음에는 setUserVisibleHint가 호출되면서 user에 visible 여부를 알 수 있다.
Clip page
다음 페이지를 미리 보여주는 UI도 구성할 수 있다.
- Adapter에서 getPageWidth를 Override해서 수정하면 된다.
class BasicFragmentAdapter extends FragmentPagerAdapter {
private ArrayList<Fragment> mFragment = new ArrayList<>();
private String[] colors = getResources().getStringArray(R.array.default_preview);
public float getPageWidth(int position) {
return getCount() == 1 ? super.getPageWidth(position) : 0.9f;
}
public BasicFragmentAdapter(FragmentManager fm) {
super(fm);
for(int i=0; i<5; i++) {
mFragment.add(BasicFragment.newInstance("Fragment " + String.valueOf(i+1), colors[i]));
}
}
public Fragment getItem(int position) {
return mFragment.get(position);
}
public int getCount() {
return mFragment.size();
}
}
결과 화면
참고
- https://stackoverflow.com/questions/36044970/fragmentstatepageradapter-resets-content-of-first-fragment
- https://blog.neteril.org/blog/2013/10/14/android-tip-viewpager-with-protruding-children
- http://www.hardcopyworld.com/ngine/android/index.php/archives/164
- http://hashcode.co.kr/questions/985/fragmentactivity%EC%99%80-activity%EC%9D%98-%EC%B0%A8%EC%9D%B4%EB%8A%94-%EB%AD%94%EA%B0%80%EC%9A%94
'Programming > Android' 카테고리의 다른 글
[Android] Dependency Structure (0) | 2018.04.19 |
---|---|
[Android] View Collapse & Expand Animation (4) | 2017.11.24 |
[Android] Debug & Release 동시에 두개 설치하기 (0) | 2017.10.12 |
[Android] Handler & Looper (0) | 2017.10.05 |
[Android] Google Play Store로 이동시키기 (0) | 2017.05.31 |