画像としてタブレイアウトのアプリを開発しています。
データバインディングライブラリでMVVMアーキテクチャを使用したいのですが、このフレームワークは初めてです。
このサンプルとしてViewPagerを使用してタブレイアウトを通常設定することで、MVVMを使用せずにこれを行うことができます。
MVVMとデータバインディングのない通常のタブレイアウト:
activity_main.xml:
<Android.support.design.widget.CoordinatorLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:layout_width="match_parent"
Android:layout_height="match_parent">
<Android.support.design.widget.AppBarLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<Android.support.v7.widget.Toolbar
Android:id="@+id/toolbar"
Android:layout_width="match_parent"
Android:layout_height="?attr/actionBarSize"
Android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
<Android.support.design.widget.TabLayout
Android:id="@+id/tabs"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
app:tabMode="fixed"
app:tabGravity="fill"/>
</Android.support.design.widget.AppBarLayout>
<Android.support.v4.view.ViewPager
Android:id="@+id/viewpager"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</Android.support.design.widget.CoordinatorLayout>
MainActivity.Java:
public class MainActivity extends AppCompatActivity {
private Toolbar toolbar;
private TabLayout tabLayout;
private ViewPager viewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new OneFragment(), "ONE");
adapter.addFragment(new TwoFragment(), "TWO");
adapter.addFragment(new ThreeFragment(), "THREE");
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
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();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
@Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
}
MVVMのタブレイアウト:
データバインディングライブラリでMVVMを使用する場合、タブレイアウトビューのビューモデルを使用する必要があります。
また、XMLとビューモデルでタブレイアウトを設定する方法がわかりません。データバインディングライブラリを使用して「レイアウトの1つのタブをタップする」などのイベントを処理する方法
データバインディングライブラリを使用してMVVMでタブレイアウトを使用するサンプルはありますか?
ご協力いただきありがとうございます。
主な活動 -
public class MainActivity extends Activity
{
@Override
protected void onCreate(@Nullable final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
App.get(this).component().inject(this);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.setHandler(this);
binding.setManager(getSupportFragmentManager());
}
@BindingAdapter({"bind:handler"})
public static void bindViewPagerAdapter(final ViewPager view, final MainActivity activity)
{
final MainActionsAdapter adapter = new MainActionsAdapter(view.getContext(), activity.getSupportFragmentManager());
view.setAdapter(adapter);
}
@BindingAdapter({"bind:pager"})
public static void bindViewPagerTabs(final TabLayout view, final ViewPager pagerView)
{
view.setupWithViewPager(pagerView, true);
}
}
xml-
<layout xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto"
xmlns:fresco="http://schemas.Android.com/apk/res-auto"
xmlns:tools="http://schemas.Android.com/tools">
<data>
<import type="Android.view.View" />
<variable
name="handler"
type="com.ui.main.MainActivity" />
<variable
name="manager"
type="Android.support.v4.app.FragmentManager" />
</data>
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:orientation="vertical">
<Android.support.v7.widget.Toolbar
Android:id="@+id/toolbar"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:animateLayoutChanges="true"
app:title="@string/app_name"
app:titleMarginStart="8dp" />
<Android.support.design.widget.TabLayout
Android:id="@+id/tab_layout"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
app:pager="@{(pager)}">
</Android.support.design.widget.TabLayout>
<Android.support.v4.view.ViewPager
Android:id="@+id/pager"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
app:handler="@{handler}" />
</LinearLayout>
</layout>
アダプター-
public class MainSectionsAdapter extends FragmentPagerAdapter
{
private static final int CONTACTS = 0;
private static final int CALLS = 1;
private static final int CHATS = 2;
private static final int[] TABS = new int[]{CONTACTS, CALLS, CHATS};
private Context mContext;
public MainSectionsAdapter(final Context context, final FragmentManager fm)
{
super(fm);
mContext = context.getApplicationContext();
}
@Override
public Fragment getItem(int position)
{
switch (TABS[position])
{
case CONTACTS:
return ContactsFragment.newInstance();
case CALLS:
return CallsFragment.newInstance();
case CHATS:
return ChatsFragment.newInstance();
}
return null;
}
@Override
public int getCount()
{
return TABS.length;
}
@Override
public CharSequence getPageTitle(int position)
{
switch (TABS[position])
{
case CONTACTS:
return mContext.getResources().getString(R.string.contacts);
case CALLS:
return mContext.getResources().getString(R.string.calls);
case CHATS:
return mContext.getResources().getString(R.string.chats);
}
return null;
}
}
これが最近新しく導入されたかどうかはわかりませんが、Androidサポートバージョン27.1.1を使用すると、カスタムデータバインディングアダプターさえ必要なく、次のように簡単に使用できます。
<Android.support.design.widget.TabLayout
Android:id="@+id/tl_1"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
app:setupWithViewPager="@{some_fragment_viewpager}"
app:tabSelectedTextColor="@Android:color/white"
app:tabTextColor="@color/v5_grey_55"
/>
<Android.support.v4.view.ViewPager
Android:id="@+id/some_fragment_viewpager"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
app:addOnPageChangeListener="@{vm.pageChangeListener}"
app:setAdapter="@{vm.pageAdapter}"
app:setCurrentItem="@{vm.pageChangeListener.currentPosition}"
/>
app:setupWithViewPager="@{some_fragment_viewpager}"
のviewPager
変数はAndroid:id="@+id/some_fragment_viewpager"
を指していることに注意してください。これがViewPagerへの参照が行われる方法です(私が知っている魔法のように)!
ViewModel
public class SomeViewModel {
public ViewPager.OnPageChangeListener pageChangeListener;
public SomeFragmentPagerAdapter pagerAdapter;
// ...
}
FragmentPagerAdapter
public classs SomeFragmentPagerAdapter extends FragmentPagerAdapter {
public Boolean currentPosition;
}
setUpWithViewpager
を使用したdatabinding
の解決策は次のとおりです。
public class BindingUtil
{
@BindingAdapter({ "setUpWithViewpager" })
public static void setUpWithViewpager(final TabLayout tabLayout, ViewPager viewPager)
{
viewPager.addOnAdapterChangeListener(new ViewPager.OnAdapterChangeListener()
{
@Override
public void onAdapterChanged(@NonNull ViewPager viewPager, @Nullable PagerAdapter oldAdapter, @Nullable PagerAdapter newAdapter)
{
if (oldAdapter == null && (newAdapter == null || newAdapter.getCount() == 0))
{
// this function will helpful when
// we don't create viewpager immediately
// when view created (this mean we create
// will pager after a period time)
return;
}
tabLayout.setupWithViewPager(viewPager);
}
});
}
}
xml
<Android.support.design.widget.TabLayout
...
app:setUpWithViewpager="@{ viewPager }"
/>
<Android.support.v4.view.ViewPager
...
Android:id="@+id/viewPager"
app:adapter="@{viewModel.pagerAdapter}"
/>
ViewModel
public class MainViewModel extends BaseObservable
{
@Bindable
public PagerAdapter getPagerAdapter()
{
return adapter;
}
private void createViewPagerAdapter()
{
...
notifyPropertyChanged(BR.pagerAdapter);
}
}
それが役に立てば幸い