我正在开发一个将标签布局作为图像的应用程序。
我想将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" />
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和视图模型中设置标签布局。如何使用数据绑定库
处理诸如“点击布局的一个选项卡”之类的事件是否有任何使用带有数据绑定库的MVVM中的Tab布局的样本?
感谢您的帮助。
答案 0 :(得分:15)
MainActivity -
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, 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;
}
}
答案 1 :(得分:3)
以下是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}"
/>
<强>视图模型强>
public class MainViewModel extends BaseObservable
{
@Bindable
public PagerAdapter getPagerAdapter()
{
return adapter;
}
private void createViewPagerAdapter()
{
...
notifyPropertyChanged(BR.pagerAdapter);
}
}
希望有所帮助
答案 2 :(得分:3)
我不确定这是不是最近才引入的,但是对于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="@{viewPager}"
app:tabSelectedTextColor="@android:color/white"
app:tabTextColor="@color/v5_grey_55"
/>
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:addOnPageChangeListener="@{vm.pageChangeListener}"
app:setAdapter="@{vm.pageAdapter}"
app:setCurrentItem="@{vm.pageChangeListener.currentPosition}"
/>
请注意,viewPager
中的app:setupWithViewPager="@{viewPager}"
变量指向android:id="@+id/viewPager"
。
这样就完成了对ViewPager的引用(就像我知道的魔术一样!)!
答案 3 :(得分:0)
如 Phan Van Linh's answer 所示,它对我有用,但是当我们在括号中提供 viewPager
的 ID 作为对 tabLayout
的引用时,它显示绑定错误。
我通过简单地提供不带括号的 ID 解决了这个问题,并在驼峰式大小写中提供了 ViewPager
的 ID。