您的位置:首页 > 其它

TwinklingRefreshLayout 支持下拉刷新和上拉加载的 RefreshLayout,自带越界回弹效果,支持 RecyclerView,AbsListView,ScrollView等

2017-04-19 17:03 961 查看


TwinklingRefreshLayout

项目地址:lcodecorex/TwinklingRefreshLayout


简介:支持下拉刷新和上拉加载的 RefreshLayout,自带越界回弹效果,支持 RecyclerView,AbsListView,ScrollView,WebView

English
Version
TwinklingRefreshLayout 延伸了 Google 的 SwipeRefreshLayout 的思想,不在列表控件上动刀,而是使用一个 ViewGroup 来包含列表控件,以保持其较低的耦合性和较高的通用性。其主要特性有:
支持 RecyclerView、ScrollView、AbsListView 系列(ListView、GridView)、WebView 以及其它可以获取到 scrollY 的控件
支持加载更多
默认支持 越界回弹
可开启没有刷新控件的纯净越界回弹模式
setOnRefreshListener 中拥有大量可以回调的方法
将 Header 和 Footer 抽象成了接口,并回调了滑动过程中的系数,方便实现个性化的 Header 和 Footer




Demo

下载
Demo


 

 

 





使用方法


1.添加 gradle 依赖

将 libray 模块复制到项目中,或者直接在 build.gradle 中依赖:
compile 'com.lcodecorex:tkrefreshlayout:1.0.3'


2.在 xml 中添加 TwinklingRefreshLayout

<?xml version="1.0" encoding="utf-8"?>
<com.lcodecore.library.TwinklingRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/refreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:tr_wave_height="180dp"
app:tr_head_height="100dp">

<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff" />
</com.lcodecore.library.TwinklingRefreshLayout>


3.在 Activity 或者 Fragment 中配置


TwinklingRefreshLayout 不会自动结束刷新或者加载更多,需要手动控制

refreshLayout.setOnRefreshListener(new TwinklingRefreshLayout.OnRefreshListener(){
@Override
public void onRefresh(final TwinklingRefreshLayout refreshLayout) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
refreshLayout.finishRefreshing();
}
},2000);
}

@Override
public void onLoadMore(final TwinklingRefreshLayout refreshLayout) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
refreshLayout.finishLoadmore();
}
},2000);
}
});
}

使用 finishRefreshing()方法结束刷新,finishLoadmore()方法结束加载更多。此处 OnRefreshListener 还有其它方法,可以选择需要的来重写。

setWaveHeight、setHeaderHeight、setBottomHeight

setWaveHeight 设置头部可拉伸的最大高度。
setHeaderHeight 头部固定高度(在此高度上显示刷新状态)
setBottomHeight 底部高度


setEnableRefresh、setEnableLoadmore

灵活的设置是否禁用上下拉。

setHeaderView(IHeaderView headerView)、setBottomView(IBottomView bottomView)

设置头部/底部个性化刷新效果,头部需要实现 IHeaderView,底部需要实现 IBottomView。

setEnableOverlayRefreshView()

是否允许在越界的时候显示刷新控件,默认是允许的,也就是 Fling 越界的时候 Header 或 Footer 照常显示,反之就是不显示;可能有特殊的情况,刷新控件会影响显示体验才设立了这个状态。

setPureScrollModeOn()

开启纯净的越界回弹模式,也就是所有刷新相关的 View 都不显示,只显示越界回弹效果


4.扩展属性

tr_wave_height 头部拉伸允许的最大高度
tr_head_height 头部高度
tr_bottom_height 底部高度
tr_overscroll_height 允许越界的最大高度
tr_enable_loadmore 是否允许加载更多,默认为 true
tr_pureScrollMode_on 是否开启纯净的越界回弹模式
tr_show_overlay_refreshview 是否在越界的时候展示刷新控件


5.在 ViewPager+Fragment 中使用的注意事项

ViewPager 默认最大加载 3 个 Fragment,Fragment 被切换到 3 个之外时,Fragment 会调用 onDestroyView()方法,当再次切换回来时,View 会被重新创建。上一版的 Demo 有点小 bug,目前都已修复。


其它说明


1.默认支持越界回弹

这一点很多类似 SwipeRefreshLayout 的刷新控件都没有做到(包括 SwipeRefreshLayout),因为没有拦截下来的时间会传递给列表控件,而列表控件的滚动状态很难获取。解决方案就是给列表控件设置了 OnTouchListener 并把事件交给 GestureDetector 处理,然后在列表控件的 OnScrollListener 中监听 View 是否滚动到了顶部(没有 OnScrollListener
的则采用延时监听策略)。


2.setOnRefreshListener 大量可以回调的方法

onPullingDown(TwinklingRefreshLayout refreshLayout, float fraction) 正在下拉的过程
onPullingUp(TwinklingRefreshLayout refreshLayout, float fraction) 正在上拉的过程
onPullDownReleasing(TwinklingRefreshLayout refreshLayout, float fraction) 下拉释放过程
onPullUpReleasing(TwinklingRefreshLayout refreshLayout, float fraction) 上拉释放过程
onRefresh(TwinklingRefreshLayout refreshLayout) 正在刷新
onLoadMore(TwinklingRefreshLayout refreshLayout) 正在加载更多
其中 fraction 表示当前下拉的距离与 Header 高度的比值(或者当前上拉距离与 Footer 高度的比值)。


3.Header 和 Footer

目前已实现的 Header 有BezierLayout(图一),GoogleDotView(图二),SinaRefreshView(图三);实现的 Footer 有 BottomProgressView(图一),LoadingView(图三),更多动效可以参考AVLoadingIndicatorView库。
其中第一幅图源于BeautifulRefreshForGirl,原来的动效只支持
21 以上版本,且滑动过程中会出现 View 消失的情况,笔者做了一些优化并使其可以正常的在界面中使用。


3.实现个性化的 Header 和 Footer

相关接口分别为 IHeaderView 和 IBottomView,代码如下:
public interface IHeaderView {
View getView();

void onPullingDown(float fraction,float maxHeadHeight,float headHeight);

void onPullReleasing(float fraction,float maxHeadHeight,float headHeight);

void startAnim(float maxHeadHeight,float headHeight);
}

其中 getView()方法用于在 TwinklingRefreshLayout 中获取到实际的 Header,因此不能返回 null。
实现像新浪微博那样的刷新效果(有部分修改,具体请看源码),实现代码如下:
1.首先定义 SinaRefreshHeader 继承自 FrameLayout 并实现 IHeaderView 方法
2.getView()方法中返回 this
3.在 onAttachedToWindow()或者构造函数方法中获取一下需要用到的布局
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();

if (rootView == null) {
rootView = View.inflate(getContext(), R.layout.view_sinaheader, null);
refreshArrow = (ImageView) rootView.findViewById(R.id.iv_arrow);
refreshTextView = (TextView) rootView.findViewById(R.id.tv);
loadingView = (ImageView) rootView.findViewById(R.id.iv_loading);
addView(rootView);
}
}

4.实现其它方法
@Override
public void onPullingDown(float fraction, float maxHeadHeight, float headHeight) {
if (fraction < 1f) refreshTextView.setText(pullDownStr);
if (fraction > 1f) refreshTextView.setText(releaseRefreshStr);
refreshArrow.setRotation(fraction * headHeight / maxHeadHeight * 180);

}

@Override
public void onPullReleasing(float fraction, float maxHeadHeight, float headHeight) {
if (fraction < 1f) {
refreshTextView.setText(pullDownStr);
refreshArrow.setRotation(fraction * headHeight / maxHeadHeight * 180);
if (refreshArrow.getVisibility() == GONE) {
refreshArrow.setVisibility(VISIBLE);
loadingView.setVisibility(GONE);
}
}
}

@Override
public void startAnim(float maxHeadHeight, float headHeight) {
refreshTextView.setText(refreshingStr);
refreshArrow.setVisibility(GONE);
loadingView.setVisibility(VISIBLE);
}

5.布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">

a514
<ImageView
android:id="@+id/iv_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_arrow"/>

<ImageView
android:id="@+id/iv_loading"
android:visibility="gone"
android:layout_width="34dp"
android:layout_height="34dp"
android:src="@drawable/anim_loading_view"/>

<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:textSize="16sp"
android:text="下拉刷新"/>
</LinearLayout>

注意 fraction 的使用,比如上面的代码
refreshArrow.setRotation(fraction
* headHeight / maxHeadHeight * 180)
fraction * headHeight
表示当前头部滑动的距离,然后算出它和最大高度的比例,然后乘以
180,可以使得在滑动到最大距离时 Arrow 恰好能旋转 180 度。
onPullingDown/onPullingUp 表示正在下拉/正在上拉的过程。 onPullReleasing 表示向上拉/下拉释放时回调的状态。 startAnim 则是在 onRefresh/onLoadMore 之后才会回调的过程(此处是显示了加载中的小菊花)
如上所示,轻而易举就可以实现一个个性化的 Header 或者 Footer。(更简单的实现请参考 Demo 中的TextHeaderView(图四))。


剩余问题

制作一个 star 相关的动效。
对回弹效果做一下优化,比如支持使用不同的插值器
带视差效果的 Header
SwipeRefreshLayout 风格的刷新 View
允许结束刷新/加载更多前先执行完自定义动画


更新日志


v1.03

扩展了更多的属性
修复 Fragment 回收导致的空指针异常问题
加入 x 方向判断,减小了滑动冲突
优化加载更多列表显示问题
可以灵活的设置是否禁用上下拉
修复 GridView 滑动过程中出现的白条问题
Demo 中添加轮播条展示


v1.02

修复加载更多列表控件的显示问题


v1.01

支持了 RecyclerView、ScrollView、AbsListView、WebView
支持越界回弹
支持个性化 Header、Footer
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐