SkillAgentSearch skills...

SmoothRefreshLayout

一款支持上下拉刷新、越界回弹、二级刷新、横向刷新、拉伸回弹、平滑滚动、嵌套滚动的多功能刷新控件

Install / Use

/learn @dkzwm/SmoothRefreshLayout

README

SmoothRefreshLayout

Methods MinSdk License

English | 中文

一个高效的Android刷新库,理论上支持所有的视图,比官方的SwipeRefreshLayout更强大且使用方便.

特性:

  • 理论上支持所有的视图,且可根据具体需求高效适配.
  • 支持多点触摸.
  • 支持嵌套滑动,完整实现了NestedScrollingChild3,NestedScrollingParent3 接口,玩转CoordinatorLayout.
  • 直接继承自ViewGroup,拥有卓越的性能,支持类FameLayout的特性(Gravity、Margin).
  • 支持自动刷新、自动上拉加载、到底自动加载更多(不推荐,建议使用Adapter实现,可自定义到底判断逻辑回调实现预加载更多).
  • 支持越界回弹,支持基于物理特性的越界回弹效果.
  • 支持刷新视图自定样式:STYLE_DEFAULT(默认不改变大小)、STYLE_SCALE(动态改变大小,会在SRL内部测量并布局,所以性能会有损失)、STYLE_PIN(不会改变视图大小,固定在顶部或者底部)、STYLE_FOLLOW_SCALE(先纵向跟随移动并且不改变视图大小,大于视图高度后动态改变视图大小且性能会有损失)、STYLE_FOLLOW_PIN(不会改变视图大小,先纵向跟随移动,大于视图高度后固定)、STYLE_FOLLOW_CENTER(不会改变视图大小,先纵向跟随移动,大于视图高度后让视图保持在移动的距离中心点).
  • 支持二级刷新事件(TwoLevelSmoothRefreshLayout),PS:淘宝二楼、京东活动.
  • 支持横向刷新(HorizontalSmoothRefreshLayout).
  • 支持ListView、GridView、RecyclerView加载更多的同步平滑滚动.
  • 支持手势:同步Fling(刷新视图仍可见的情况下,会先回滚隐藏刷新视图,而后向下传递Fling手势).
  • 支持作为可拉伸内部视图布局使用(类小米设置页效果).
  • 丰富的回调接口和调试信息,可利用现有API实现丰富的效果.

引入

添加如下依赖到你的 build.gradle 文件:

dependencies {
    implementation 'com.github.dkzwm:srl-core:1.7.2.4'
    implementation 'com.github.dkzwm:srl-ext-classics:1.7.2.4'
    implementation 'com.github.dkzwm:srl-ext-material:1.7.2.4'
    implementation 'com.github.dkzwm:srl-ext-dynamic-rebound:1.7.2.4'
    implementation 'com.github.dkzwm:srl-ext-horizontal:1.7.2.4'
    implementation 'com.github.dkzwm:srl-ext-two-level:1.7.2.4'
    implementation 'com.github.dkzwm:srl-ext-util:1.7.2.4'
}

演示程序

下载 Demo.apk

更新日志

老版本升级务必查看

更新日志

快照

嵌套滑动 二级刷新

横向刷新 拉伸收缩效果

QQ红包活动 浏览器内核下拉展示

使用

在Xml中配置

<?xml version="1.0" encoding="utf-8"?>
<me.dkzwm.widget.srl.SmoothRefreshLayout
	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">
	<TextView
		android:layout_width="match_parent"
		android:layout_height="match_parent"/>
</me.dkzwm.widget.srl.SmoothRefreshLayout>

Java代码配置

SmoothRefreshLayout refreshLayout = (SmoothRefreshLayout)findViewById(R.id.smoothRefreshLayout);
refreshLayout.setHeaderView(new ClassicHeader(this));
refreshLayout.setOnRefreshListener(new RefreshingListenerAdapter() {
	@Override
	public void onRefreshing() {
		mHandler.postDelayed(new Runnable() {
			@Override
			public void run() {
				refreshLayout.refreshComplete();
			}
		}, 4000);
	}
});

自定义刷新视图

接口定义
public interface IRefreshView <T extends IIndicator> {    

    byte TYPE_HEADER = 0;
    byte TYPE_FOOTER = 1;

    byte STYLE_DEFAULT = 0;
    byte STYLE_SCALE = 1;
    byte STYLE_PIN = 2;
    byte STYLE_FOLLOW_SCALE = 3;
    byte STYLE_FOLLOW_PIN = 4;
    byte STYLE_FOLLOW_CENTER = 5;

    /**
     * 返回是头部视图还是尾部视图;
     */
    int getType();

    /**
     * 一般情况都是View实现本接口,所以返回this;
     */
    View getView();

    /**
     * 获取视图样式,自1.4.8版本后支持6种样式,STYLE_DEFAULT、STYLE_SCALE、STYLE_PIN、STYLE_FOLLOW_SCALE、STYLE_FOLLOW_PIN、STYLE_FOLLOW_CENTER;
     */
    int getStyle();

    /**
     * 获取视图的自定义高度,当视图样式为STYLE_SCALE和STYLE_FOLLOW_SCALE时,必须返回一个确切且大于0的值,使用横向刷新库时,该属性实际应该返回的是视图的宽度;
     * 自1.6.1版本开始,如果想要当前视图铺满布局即MATCH_PARENT,那么支持返回ViewGroup.LayoutParams.MATCH_PARENT对应的值即`-1`;
     */
    int getCustomHeight();

    /**
     * 手指离开屏幕;
     */
    void onFingerUp(SmoothRefreshLayout layout, T indicator);

    /**
     * 重置视图;
     */
    void onReset(SmoothRefreshLayout layout);

    /**
     * 重新配置视图,准备刷新;
     */
    void onRefreshPrepare(SmoothRefreshLayout layout);

    /**
     * 开始刷新;
     */
    void onRefreshBegin(SmoothRefreshLayout layout, T indicator);

    /**
     * 刷新完成;
     */
    void onRefreshComplete(SmoothRefreshLayout layout,boolean isSuccessful);

    /**
     * 当头部或者尾部视图发生位置变化;
     */
    void onRefreshPositionChanged(SmoothRefreshLayout layout, byte status, T indicator);

    /**
     * 当头部或者尾部视图仍然处于处理事务中,这时候移动其他刷新视图则会调用该方法;
     * 在1.4.6版本新加入;
     */
    void onPureScrollPositionChanged(SmoothRefreshLayout layout, byte status, T indicator);
}
添加自定义刷新视图
  • 全局静态代码构造
        SmoothRefreshLayout.setDefaultCreator(new IRefreshViewCreator() {
            @Override
            public IRefreshView<IIndicator> createHeader(SmoothRefreshLayout layout) {
                ClassicHeader header = new ClassicHeader(layout.getContext());
                return header;
            }

            @Override
            public IRefreshView<IIndicator> createFooter(SmoothRefreshLayout layout) {
                ClassicFooter footer = new ClassicFooter(layout.getContext());
                return footer;
            }
        });
  • 动态代码添加
        ClassicHeader header = new ClassicHeader(mRefreshLayout.getContext());
        mRefreshLayout.setHeaderView(header);
        ClassicFooter footer = new ClassicFooter(mRefreshLayout.getContext());
        mRefreshLayout.setFooterView(footer);
  • 请直接写入Xml文件,SmoothRefreshLayout会根据添加的View是否是实现了IRefreshView接口进行判断

实现类QQ下拉阻尼效果

       mRefreshLayout.setIndicatorOffsetCalculator(new IIndicator.IOffsetCalculator() {
           @Override
           public float calculate(@IIndicator.MovingStatus int status, int currentPos, float offset) {
               if (status == IIndicator.MOVING_HEADER) {
                   if (offset < 0) {
                       //如果希望拖动缩回时类似QQ一样没有阻尼效果,阻尼效果只存在于下拉则可以在此返回offset
                       //如果希望拖动缩回时类似QQ一样有阻尼效果,那么请注释掉这个判断语句
                       return offset;
                   }
                   return (float) Math.pow(Math.pow(currentPos / 2, 1.28d) + offset, 1 / 1.28d) * 2 - currentPos;
               } else if (status == IIndicator.MOVING_FOOTER) {
                   if (offset > 0) {
                       //如果希望拖动缩回时类似QQ一样没有阻尼效果,阻尼效果只存在于上拉则可以在此返回offset
                       //如果希望拖动缩回时类似QQ一样有阻尼效果,那么请注释掉这个判断语句
                       return offset;
                   }
                   return -((float) Math.pow(Math.pow(currentPos / 2, 1.28d) - offset, 1 / 1.28d) * 2 - currentPos);
               } else {
                   if (offset > 0) {
                       return (float) Math.pow(offset, 1 / 1.28d) * 2;
                   } else if (offset < 0) {
                       return -(float) Math.pow(-offset, 1 / 1.28d) * 2;
                   } else {
                       return offset;
                   }
               }
           }
       });

Xml属性

SmoothRefreshLayout 自身配置

|名称|类型|描述| |:---:|:---:|:---:| |sr_content|reference|指定内容视图的资源ID| |sr_resistance|float|移动刷新视图时候的移动阻尼(默认:1.65f)| |sr_resistanceOfFooter|float|移动Footer视图时候的移动阻尼(默认:1.65f)| |sr_resistanceOfHeader|float|移动Header视图时候的移动阻尼(默认:1.65f)| |sr_ratioToRefresh|float|触发刷新时位置占刷新视图的高度比(默认:1f)| |sr_ratioOfHeaderToRefresh|float|触发刷新时位置占Header视图的高度比(默认:1f)| |sr_ratioOfFooterToRefresh|float|触发加载更多时位置占Footer视图的高度比(默认:1f)| |sr_ratioToKeep|float|刷新中保持视图位置占刷新视图的高度比(默认:1f),该属性的值必须小于等于触发刷新高度比才会有效果| |sr_ratioToKeepHeader|float|刷新中保持视图位置占Header视图的高度比(默认:1f),该属性的值必须小于等于触发刷新高度比才会有效果| |sr_ratioToKeepFooter|float|刷新中保持视图位置占Footer视图的高度比(默认:1f),该属性的值必须小于等于触发刷新高度比才会有效果| |sr_maxMoveRatio|float|最大移动距离占刷新视图的高度比(默认:0f,表示不会触发)| |sr_maxMoveRatioOfHeader|float|最大移动距离占Header视图的高度比(默认:0f,表示不会触发)| |sr_maxMoveRatioOfFooter|float|最大移动距离占Footer视图的高度比(默认:0f,表示不会触发)| |sr_closeDuration|integer|指定收缩刷新视图到起始位置的时长(默认:350)| |sr_closeHeaderDuration|integer|指定收缩Header视图到起始位置的时长(默认:350)| |sr_closeFooterDuration|integer|指定收缩Footer视图到起始位置的时长(默认:350)| |sr_backToKeepDuration|integer|设置回滚到保持刷新视图位置的时间(默认:200)| |sr_backToKeepHeaderDuration|integer|设置回滚到保持Header视图位置的时间(默认:200)| |sr_backToKeepFooterDuration|integer|设置回滚到保持Footer视图位置的时间(默认:200)| |sr_enablePinContent|boolean|固定内容视图(默认:false)| |sr_enableKeep|boolean|刷新中保持视图停留在所设置的应该停留的位置(默认:true)| |sr_enablePullToRefresh|boolean|拉动刷新,下拉或者上拉到触发刷新位置即立即触发刷新(默认:false)| |sr_enableOverScroll|boolean|越界回弹(默认:true)| |sr_enableRefresh|boolean|设置是否启用下拉刷新(默认:ture)| |sr_enableLoadMore|boolean|设置是否启用加载更多(默认:false)| |sr_mode|enum|模式设置(默认:MODE_DEFAULT为刷新控件模式)| |sr_stickyHeader|reference|指定黏贴头部的资源ID| |sr_stickyFooter|reference|指定黏贴尾部的资源ID|

TwoLevelSmoothRefreshLayout 自身配置

|名称|类型|描述| |:---:|:---:|:---:| |sr_enableTwoLevelRefresh|boolean|设置是否启用二级刷新(默认:true)| |sr_backToKeep2Duration|boolean|设置回滚到保持二级刷新头部处于二级刷新过程中的时长(默认:500)| |sr_closeHeader2Duration|boolean|设置关闭二级刷新头部的时长(默认:500)|

SmoothRefreshLayout包裹内部其他View支持配置

|名称|类型|描述| |:---:|:---:|:---:| |layout_gravity|flag|指定其它被包裹视图的对齐属性(非 targetView、非refreshView)|

SmoothRefreshLayout java属性设置方法

|名称|参数|描述| |:---:|:---:|:---:| |setHeaderView|IRefreshView|配置头部视图| |setFooterView|IRefreshView|配置尾部视图| |setContentView|View|配置内容视图| |setMode|int|配置当前模式| |setLayoutManager|LayoutManager|配置自定义布局管理器| |setDisableWhenAnotherDirectionMove|boolean|内部视图含有其他方向滑动视图时需设置该属性为ture(默认:false)| |setMaxOverScrollDuration|int|设置越界回弹动画最长时间(默认:350)| |setMinOverScrollDuration|int|设置越界回弹动画最短时间(默认:100)| |setResistance|float|移动刷新视图时候的移动阻尼(默认:1.65f)| |setResistanceOfFooter|float|移动Footer视图时候的移动阻尼(默认:1.65f)| |setResistanceOfHeader|float|移动Header视图时候的移动阻尼(默认:1.65f)| |setRatioToRefresh|float|触发刷新时位置占刷新视图的高度比(默认:1.1f)| |setRatioOfHeaderToRefresh|float|触发刷新时位置占Header视图的高度比(默认:1.1f)| |setRatioOfFooterToRefresh|float|触发加载更多时位置

View on GitHub
GitHub Stars1.3k
CategoryDevelopment
Updated1mo ago
Forks217

Languages

Java

Security Score

100/100

Audited on Feb 25, 2026

No findings