지금까지는 어지간하면 데이터 바인딩만 사용해도 되는데, ViewPager는 전부 다 그렇게 하기에는 조금 무리가 있는 것 같다.
일단 Activity의 getSupportFragmentManager() 를 어댑터에 넘겨줘야 하는데, @BindAdapter를 사용하면 메소드를 public static 으로 선언해야해서 activity의 static 변수를 선언해둬야 하는데, 코드가 더러워 보인다.
게다가 예제에서는 좌우 페이지 넘김 버튼도 같이 넣고 싶은데, 이렇게 하면 ViewPager를 드래그로 넘겼을 때 버튼의 enabled 를 바꾸기위한 작업도 들어가야해서 이래저래 꼬이는 부분이 생긴다. 물론 내 실력 탓이겠지만…
http://stackoverflow.com/a/42208693/1025379 이 방법을 이용하면 될 것 같다!!
일단 ViewPager 에서 사용할 어댑터를 만든다.
public class ViewPagerAdapter extends FragmentStatePagerAdapter { private ArrayList<Fragment> fragments = new ArrayList<>(); public ViewPagerAdapter(FragmentManager fm) { super(fm); } public void add(Fragment fragment) { fragments.add(fragment); } @Override public Fragment getItem(int position) { return fragments.get(position); } @Override public int getCount() { return fragments.size(); } }
뷰모델을 만든다. 현재 페이지, 전체 페이지 갯수, 첫 페이지인가, 마지막 페이지 인가를 판단하는 변수만 있으면 되지 싶다.
public class ViewPagerViewModel implements BaseViewModel { public final ObservableInt currentPage = new ObservableInt(); public final ObservableInt maxPage = new ObservableInt(); public final ObservableBoolean isFirstPage = new ObservableBoolean(); public final ObservableBoolean isLastPage = new ObservableBoolean(); @Override public void onCreate() { currentPage.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() { @Override public void onPropertyChanged(Observable observable, int i) { pageMoved(); } }); isFirstPage.set(true); } @Override public void onResume() {} @Override public void onPause() {} @Override public void onDestroy() {} private void pageMoved() { isFirstPage.set(currentPage.get() == 0); isLastPage.set(currentPage.get() == maxPage.get() - 1); } public ViewPager.SimpleOnPageChangeListener pageChangeListener = new ViewPager.SimpleOnPageChangeListener() { @Override public void onPageSelected(int position) { super.onPageSelected(position); currentPage.set(position); } }; public View.OnClickListener pageChangeButtonClickListener = new View.OnClickListener() { @Override public void onClick(View view) { currentPage.set(currentPage.get() + Integer.valueOf(view.getTag().toString())); } }; }
레이아웃을 그린다. 페이지 넘김 버튼은 tag를 이용해서 1페이지씩 바뀌게 했다.
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <data> <variable name="model" type="kr.susemi99.testmvvm.view_pager.ViewPagerViewModel"/> </data> <LinearLayout 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="0dp" android:layout_weight="1" app:currentItem="@{model.currentPage}" app:onPageChangeListener="@{model.pageChangeListener}"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:enabled="@{!model.isFirstPage}" android:onClick="@{model.pageChangeButtonClickListener}" android:tag="-1" android:text="<"/> <Button android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:enabled="@{!model.isLastPage}" android:onClick="@{model.pageChangeButtonClickListener}" android:tag="1" android:text=">"/> </LinearLayout> </LinearLayout> </layout>
액티비티에서 어댑터에 프래그먼트를 넣고, 강제로 ViewPager를 찾아서 setAdapter()를 호출했다.
public class ViewPagerActivity extends AppCompatActivity { private ViewPagerViewModel model = new ViewPagerViewModel(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityViewPagerBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_view_pager); binding.setModel(model); model.onCreate(); ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager()); adapter.add(OneFragment.instance()); adapter.add(InputFragment.instance()); adapter.add(OneFragment.instance()); binding.viewPager.setAdapter(adapter); model.maxPage.set(adapter.getCount()); } }
드래그로 좌우이동했을 때 버튼의 사용여부가 자동으로 바뀌고, 버튼으로도 페이지를 넘길 수 있다.