diff --git a/README.md b/README.md
index 012e826..3e35090 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,22 @@
-ConsecutiveScrollerLayout是Android下支持多个滑动布局(RecyclerView、WebView、ScrollView等)和lView等)和普通控件(TextView、ImageView、LinearLayou、自定义View等)持续连贯滑动的容器,它使所有的子View像一个整体一样连续顺畅滑动。并且支持布局吸顶功能。
+## 简介
-#### 效果图
+ConsecutiveScrollerLayout是Android下支持多个滑动布局(RecyclerView、ViewPager、WebView、ScrollView等)和普通控件(TextView、ImageView、LinearLayou、自定义View等)持续连贯滑动的容器,它使所有的子View像一个整体一样连续顺畅滑动。
+
+ConsecutiveScrollerLayout支持多种模式的布局吸顶功能,能动态控制吸顶View的显示位置和状态,能适用于大部分的业务场景。
+
+ConsecutiveScrollerLayout能通过实现接口,支持复杂的、多层嵌套下的滑动布局的滑动处理。
+
+ConsecutiveScrollerLayout支持NestedScrolling机制。
+
+## 效果图
![sample](https://upload-images.jianshu.io/upload_images/2365010-1d0ebf289428ce8c.gif?imageMogr2/auto-orient/strip)
![sticky](https://upload-images.jianshu.io/upload_images/2365010-f2b64d20022d2566.gif?imageMogr2/auto-orient/strip)
+![permanent_sticky](https://github.com/donkingliang/ConsecutiveScroller/blob/master/image/permanent_sticky.gif?raw=true)
+![sink_sticky](https://github.com/donkingliang/ConsecutiveScroller/blob/master/image/sink_sticky.gif?raw=true)
+![viewpager](https://github.com/donkingliang/ConsecutiveScroller/blob/master/image/viewpager.gif?raw=true)
-### 引入依赖
+## 引入依赖
在Project的build.gradle在添加以下代码
@@ -20,683 +31,20 @@ allprojects {
在Module的build.gradle在添加以下代码
```groovy
// 使用了Androidx
-implementation 'com.github.donkingliang:ConsecutiveScroller:4.4.2'
+implementation 'com.github.donkingliang:ConsecutiveScroller:4.5.0'
// 或者
// 使用Android support包
-implementation 'com.github.donkingliang:ConsecutiveScroller:4.4.2-support'
-```
-
-**注意:** 如果你准备使用这个库,请务必认真阅读下面的文档。它能让你了解ConsecutiveScrollerLayout可以实现的功能,以及避免不必要的错误。
-
-### 基本使用
-
-ConsecutiveScrollerLayout的使用非常简单,把需要滑动的布局作为ConsecutiveScrollerLayout的`直接子View`即可。
-
-```xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-```
-**注意:**
-
-1、ConsecutiveScrollerLayout只能处理它的`直接子View`的滑动事件,如果一个滑动控件不是ConsecutiveScrollerLayout的直接子View,而是中间嵌套了其他布局,那么这个滑动控件将无法滑动。需要设置[局部滑动](#局部滑动)或者实现[滑动子view的下级view](#滑动子view的下级view)。我们建议滑动控件都应该作为ConsecutiveScrollerLayout的直接子View。
-
-2、ConsecutiveScrollerLayout的非滑动子View(如:TextView、LinearLayout等),如果它的内容有可能超出ConsecutiveScrollerLayout的显示高度,就需要使用滑动控件(如ScrollView等)包裹,否则可能内容显示不全。
-
-#### 关于margin
-
-ConsecutiveScrollerLayout支持左右margin,但是`不支持上下margin`,子View间的间距可以通过`Space`或者`空白View`设置。
-
-```xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-```
-
-#### 布局对齐方式
-
-ConsecutiveScrollerLayout的布局方式类似于垂直的LinearLayout,但是它没有gravity和子view layout_gravity属性。ConsecutiveScrollerLayout为它的子view提供了`layout_align`属性,用于设置子view和父布局的对齐方式。layout_align有三个值:`左对齐(LEFT)` 、`右对齐(RIGHT)` 和`中间对齐(CENTER)`。
-
-```xml
-
-
-
- // 对齐方式
-
-
-```
-
-#### 嵌套Fragment
-
-要想把一个Fragment嵌套在ConsecutiveScrollerLayout里。通常我们需要一个布局容器来承载我们的Fragment,或者直接把Fragment写在activity的布局里。如果Fragment是垂直滑动的,那么承载Fragment的容器需要是ConsecutiveScrollerLayout,以及Fragment的根布局也需要是垂直滑动的。我们推荐使用`ConsecutiveScrollerLayout`或者其他`可垂直滑动的控件`(比如:RecyclerView、NestedScrollView)作为Fragment的根布局。如果你的Fragment不是垂直滑动的,则可以忽略这个限制。
-
-```xml
-
-
-
-
-
-
-
-
-
-
-```
-
-### 布局吸顶
-
-要实现布局的吸顶效果,在以前,我们可能会写两个一摸一样的布局,一个隐藏在顶部,一个嵌套在ScrollView下,通过监听ScrollView的滑动来显示和隐藏顶部的布局。这种方式实现起来既麻烦也不优雅。ConsecutiveScrollerLayout内部实现了子View吸附顶部的功能,只要设置一个属性,就可以实现吸顶功能。而且支持设置多个子View吸顶,后面的View要吸顶时会把前面的吸顶View推出屏幕。
-
-```xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-```
-
-#### 常驻吸顶
-
-如果你不希望吸顶的view被后面的吸顶view顶出屏幕,而且多个吸顶view排列吸附在顶部,你可以设置常驻吸顶模式:`app:isPermanent="true"`。
-
-```xml
-
-
-
-
-```
-
-#### 关于吸顶功能的其他方法
-
-```java
-// 设置吸顶到顶部的距离,在距离顶部一定距离时开始悬停吸顶
-scrollerLayout.setStickyOffset(50);
-
-// 监听吸顶变化(普通模式)
-scrollerLayout.setOnStickyChangeListener(OnStickyChangeListener);
-// 监听吸顶变化(常驻模式)
-scrollerLayout.setOnPermanentStickyChangeListener(OnPermanentStickyChangeListener);
-// 获取当前吸顶view(普通模式)
-scrollerLayout.getCurrentStickyView();
-// 获取当前吸顶view(常驻模式)
-scrollerLayout.getCurrentStickyViews();
-// 设置吸顶常驻模式
-public void setPermanent(boolean isPermanent);
-// 判断子view是否处于吸顶状态
-public boolean theChildIsStick(View child);
-// 判断子view是否是吸顶view
-public boolean isStickyView(View child);
-
-/**
- * 在View吸顶的状态下,是否可以触摸view来滑动ConsecutiveScrollerLayout布局。
- * 默认为false,则View吸顶的状态下,不能触摸它来滑动布局
- */
-app:layout_isTriggerScroll="true"
-
-/**
- * 吸顶下沉模式
- * 默认情况下,吸顶view在吸顶状态下,会显示在布局上层,覆盖其他布局。
- * 如果设置了下沉模式,则会相反,view在吸顶时会显示在下层,被其他布局覆盖,隐藏在下面。
- * 实现的效果可参考demo中的例子
- */
-app:layout_isSink="true";
-
-```
-
-### 局部滑动
-
-ConsecutiveScrollerLayout将所有的子View视作一个整体,由它统一处理页面的滑动事件,所以它默认会拦截可滑动的子View的滑动事件,由自己来分发处理。并且会追踪用户的手指滑动事件,计算调整ConsecutiveScrollerLayout滑动偏移。如果你希望某个子View自己处理自己的滑动事件,可以通过设置layout_isConsecutive属性来告诉父View不要拦截它的滑动事件,这样就可以实现在这个View自己的高度内滑动自己的内容,而不会作为ConsecutiveScrollerLayout的一部分来处理。
-
-```xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-```
-
-在这个例子中NestedScrollView希望在自己的高度里滑动自己的内容,而不是跟随ConsecutiveScrollerLayout滑动,只要给它设置`layout_isConsecutive="false"`就可以了。而LinearLayout虽然不是滑动布局,但是在下面嵌套了个滑动布局RecyclerView,所以它也需要设置layout_isConsecutive="false"。
-
-ConsecutiveScrollerLayout支持NestedScrolling机制,如果你的局部滑动的view实现了NestedScrollingChild接口(如:RecyclerView、NestedScrollView等),它滑动完成后会把滑动事件交给父布局。如果你不想你的子view或它的下级view与父布局嵌套滑动,可以给子view设置`app:layout_isNestedScroll="false"`。它可以禁止子view与ConsecutiveScrollerLayout的嵌套滑动
-
-### 滑动子view的下级view
-
-ConsecutiveScrollerLayout默认情况下只会处理它的直接子view的滑动,但有时候需要滑动的布局可能不是ConsecutiveScrollerLayout的直接子view,而是子view所嵌套的下级view。比如ConsecutiveScrollerLayout嵌套FrameLayout,FrameLayout嵌套ScrollView,我们希望ConsecutiveScrollerLayout也能正常处理ScrollView的滑动。为了支持这种需求,ConsecutiveScroller提供了一个接口:`IConsecutiveScroller`。子view实现IConsecutiveScroller接口,并通过实现接口方法告诉ConsecutiveScrollerLayout需要滑动的下级view,ConsecutiveScrollerLayout就能正确地处理它的滑动事件。IConsecutiveScroller需要实现两个方法:
-
-```java
- /**
- * 返回当前需要滑动的下级view。在一个时间点里只能有一个view可以滑动。
- */
- View getCurrentScrollerView();
-
- /**
- * 返回所有可以滑动的子view。由于ConsecutiveScrollerLayout允许它的子view包含多个可滑动的子view,所以返回一个view列表。
- */
- List getScrolledViews();
-```
-
-在前面提到的例子中,我们可以这样实现:
-
-```java
-public class MyFrameLayout extends FrameLayout implements IConsecutiveScroller {
-
- @Override
- public View getCurrentScrollerView() {
- // 返回需要滑动的ScrollView
- return getChildAt(0);
- }
-
- @Override
- public List getScrolledViews() {
- // 返回需要滑动的ScrollView
- List views = new ArrayList<>();
- views.add(getChildAt(0));
- return views;
- }
-}
-```
-
-```xml
-
-
-
-
-
-
-
-
-
-
-
-```
-
-这样ConsecutiveScrollerLayout就能正确地处理ScrollView的滑动。这是一个简单的例子,在实际的需求中,我们一般不需要这样做。
-
-**注意:**
-
-1、getCurrentScrollerView()和getScrolledViews()必须正确地返回需要滑动的view,这些view可以是经过多层嵌套的,不一定是直接子view。所以使用者应该按照自己的实际场景去实现者两个方法。
-
-2、滑动的控件应该跟嵌套它的子view的高度保持一致,也就是说滑动的控件高度应该是match_parent,并且包裹它的子view和它本身都不要设置上下边距(margin和ppadding)。宽度没有这个限制。
-
-#### 对ViewPager的支持
-
-如果你的ViewPager承载的子布局(或Fragment)不是可以垂直滑动的,那么使用普通的ViewPager即可。如果是可以垂直滑动的,那么你的ViewPager需要实现IConsecutiveScroller接口,并返回需要滑动的view对象。框架里提供了一个实现了IConsecutiveScroller接口自定义控件:`ConsecutiveViewPager`。使用这个控件,然后你的ConsecutiveViewPager的子view(或Fragment的根布局)是可垂直滑动的view,如:RecyclerView、NestedScrollView、ConsecutiveScrollerLayout即可。这样你的ViewPager就能正确地跟ConsecutiveScrollerLayout一起滑动了。
-
-```xml
-
-
-
-
-
-
-
-
-```
-
-布局吸顶时会覆盖在下面的布局的上面,有时候我们希望TabLayout吸顶悬浮在顶部,但是不希望它覆盖遮挡ViewPager的内容。ConsecutiveViewPager提供了setAdjustHeight调整自己的布局高度,让自己不被TabLayout覆盖。注意:只有ConsecutiveScrollerLayout是ConsecutiveScrollerLayout的最低部时才能这样做。
-
-```java
-// 保证能获取到tabLayout的高度
-tabLayout.post(new Runnable() {
- @Override
- public void run() {
- viewPager.setAdjustHeight(tabLayout.getHeight());
- }
-});
-```
-
-#### 对ViewPager2的支持
-
-从4.4.0版本开始,支持在ConsecutiveScrollerLayout中使用ViewPager2。跟ViewPager一样,框架里专门提供了一个ViewPage2的自定义控件:`ConsecutiveViewPager2`。你必须使用它,而不能直接使用Androidx里的ViewPager2。不过你要使用它,依然需要引入ViewPager2依赖。
-
-```groovy
-// xxx:viewpager2版本号
-implementation 'androidx.viewpager2:viewpager2:xxx'
-```
-
-```xml
-
-
-
-
-
-
-
-
-```
-
-ConsecutiveViewPager2提供了跟ConsecutiveViewPager一样的功能,同时也支持setAdjustHeight方法,使用的限制也与ConsecutiveViewPager一样,你可以阅读上一节:**对ViewPager的支持**了解。
-
-不过ConsecutiveViewPager2并不是ViewPager2的子类(ViewPager2不允许继承),而是一个包含ViewPager2的控件,所以你不能把ConsecutiveViewPager2当作ViewPager2。但是ConsecutiveViewPager2提供了跟ViewPager2一样的常用方法,而且提供了获取ViewPager2对象的方法:
-
-```java
-public ViewPager2 getViewPager2();
-```
-
-所以你完全可以像使用ViewPager2一样使用它。
-
-**注意事项:**
-
-1、ConsecutiveViewPager2只能作为ConsecutiveScrollerLayout的子view,中间不能嵌套其他层级。
-
-2、不要给ConsecutiveViewPager2设置padding。
-
-3、ConsecutiveViewPager2不支持垂直翻页。也就是说,它只能跟ViewPager一样水平翻页和支持item垂直滑动。
-
-### 使用腾讯x5的WebView
-
-由于腾讯x5的VebView是一个FrameLayout嵌套WebView的布局,而不是一个WebView的子类,所以要在ConsecutiveScrollerLayout里使用它,需要把它的滑动交给它里面的WebView。自定义MyWebView继承腾讯的WebView,重写它的scrollBy()方法即可。
-
-```java
-public class MyWebView extends com.tencent.smtt.sdk.WebView {
-
- @Override
- public void scrollBy(int x, int y) {
- // 把滑动交给它的子view
- getView().scrollBy(x, y);
- }
-}
-```
-
-通过实现IConsecutiveScroller接口同样可以实现对x5的WebView支持。
-
-```java
-public class MyWebView extends com.tencent.smtt.sdk.WebView implements IConsecutiveScroller {
-
- @Override
- public View getCurrentScrollerView() {
- return getView();
- }
-
- @Override
- public List getScrolledViews() {
- List views = new ArrayList<>();
- views.add(getView());
- return views;
- }
-
-}
-```
-
-另外需要隐藏它的子view的滚动条
-
-```java
-View view = webView.getView();
-view.setVerticalScrollBarEnabled(false);
-view.setHorizontalScrollBarEnabled(false);
-view.setOverScrollMode(OVER_SCROLL_NEVER);
-```
-
-### 使用SmartRefreshLayout
-
-SmartRefreshLayout和SwipeRefreshLayout等刷新控件可以嵌套ConsecutiveScrollerLayout实现下拉刷新功能,但是ConsecutiveScrollerLayout内部嵌套它们来刷新子view,因为子view是ConsecutiveScrollerLayout滑动内容等一部分。除非你给SmartRefreshLayout或者SwipeRefreshLayout设置app:layout_isConsecutive="false"。
-
-如果你在页面ConsecutiveScrollerLayout嵌套Fragment,你的Fragment里不能使用SmartRefreshLayout,只能在外面的ConsecutiveScrollerLayout外嵌套SmartRefreshLayout,因为这里的Fragment是ConsecutiveScrollerLayout的一部分,不能在ConsecutiveScrollerLayout内部使用SmartRefreshLayout。这时如果你想在Fragment里使用上拉加载功能,可以将外部的SmartRefreshLayout的上拉加载回调通知给Fragment。我在demo中的ViewPagerActivity有提供一个示例,你也可以根据自己的具体业务实现。
-
-如果你使用了吸顶功能,SmartRefreshLayout上拉布局时也会把吸顶View推上去。可以使用下面的方式,让布局上拉时,吸顶view也能固定在顶部。
-
-```java
-refreshLayout.setOnMultiPurposeListener(new SimpleMultiPurposeListener() {
- @Override
- public void onFooterMoving(RefreshFooter footer, boolean isDragging, float percent, int offset, int footerHeight, int maxDragHeight) {
- // 上拉加载时,保证吸顶头部不被推出屏幕。
- // 如果你本身就设置了吸顶偏移量,那么这里的offset计算你的偏移量加offset
- scrollerLayout.setStickyOffset(offset);
- }
-});
-```
-
-### 其他常用方法
-
-```java
-
-// 修改子view的LayoutParams属性,LayoutParams属性对应xml中的app:layout_属性
-ConsecutiveScrollerLayout.LayoutParams lp = (ConsecutiveScrollerLayout.LayoutParams)view.getLayoutParams();
-// 修改各种属性
-lp.isConsecutive = false;
-lp.isSticky = false;
-view.setLayoutParams(lp);
-
-// 滑动到指定view的位置,可以设置一个位置偏移量
-public void scrollToChild(View view);
-public void scrollToChildWithOffset(View view, int offset);
-public void smoothScrollToChild(View view);
-public void smoothScrollToChildWithOffset(View view, int offset);
-
-// 判断是否滑动到顶部
-public boolean isScrollTop();
-// 判断是否滑动到底部
-public boolean isScrollBottom();
-
-// 在fling的情况下停止布局滑动
-public void stopScroll();
-
-//监听滑动
-public void setOnVerticalScrollChangeListener(OnScrollChangeListener l);
-```
-
-### 其他注意事项
-
-1、WebView在加载的过程中如果滑动的布局,可能会导致WebView与其他View在显示上断层,使用下面的方法一定程度上可以避免这个问题。
-
-```java
-webView.setWebChromeClient(new WebChromeClient() {
- @Override
- public void onProgressChanged(WebView view, int newProgress) {
- super.onProgressChanged(view, newProgress);
- scrollerLayout.checkLayoutChange();
- }
- });
-```
-
-2、如果你的RecyclerView Item大小不是固定,而是在滑动时动态变化的,可能会引起滑动时页面跳动,你可以给RecyclerView设置tag: android:tag="InterceptRequestLayout",ConsecutiveScrollerLayout内部会对具有这个tag的RecyclerView做一些处理。如果你的RecyclerView不存在这种问题,不要加这个tag,因为它会影响性能。
-
-3、继承AbsListView的布局(ListView、GridView等),在滑动上可能会与用户的手指滑动不同步,推荐使用RecyclerView代替。
-
-4、ConsecutiveScroller的minSdkVersion是19,如果你的项目支持19以下,可以设置:
-
-```xml
-
+implementation 'com.github.donkingliang:ConsecutiveScroller:4.5.0-support'
```
-但是不要在minSdkVersion小于19的项目使用AbsListView的子类,因为ConsecutiveScrollerLayout使用了只有19以上才有的AbsListView API。
+## 使用文档
-5、使用ConsecutiveScrollerLayout提供的setOnVerticalScrollChangeListener()方法监听布局的滑动事件。View所提供的setOnScrollChangeListener()方法已无效。
+查看文档请移步 [wiki](https://github.com/donkingliang/ConsecutiveScroller/wiki)
-6、通过getOwnScrollY()方法获取ConsecutiveScrollerLayout的整体垂直滑动距离,这个滑动距离包含了ConsecutiveScrollerLayout本身和所有子view的滑动距离之和。View的getScrollY()方法获取的是ConsecutiveScrollerLayout本身的滑动距离。
+## LICENSE
-7、如果嵌套WebView,请确保WebView加载的网页是符合移动端的,则网页的body高度就是显示的内容高度。否则显示不全。[#109](https://github.com/donkingliang/ConsecutiveScroller/issues/109)
+
-8、4.4.0以下版本,如果使用水平滑动的RecyclerView,需要使用FrameLayout包裹一下,不用让它作为ConsecutiveScrollerLayout的子view,否则可能会有滑动冲突。这是个bug,在4.4.0时已修复。
+ConsecutiveScroller 基于 Apache-2.0 协议进行分发和使用,更多信息参见 [协议文件](LICENSE)。