前言
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