-
Notifications
You must be signed in to change notification settings - Fork 353
4.滑动子view的下级view
ConsecutiveScrollerLayout默认情况下只会处理它的直接子view
的滑动,但有时候需要滑动的布局可能不是ConsecutiveScrollerLayout的直接子view,而是子view所嵌套的下级view。比如ConsecutiveScrollerLayout嵌套FrameLayout,FrameLayout嵌套RecyclerView,我们希望ConsecutiveScrollerLayout也能正常处理RecyclerView的滑动,那么就需要让ConsecutiveScrollerLayout知道FrameLayout下的RecyclerView是需要由ConsecutiveScrollerLayout处理滑动事件的滑动控件。为了支持这种需求,ConsecutiveScroller提供了两种实现方式:app:layout_scrollChild
属性和IConsecutiveScroller
接口。
子View可以通过app:layout_scrollChild
属性指定需要处理滑动事件的下级View.
<com.donkingliang.consecutivescroller.ConsecutiveScrollerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/scrollerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_scrollChild="@+id/recyclerView"> // 指定recyclerView为需要滑动的view
<!-- 滑动控件的高度应该是占满父布局的 -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
</com.donkingliang.consecutivescroller.ConsecutiveScrollerLayout>
这种方式使用简单,但是只能指定一个滑动View,而且无法适用于滑动View需要根据不同状态动态变化的复杂场景。
子view实现IConsecutiveScroller接口,并通过实现接口方法告诉ConsecutiveScrollerLayout需要滑动的下级view,ConsecutiveScrollerLayout就能正确地处理它的滑动事件。IConsecutiveScroller需要实现两个方法:
/**
* 返回当前需要滑动的下级view。在一个时间点里只能有一个view可以滑动。
*/
View getCurrentScrollerView();
/**
* 返回所有可以滑动的子view。由于ConsecutiveScrollerLayout允许它的子view包含多个可滑动的子view,所以返回一个view列表。
*/
List<View> getScrolledViews();
在前面提到的例子中,我们可以这样实现:
public class MyFrameLayout extends FrameLayout implements IConsecutiveScroller {
@Override
public View getCurrentScrollerView() {
// 返回需要滑动的ScrollView
return getChildAt(0);
}
@Override
public List<View> getScrolledViews() {
// 返回需要滑动的ScrollView
List<View> views = new ArrayList<>();
views.add(getChildAt(0));
return views;
}
}
<com.donkingliang.consecutivescroller.ConsecutiveScrollerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/scrollerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical">
<com.donkingliang.consecutivescrollerdemo.view.MyFrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 滑动控件的高度应该是占满父布局的 -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</com.donkingliang.consecutivescrollerdemo.view.MyFrameLayout>
</com.donkingliang.consecutivescroller.ConsecutiveScrollerLayout>
这样ConsecutiveScrollerLayout就能正确地处理ScrollView的滑动。这是一个简单的例子,在实际的需求中,我们一般不需要这样做。
使用IConsecutiveScroller接口,可以同时支持多个滑动子view,可以根据不同的业务场景和状态,返回不同的滑动view。
注意:
1、getCurrentScrollerView()和getScrolledViews()必须正确地返回需要滑动的view,这些view可以是经过多层嵌套的,不一定是直接子view。所以使用者应该按照自己的实际场景去实现者两个方法。
2、滑动的控件应该跟嵌套它的子view的高度保持一致,也就是说滑动的控件高度应该是match_parent,并且包裹它的子view和它本身都不要设置上下边距(margin和ppadding)。宽度没有这个限制。
如果你的ViewPager承载的子布局(或Fragment)不是可以垂直滑动的,那么使用普通的ViewPager即可。如果是可以垂直滑动的,那么你的ViewPager需要实现IConsecutiveScroller接口,并返回需要滑动的view对象。框架里提供了一个实现了IConsecutiveScroller接口的自定义控件:ConsecutiveViewPager
。你应该使用这个控件,并且你的ConsecutiveViewPager的子view(或Fragment的根布局)是可垂直滑动的view,如:RecyclerView、NestedScrollView、ConsecutiveScrollerLayout等。这样你的ViewPager就能正确地跟ConsecutiveScrollerLayout一起滑动了。
<?xml version="1.0" encoding="utf-8"?>
<com.donkingliang.consecutivescroller.ConsecutiveScrollerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/scrollerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
app:tabGravity="fill"
app:tabIndicatorColor="@color/colorPrimary"
app:tabIndicatorHeight="3dp"
app:tabMode="scrollable"
app:tabSelectedTextColor="@color/colorPrimary" />
<com.donkingliang.consecutivescroller.ConsecutiveViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</com.donkingliang.consecutivescroller.ConsecutiveScrollerLayout>
布局吸顶时会覆盖在下面的布局的上面,有时候我们希望TabLayout吸顶悬浮在顶部,但是不希望它覆盖遮挡ViewPager的内容。那么你可以使用autoAdjustHeightAtBottomView属性和adjustHeightOffset属性
从4.4.0版本开始,支持在ConsecutiveScrollerLayout中使用ViewPager2。跟ViewPager一样,框架里专门提供了一个ViewPage2的自定义控件:ConsecutiveViewPager2
。你必须使用它,而不能直接使用Androidx里的ViewPager2。不过你要使用它,依然需要引入ViewPager2依赖。
// xxx:viewpager2版本号
implementation 'androidx.viewpager2:viewpager2:xxx'
<?xml version="1.0" encoding="utf-8"?>
<com.donkingliang.consecutivescroller.ConsecutiveScrollerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/scrollerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
app:tabGravity="fill"
app:tabIndicatorColor="@color/colorPrimary"
app:tabIndicatorHeight="3dp"
app:tabMode="scrollable"
app:tabSelectedTextColor="@color/colorPrimary" />
<com.donkingliang.consecutivescroller.ConsecutiveViewPager2
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</com.donkingliang.consecutivescroller.ConsecutiveScrollerLayout>
ConsecutiveViewPager2提供了跟ConsecutiveViewPager一样的功能。ConsecutiveViewPager2并不是ViewPager2的子类(ViewPager2不允许继承),而是一个包含ViewPager2的控件,所以你不能把ConsecutiveViewPager2当作ViewPager2。但是ConsecutiveViewPager2提供了跟ViewPager2一样的常用方法,而且提供了获取ViewPager2对象的方法:
public ViewPager2 getViewPager2();
所以你完全可以像使用ViewPager2一样使用它。
注意事项:
1、ConsecutiveViewPager2只能作为ConsecutiveScrollerLayout的子view,中间不能嵌套其他层级。
2、不要给ConsecutiveViewPager2设置padding。
3、ConsecutiveViewPager2不支持垂直翻页。也就是说,它只能跟ViewPager一样水平翻页和支持item垂直滑动。