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 |