[android] MVVM – 8. ViewPager

지금까지는 어지간하면 데이터 바인딩만 사용해도 되는데, 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="&lt;"/>

      <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="&gt;"/>
    </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());
  }
}

 

 

 

드래그로 좌우이동했을 때 버튼의 사용여부가 자동으로 바뀌고, 버튼으로도 페이지를 넘길 수 있다.