如何分离 TabLayout 和 ViewPager 操作?
How can I separate TabLayout and ViewPager actions?
我在两者之间有一个标准设置,但我希望 TabLayout 的点击(当用户直接触摸 TabLayout 的点时)不同于 ViewPager 的滑动。也许我只想点击操作打印 "tap",滑动操作打印 "swipe"。目前,除了将 TabLayout 附加到 ViewPager 之外,我没有在 TabLayout 上设置任何内容,但是当我在 ViewPager 上滑动时,它会同时打印 "swipe" 和 "tap".
所以花了一些时间,但我终于得到了我想要的。事实证明,TabLayout 的侦听器关心 ViewPager 处理的内容,而不是相反。因此,当 VP 被滑动时,两个听众都听到了。当 TabLayout 被点击时,只有 TabLayout 知道。因此,我可以设置点按功能来执行它的点按操作,然后在滑动功能中我只需确保它可以确定实际移动 VP 的是滑动还是点按。
MVVM 视图模型绑定:
@BindingAdapter({"onAdapterChangeListener"})
public static void setOnAdapterChangeListener(ViewPager viewPager, BehaviorSubject<Void> adapterChangeSubject) {
viewPager.addOnAdapterChangeListener((viewPager1, oldAdapter, newAdapter) -> adapterChangeSubject.onNext(null));
}
@BindingAdapter({"viewPager","onTap","onSwipe"})
public static void addOnTabSelectedListener(TabLayout tabLayout, ViewPager viewPager, BehaviorSubject<Integer> tapSubject, BehaviorSubject<Integer> swipeSubject) {
viewPager.addOnAdapterChangeListener((viewPager1, oldAdapter, newAdapter) -> {
tabLayout.setupWithViewPager(viewPager);
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
int tabPosition = tab.getPosition();
if (tabPosition == viewPager.getCurrentItem()) {
swipeSubject.onNext(tabPosition);
// A swipe will have the VP tell the TabLayout what tab to move to before
// this is called, so if the two positions match, it means the user
// performed a swipe action
} else {
tapSubject.onNext(tabPosition);
viewPager.setCurrentItem(tabPosition);
// Otherwise, it was definitely a tap action
}
}
// If I updated from API 23 to 24 I would use tabLayout.addOnTab and wouldn't
// need these guys below
@Override
public void onTabUnselected(TabLayout.Tab tab) {}
@Override
public void onTabReselected(TabLayout.Tab tab) {}
});
});
}
XML:
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="-17dp"
android:layout_gravity="top"
app:tabBackground="@drawable/dot_tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"
app:tabPaddingEnd="5dp"
app:tabPaddingStart="5dp"
app:viewPager="@{{viewPager}}"
app:onTap="@{carouselViewModel.tapSubject}"
app:onSwipe="@{carouselViewModel.swipeSubject}"/>
<com.snip.CustomViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:paddingEnd="20dp"
android:paddingStart="20dp"
app:onAdapterChangeListener="@{carouselViewModel.carouselAdapterChangeSubject}"/>
CarouselViewModel:
swipeSubject
.subscribe(page -> {
doTheSwipeThing();
});
tapSubject
.subscribe(page -> {
doTheTapThing();
});
我在两者之间有一个标准设置,但我希望 TabLayout 的点击(当用户直接触摸 TabLayout 的点时)不同于 ViewPager 的滑动。也许我只想点击操作打印 "tap",滑动操作打印 "swipe"。目前,除了将 TabLayout 附加到 ViewPager 之外,我没有在 TabLayout 上设置任何内容,但是当我在 ViewPager 上滑动时,它会同时打印 "swipe" 和 "tap".
所以花了一些时间,但我终于得到了我想要的。事实证明,TabLayout 的侦听器关心 ViewPager 处理的内容,而不是相反。因此,当 VP 被滑动时,两个听众都听到了。当 TabLayout 被点击时,只有 TabLayout 知道。因此,我可以设置点按功能来执行它的点按操作,然后在滑动功能中我只需确保它可以确定实际移动 VP 的是滑动还是点按。
MVVM 视图模型绑定:
@BindingAdapter({"onAdapterChangeListener"})
public static void setOnAdapterChangeListener(ViewPager viewPager, BehaviorSubject<Void> adapterChangeSubject) {
viewPager.addOnAdapterChangeListener((viewPager1, oldAdapter, newAdapter) -> adapterChangeSubject.onNext(null));
}
@BindingAdapter({"viewPager","onTap","onSwipe"})
public static void addOnTabSelectedListener(TabLayout tabLayout, ViewPager viewPager, BehaviorSubject<Integer> tapSubject, BehaviorSubject<Integer> swipeSubject) {
viewPager.addOnAdapterChangeListener((viewPager1, oldAdapter, newAdapter) -> {
tabLayout.setupWithViewPager(viewPager);
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
int tabPosition = tab.getPosition();
if (tabPosition == viewPager.getCurrentItem()) {
swipeSubject.onNext(tabPosition);
// A swipe will have the VP tell the TabLayout what tab to move to before
// this is called, so if the two positions match, it means the user
// performed a swipe action
} else {
tapSubject.onNext(tabPosition);
viewPager.setCurrentItem(tabPosition);
// Otherwise, it was definitely a tap action
}
}
// If I updated from API 23 to 24 I would use tabLayout.addOnTab and wouldn't
// need these guys below
@Override
public void onTabUnselected(TabLayout.Tab tab) {}
@Override
public void onTabReselected(TabLayout.Tab tab) {}
});
});
}
XML:
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="-17dp"
android:layout_gravity="top"
app:tabBackground="@drawable/dot_tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"
app:tabPaddingEnd="5dp"
app:tabPaddingStart="5dp"
app:viewPager="@{{viewPager}}"
app:onTap="@{carouselViewModel.tapSubject}"
app:onSwipe="@{carouselViewModel.swipeSubject}"/>
<com.snip.CustomViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:paddingEnd="20dp"
android:paddingStart="20dp"
app:onAdapterChangeListener="@{carouselViewModel.carouselAdapterChangeSubject}"/>
CarouselViewModel:
swipeSubject
.subscribe(page -> {
doTheSwipeThing();
});
tapSubject
.subscribe(page -> {
doTheTapThing();
});