Compose中的RefreshLayout

前言

Compose库中是没有原生的类似RefreshLayout的布局的

于是我们来自己实现一个RefreshLayout

正文

RefreshLayout

先看看RefreshLayout实现的效果:

使用下拉刷新功能代码很简单(下拉+上拉,包括自定义也很简单):

 看一下api:

/**
 * 可以任意方向拖动刷新的容器
 * @param refreshContent 刷新布局内容区域
 * @param refreshLayoutState RefreshLayout的状态,可以调用[rememberRefreshLayoutState]方法创建state并传入一个刷新时触发的回调
 * @param modifier 修饰
 * @param refreshContentThreshold 刷新布局拖动的阈值,拖动超过多少松开才算真的刷新,如果为null,表示为[refreshContent]的宽或高
 * @param composePosition 设置刷新布局所在的位置,并且间接指定了滑动方向
 * @param contentIsMove content组件是否在刷新时跟着移动,true的效果类似于PullToRefresh,false的效果类似于SwipeRefreshLayout
 * @param dragEfficiency 拖动的'有效率',比如默认是手指拖动20px,只能拖出10px
 * @param isSupportCanNotScrollCompose 是否需要支持无法滚动的组件,为true的话内部会套一层可滚动组件
 * @param userEnable 用户是否可以拖动,等于false时用户拖动无反应,但代码可以修改刷新状态
 * @param content compose内容区域
 */
@Composable
fun RefreshLayout()

/**
 * 下拉刷新
 * @param refreshLayoutState RefreshLayout的状态
 * @param modifier 修饰
 * @param refreshContent 刷新布局内容区域
 * @param content compose内容区域
 */
@Composable
fun PullToRefresh()

/**
 * 下拉刷新+上拉加载,如果内部不支持上下滑动的话,则无法使用(可以给modifier加上[verticalScroll]修饰)
 * @param topRefreshLayoutState top的刷新布局的state,可以调用[rememberRefreshLayoutState]方法创建state并传入一个刷新时触发的回调
 * @param bottomRefreshLayoutState bottom的刷新布局的state,可以调用[rememberRefreshLayoutState]方法创建state并传入一个刷新时触发的回调
 * @param modifier 修饰
 * @param topRefreshContent top的刷新布局的content,有默认样式,可以传入lambda自定义
 * @param bottomIsLoadFinish bottom刷新布局是否刷新完成
 * @param bottomRefreshContent bottom的刷新布局的content,有默认样式,可以传入lambda自定义
 * @param content 内容
 */
@Composable
fun VerticalRefreshableLayout()

原理:

原理其实和安卓xml布局中的RefreshLayout一样,就是通过拦截滑动事件,分配此次事件是父项先用还是子项先用,具体可以参考nestedScroll Modifier,其中传入的connection属性配上下面的注释应该思路就很清晰了:

    val connectionState = remember {
        object : NestedScrollConnection {
            //获取Fling动作结束时的速度
            override suspend fun onPostFling(
                consumed: Velocity,//之前消费的所有速度
                available: Velocity//当前剩下还可用的速度
            ): Velocity {
                //返回:当前组件消费的速度,如果不消费,可以返回Velocity.Zero,否则剩下的速度会继续交由当前布局的父布局进行处理
                return super.onPostFling(consumed, available)
            }

            //获取子布局处理后剩下的滑动事件
            override fun onPostScroll(
                consumed: Offset,//被消费的所有滑动事件偏移量
                available: Offset,//当前还剩下可用的滑动事件偏移量
                source: NestedScrollSource//滑动事件的类型
            ): Offset {
                //返回:当前组件消费的滑动事件偏移量,如果不想消费,可以返回Offset.Zero,否则剩下的偏移量会继续交由当前布局的父布局进行处理
                return super.onPostScroll(consumed, available, source)
            }

            //获取Fling动作开始时的速度
            override suspend fun onPreFling(
                available: Velocity//Fling动作开始时的速度
            ): Velocity {
                //返回:当前组件消费的速度,如果不消费,可以返回Velocity.Zero
                return super.onPreFling(available)
            }

            //可以预先拦截滑动事件,消费后再交由子布局
            override fun onPreScroll(
                available: Offset, //当前可用的滑动事件偏移量
                source: NestedScrollSource//滑动事件的类型
            ): Offset {
                //返回:当前组件消费的滑动事件偏移量,如果不消费,可以返回Offset.Zero
                return super.onPreScroll(available, source)
            }
        }
    }

引入项目

 在根项目的build.gradle文件中加入:

allprojects {
    repositories {
        maven { url 'https://jitpack.io' }
        ...
    }
}

app的build.gradle中加上,最新版本参考:JitPack | Publish JVM and Android libraries

dependencies{
    ...
    implementation 'com.github.ltttttttttttt:ComposeViews:1.1.4'
}

 然后就可以愉快的使用RefreshLayout了

项目已开源,欢迎star:GitHub - ltttttttttttt/ComposeViews

并且项目中不止有FlowLayout,还有更多好用的Compose组件,比如:

ComposePager

Banner

GoodTextField和PasswordTextField

FlowLayout

后续还会添加更多的Compose组件

end

猜你喜欢

转载自blog.csdn.net/qq_33505109/article/details/127115038
今日推荐