Skip to content

Commit 4b8fbb1

Browse files
committed
Merge remote-tracking branch 'git/master'
2 parents e3bef83 + 4746ef9 commit 4b8fbb1

File tree

1 file changed

+392
-0
lines changed

1 file changed

+392
-0
lines changed

README.md

Lines changed: 392 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,392 @@
1+
# RxRefreshLayout
2+
RxRefreshLayout延伸了Google的SwipeRefreshLayout的思想,不在列表控件上动刀,而是使用一个ViewGroup来包含列表控件,以保持其较低的耦合性和较高的通用性。其主要特性有:
3+
4+
1. 支持RecyclerView、ScrollView、AbsListView系列(ListView、GridView)、WebView以及其它可以获取到scrollY的控件
5+
2. 支持加载更多
6+
3. 默认支持 **越界回弹**,随手势速度有不同的效果
7+
4. 可开启没有刷新控件的纯净越界回弹模式
8+
5. setOnRefreshListener中拥有大量可以回调的方法
9+
6. 将Header和Footer抽象成了接口,并回调了滑动过程中的系数,方便实现个性化的Header和Footer
10+
7. 支持NestedScroll,嵌套CoordinatorLayout
11+
12+
13+
## tip
14+
欢迎朋友们多多star支持
15+
16+
## 集成AS
17+
18+
> Step 1.先在 build.gradle(Project:XXXX) 的 repositories 添加:
19+
20+
allprojects {
21+
repositories {
22+
...
23+
maven { url "https://jitpack.io" }
24+
}
25+
}
26+
> Step 2. 然后在 build.gradle(Module:app) 的 dependencies 添加:
27+
28+
dependencies {
29+
//基础工具库
30+
implementation 'com.github.zhangi789:RxRefreshLayout:3.1.2'
31+
}
32+
33+
#### 2.在xml中添加RxRefreshLayout
34+
```xml
35+
<?xml version="1.0" encoding="utf-8"?>
36+
<com.xfresh.cn.RxRefreshLayout
37+
xmlns:android="http://schemas.android.com/apk/res/android"
38+
xmlns:app="http://schemas.android.com/apk/res-auto"
39+
android:id="@+id/refreshLayout"
40+
android:layout_width="match_parent"
41+
android:layout_height="match_parent"
42+
app:tr_wave_height="180dp"
43+
app:tr_head_height="100dp">
44+
45+
<android.support.v7.widget.RecyclerView
46+
android:id="@+id/recyclerview"
47+
android:layout_width="match_parent"
48+
android:layout_height="match_parent"
49+
android:overScrollMode="never"
50+
android:background="#fff" />
51+
</com.xfresh.cn.RxRefreshLayout>
52+
```
53+
54+
Android系统为了跟iOS不一样,当界面OverScroll的时候会显示一个阴影。为了达到更好的显示效果,最好禁用系统的overScroll,如上给RecyclerView添加`android:overScrollMode="never"`
55+
56+
#### 3.在Activity或者Fragment中配置
57+
##### RxRefreshLayout不会自动结束刷新或者加载更多,需要手动控制
58+
```java
59+
refreshLayout.setOnRefreshListener(new RefreshListenerAdapter(){
60+
@Override
61+
public void onRefresh(final TwinklingRefreshLayout refreshLayout) {
62+
new Handler().postDelayed(new Runnable() {
63+
@Override
64+
public void run() {
65+
refreshLayout.finishRefreshing();
66+
}
67+
},2000);
68+
}
69+
70+
@Override
71+
public void onLoadMore(final TwinklingRefreshLayout refreshLayout) {
72+
new Handler().postDelayed(new Runnable() {
73+
@Override
74+
public void run() {
75+
refreshLayout.finishLoadmore();
76+
}
77+
},2000);
78+
}
79+
});
80+
}
81+
```
82+
使用finishRefreshing()方法结束刷新,finishLoadmore()方法结束加载更多。此处OnRefreshListener还有其它方法,可以选择需要的来重写。
83+
84+
如果你想进入到界面的时候主动调用下刷新,可以调用startRefresh()/startLoadmore()方法。
85+
86+
##### setWaveHeight、setHeaderHeight、setBottomHeight、setOverScrollHeight
87+
- setMaxHeadHeight 设置头部可拉伸的最大高度。
88+
- setHeaderHeight 头部固定高度(在此高度上显示刷新状态)
89+
- setMaxBottomHeight
90+
- setBottomHeight 底部高度
91+
- setOverScrollHeight 设置最大的越界高度
92+
93+
#### setEnableRefresh、setEnableLoadmore
94+
灵活的设置是否禁用上下拉。
95+
96+
##### setHeaderView(IHeaderView headerView)、setBottomView(IBottomView bottomView)
97+
设置头部/底部个性化刷新效果,头部需要实现IHeaderView,底部需要实现IBottomView。
98+
99+
#### setEnableOverScroll
100+
是否允许越界回弹。
101+
102+
##### setOverScrollTopShow、setOverScrollBottomShow、setOverScrollRefreshShow
103+
是否允许在越界的时候显示刷新控件,默认是允许的,也就是Fling越界的时候Header或Footer照常显示,反之就是不显示;可能有特殊的情况,刷新控件会影响显示体验才设立了这个状态。
104+
105+
##### setPureScrollModeOn()
106+
开启纯净的越界回弹模式,也就是所有刷新相关的View都不显示,只显示越界回弹效果
107+
108+
##### setAutoLoadMore
109+
是否在底部越界的时候自动切换到加载更多模式
110+
111+
##### addFixedExHeader
112+
添加一个固定在顶部的Header(效果还需要优化)
113+
114+
##### startRefresh、startLoadMore、finishRefreshing、finishLoadmore
115+
116+
##### setFloatRefresh(boolean)
117+
支持切换到像SwipeRefreshLayout一样的悬浮刷新模式了。
118+
119+
##### setTargetView(View view)
120+
设置滚动事件的作用对象。
121+
122+
##### setDefaultHeader、setDefaultFooter
123+
现在已经提供了设置默认的Header、Footer的static方法,可在Application或者一个Activity中这样设置:
124+
```java
125+
RxRefreshLayout.setDefaultHeader(SinaRefreshView.class.getName());
126+
RxRefreshLayout.setDefaultFooter(BallPulseView.class.getName());
127+
```
128+
129+
130+
#### 4.扩展属性
131+
- tr_max_head_height 头部拉伸允许的最大高度
132+
- tr_head_height 头部高度
133+
- tr_max_bottom_height
134+
- tr_bottom_height 底部高度
135+
- tr_overscroll_height 允许越界的最大高度
136+
- tr_enable_refresh 是否允许刷新,默认为true
137+
- tr_enable_loadmore 是否允许加载更多,默认为true
138+
- tr_pureScrollMode_on 是否开启纯净的越界回弹模式
139+
- tr_overscroll_top_show - 否允许顶部越界时显示顶部View
140+
- tr_overscroll_bottom_show 是否允许底部越界时显示底部View
141+
- tr_enable_overscroll 是否允许越界回弹
142+
- tr_floatRefresh 开启悬浮刷新模式
143+
- tr_autoLoadMore 越界时自动加载更多
144+
- tr_enable_keepIView 是否在开始刷新之后保持状态,默认为true;若需要保持原来的操作逻辑,这里设置为false即可
145+
- tr_showRefreshingWhenOverScroll 越界时直接显示正在刷新中的头部
146+
- tr_showLoadingWhenOverScroll 越界时直接显示正在加载更多中的底部
147+
148+
## 其它说明
149+
### 1.默认支持越界回弹,并可以随手势越界不同的高度
150+
这一点很多类似SwipeRefreshLayout的刷新控件都没有做到(包括SwipeRefreshLayout),因为没有拦截下来的时间会传递给列表控件,而列表控件的滚动状态很难获取。解决方案就是给列表控件设置了OnTouchListener并把事件交给GestureDetector处理,然后在列表控件的OnScrollListener中监听View是否滚动到了顶部(没有OnScrollListener的则采用延时监听策略)。
151+
152+
### 2.setOnRefreshListener大量可以回调的方法
153+
- onPullingDown(TwinklingRefreshLayout refreshLayout, float fraction) 正在下拉的过程
154+
- onPullingUp(TwinklingRefreshLayout refreshLayout, float fraction) 正在上拉的过程
155+
- onPullDownReleasing(TwinklingRefreshLayout refreshLayout, float fraction) 下拉释放过程
156+
- onPullUpReleasing(TwinklingRefreshLayout refreshLayout, float fraction) 上拉释放过程
157+
- onRefresh(TwinklingRefreshLayout refreshLayout) 正在刷新
158+
- onLoadMore(TwinklingRefreshLayout refreshLayout) 正在加载更多
159+
160+
其中fraction表示当前下拉的距离与Header高度的比值(或者当前上拉距离与Footer高度的比值)。
161+
162+
### 3.Header和Footer
163+
##### BezierLayout(pic 4)
164+
- setWaveColor
165+
- setRippleColor
166+
167+
##### GoogleDotView(pic 5)
168+
##### SinaRefreshView(pic 3)
169+
- setArrowResource
170+
- setTextColor
171+
- setPullDownStr
172+
- setReleaseRefreshStr
173+
- setRefreshingStr
174+
175+
##### ProgressLayout(SwipeRefreshLayout pic 6)
176+
- setProgressBackgroundColorSchemeResource(@ColorRes int colorRes)
177+
- setProgressBackgroundColorSchemeColor(@ColorInt int color)
178+
- setColorSchemeResources(@ColorRes int... colorResIds)
179+
180+
####Footer
181+
##### BallPulseView(pic 2)
182+
- setNormalColor(@ColorInt int color)
183+
- setAnimatingColor(@ColorInt int color)
184+
185+
##### LoadingView(pic 3)
186+
更多动效可以参考[AVLoadingIndicatorView](https://github.com/81813780/AVLoadingIndicatorView)库。
187+
188+
189+
### 3.实现个性化的Header和Footer
190+
相关接口分别为IHeaderView和IBottomView,代码如下:
191+
```java
192+
public interface IHeaderView {
193+
View getView();
194+
195+
void onPullingDown(float fraction,float maxHeadHeight,float headHeight);
196+
197+
void onPullReleasing(float fraction,float maxHeadHeight,float headHeight);
198+
199+
void startAnim(float maxHeadHeight,float headHeight);
200+
201+
void reset();
202+
}
203+
```
204+
205+
其中getView()方法用于在TwinklingRefreshLayout中获取到实际的Header,因此不能返回null。
206+
207+
**实现像新浪微博那样的刷新效果**(有部分修改,具体请看源码),实现代码如下:
208+
209+
1.首先定义SinaRefreshHeader继承自FrameLayout并实现IHeaderView方法
210+
211+
2.getView()方法中返回this
212+
213+
3.在onAttachedToWindow()或者构造函数方法中获取一下需要用到的布局
214+
215+
4. 在onFinish()方法中调用listener.onAnimEnd()。此方法的目的是为了在finish之前可以执行一段动画。
216+
217+
```java
218+
private void init() {
219+
View rootView = View.inflate(getContext(), R.layout.view_sinaheader, null);
220+
refreshArrow = (ImageView) rootView.findViewById(R.id.iv_arrow);
221+
refreshTextView = (TextView) rootView.findViewById(R.id.tv);
222+
loadingView = (ImageView) rootView.findViewById(R.id.iv_loading);
223+
addView(rootView);
224+
}
225+
```
226+
227+
4.实现其它方法
228+
```java
229+
@Override
230+
public void onPullingDown(float fraction, float maxHeadHeight, float headHeight) {
231+
if (fraction < 1f) refreshTextView.setText(pullDownStr);
232+
if (fraction > 1f) refreshTextView.setText(releaseRefreshStr);
233+
refreshArrow.setRotation(fraction * headHeight / maxHeadHeight * 180);
234+
235+
236+
}
237+
238+
@Override
239+
public void onPullReleasing(float fraction, float maxHeadHeight, float headHeight) {
240+
if (fraction < 1f) {
241+
refreshTextView.setText(pullDownStr);
242+
refreshArrow.setRotation(fraction * headHeight / maxHeadHeight * 180);
243+
if (refreshArrow.getVisibility() == GONE) {
244+
refreshArrow.setVisibility(VISIBLE);
245+
loadingView.setVisibility(GONE);
246+
}
247+
}
248+
}
249+
250+
@Override
251+
public void startAnim(float maxHeadHeight, float headHeight) {
252+
refreshTextView.setText(refreshingStr);
253+
refreshArrow.setVisibility(GONE);
254+
loadingView.setVisibility(VISIBLE);
255+
}
256+
257+
@Override
258+
public void onFinish(OnAnimEndListener listener) {
259+
listener.onAnimEnd();
260+
}
261+
```
262+
263+
5.布局文件
264+
```xml
265+
<?xml version="1.0" encoding="utf-8"?>
266+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
267+
android:orientation="horizontal" android:layout_width="match_parent"
268+
android:layout_height="match_parent"
269+
android:gravity="center">
270+
<ImageView
271+
android:id="@+id/iv_arrow"
272+
android:layout_width="wrap_content"
273+
android:layout_height="wrap_content"
274+
android:src="@drawable/ic_arrow"/>
275+
276+
<ImageView
277+
android:id="@+id/iv_loading"
278+
android:visibility="gone"
279+
android:layout_width="34dp"
280+
android:layout_height="34dp"
281+
android:src="@drawable/anim_loading_view"/>
282+
283+
<TextView
284+
android:id="@+id/tv"
285+
android:layout_width="wrap_content"
286+
android:layout_height="wrap_content"
287+
android:layout_marginLeft="16dp"
288+
android:textSize="16sp"
289+
android:text="下拉刷新"/>
290+
</LinearLayout>
291+
```
292+
293+
注意fraction的使用,比如上面的代码`refreshArrow.setRotation(fraction * headHeight / maxHeadHeight * 180)``fraction * headHeight`表示当前头部滑动的距离,然后算出它和最大高度的比例,然后乘以180,可以使得在滑动到最大距离时Arrow恰好能旋转180度。
294+
295+
296+
onPullingDown/onPullingUp表示正在下拉/正在上拉的过程。
297+
onPullReleasing表示向上拉/下拉释放时回调的状态。
298+
startAnim则是在onRefresh/onLoadMore之后才会回调的过程(此处是显示了加载中的小菊花)
299+
300+
如上所示,轻而易举就可以实现一个个性化的Header或者Footer。(更简单的实现请参考Demo中的 **TextHeaderView(图四)**)。
301+
302+
### NestedScroll
303+
#### RxRefreshLayout嵌套CoordinatorLayout
304+
---layout
305+
```xml
306+
<?xml version="1.0" encoding="utf-8"?>
307+
<com.xfresh.cn.RxRefreshLayout
308+
xmlns:android="http://schemas.android.com/apk/res/android"
309+
xmlns:app="http://schemas.android.com/apk/res-auto"
310+
android:id="@+id/refresh"
311+
android:layout_width="match_parent"
312+
android:layout_height="match_parent">
313+
314+
<android.support.design.widget.CoordinatorLayout
315+
android:id="@+id/coord_container"
316+
android:layout_width="match_parent"
317+
android:layout_height="match_parent"
318+
android:addStatesFromChildren="true"
319+
android:fitsSystemWindows="true">
320+
321+
<android.support.design.widget.AppBarLayout
322+
android:id="@+id/appbar_layout"
323+
android:layout_width="match_parent"
324+
android:layout_height="wrap_content"
325+
android:clipChildren="false">
326+
327+
<!--...-->
328+
329+
</android.support.design.widget.AppBarLayout>
330+
331+
<android.support.v7.widget.RecyclerView
332+
android:id="@+id/recyclerview"
333+
android:layout_width="match_parent"
334+
android:layout_height="match_parent"
335+
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
336+
337+
</android.support.design.widget.CoordinatorLayout>
338+
</com.xfresh.cn.RxRefreshLayout>
339+
```
340+
341+
--- 代码1
342+
```
343+
refreshLayout.setTargetView(rv);
344+
```
345+
让refreshLayout能够找到RecyclerView/ListView
346+
347+
--- 代码2
348+
```java
349+
AppBarLayout appBarLayout = (AppBarLayout) findViewById(R.id.appbar_layout);
350+
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
351+
@Override
352+
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
353+
if (verticalOffset >= 0) {
354+
refreshLayout.setEnableRefresh(true);
355+
refreshLayout.setEnableOverScroll(false);
356+
} else {
357+
refreshLayout.setEnableRefresh(false);
358+
refreshLayout.setEnableOverScroll(false);
359+
}
360+
}
361+
});
362+
```
363+
设置AppBarLayout的移动监听器,需要下拉显示AppBarLayout时需设置setEnableRefresh(false),setEnableOverScroll(false);AppBarLayout隐藏后还原为原来设置的值即可。
364+
365+
####CoordinatorLayout嵌套RxRefreshLayout
366+
--- layout
367+
```xml
368+
<?xml version="1.0" encoding="utf-8"?>
369+
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
370+
xmlns:app="http://schemas.android.com/apk/res-auto"
371+
android:id="@+id/coord_container"
372+
android:layout_width="match_parent"
373+
android:layout_height="match_parent"
374+
android:addStatesFromChildren="true"
375+
android:fitsSystemWindows="true">
376+
377+
<com.xfresh.cn.RxRefreshLayout
378+
android:id="@+id/refresh"
379+
android:layout_width="match_parent"
380+
android:layout_height="match_parent"
381+
app:layout_behavior="@string/appbar_scrolling_view_behavior">
382+
383+
<android.support.v7.widget.RecyclerView
384+
android:id="@+id/recyclerview"
385+
android:layout_width="match_parent"
386+
android:layout_height="match_parent" />
387+
388+
</com.xfresh.cn.RxRefreshLayout>
389+
390+
</android.support.design.widget.CoordinatorLayout>
391+
```
392+
注意给RxRefreshLayout设置一个layout_behavior="@string/appbar_scrolling_view_behavior"

0 commit comments

Comments
 (0)