代码量最少, 使用便捷, 非侵入式, 知足常见需求, 同时方便扩展和自定义.android
用最少的代码实现开发过程当中的常见需求:git
多类型github
添加头布局和脚布局bash
点击/长按事件网络
切换模式app
选择模式框架
拖拽移动异步
侧滑删除maven
下拉刷新 | 上拉加载 (PageRefreshLayout|SmartRefreshLayout)ide
多状态缺省页 (PageRefreshLayout)
自动分页加载 (PageRefreshLayout)
扩展
伸缩布局 (FlexboxLayoutManager)
自动化网络请求 (KalleExtension)
该网络请求基于Kalle|RxJava|Moshi|LifeCycle|本库 实现自动化的网络请求
将来将支持:
project of build.gradle
allprojects {
repositories {
// ...
maven { url 'https://jitpack.io' }
}
}
复制代码
module of build.gradle
implementation 'com.github.liangjingkanji:BRV:1.0.4'
复制代码
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
BindingAdapter.modelId = BR.m // 推荐在Application中进行初始化或使用以前便可
}
}
复制代码
快速建立布局管理器
fun RecyclerView.linear( @RecyclerView.Orientation orientation: Int = VERTICAL, reverseLayout: Boolean = false )
fun RecyclerView.grid( spanCount: Int, @RecyclerView.Orientation orientation: Int = VERTICAL, reverseLayout: Boolean = false )
fun RecyclerView.staggered( spanCount: Int, @RecyclerView.Orientation orientation: Int = VERTICAL )
复制代码
rv.linear().setup {
addType<Model>(R.layout.item_1)
addType<Store>(R.layout.item_2)
}.models = data
复制代码
开发中经常遇到一个列表, 列表每一个数据对应的一个字段来判断itemType
addType<Model>{
// 使用年龄来做为判断返回不一样的布局
when (age) {
23 -> {
R.layout.item_1
}
else -> {
R.layout.item_2
}
}
}
复制代码
快速实现分割线
fun RecyclerView.divider( @DrawableRes drawable: Int, @RecyclerView.Orientation orientation: Int = RecyclerView.VERTICAL, block: ((Rect, View, RecyclerView, RecyclerView.State) -> Boolean)? = null
)
复制代码
监听事件须要先添加想要监听的view
fun addClickable(@IdRes vararg id: Int)
// 过滤500毫秒内重复点击
fun addFastClickable(@IdRes vararg id: Int)
// 区别于上面函数不过滤重复点击事件
fun addLongClickable(@IdRes vararg id: Int)
// 长按事件
复制代码
事件回调
onClick{
}
// 点击事件
onLongClick{
}
// 长按点击事件
onBind {
false
}
复制代码
onBind
属于onBindViewHolder
事件监听.
若是你须要本身去设置数据或绑定事件就使用该函数. 返回值决定是否用框架内部默认的Databinding绑定布局. false
表示不绑定.
更简单的写法示例
rv.linear().setup {
addType<Model>{
R.layout.item_1
}
onClick(R.id.item, R.id.user_portrait){
}
onLongClick(R.id.item){
}
}.models = data
复制代码
头布局和脚布局在rv中算做一个item, 因此计算position
的时候应当考虑其.
操做头布局
fun addHeader(view: View)
fun removeHeader(view: View)
fun clearHeader()
fun isHeader(@IntRange(from = 0) position: Int): Boolean
复制代码
操做脚布局
fun addFooter(view: View)
fun removeFooter(view: View)
fun clearFooter()
fun isFooter(@IntRange(from = 0) position: Int): Boolean
复制代码
获取数据
val headerCount: Int
val footerCount: Int
复制代码
获取数据的最终手段不是只有一种而已能够存在对重对称加密手段
切换模式至关于会提供一个回调函数遍历全部的item, 你能够在这个回调函数里面依次刷新他们.
经常使用于切换选择模式.
fun toggle()
// 切换模式
fun getToggleMode(): Boolean
// 范围当前出何种切换模式
fun setToggleMode(toggleMode: Boolean)
// 设置切换模式, 若是设置的是当前正处于的模式不会触发回调
复制代码
回调函数
onToggle { type, position, toggleMode -> // 类型 位置 切换布尔值
// 在这里能够给item刷新成选择模式
}
// 切换完成
onToggleEnd {
// 例如切换工具栏为选择模式
}
复制代码
fun allChecked()
// 全选
fun allChecked(isAllChecked: Boolean)
// 全选或者所有取消全选
fun clearChecked()
// 取消全选
fun reverseChecked()
// 反选
fun setChecked(@IntRange(from = 0) position: Int, checked: Boolean)
// 设置某个item的选择状态
fun toggleChecked(@IntRange(from = 0) position: Int)
// 切换某个item的选择状态
fun <M> getCheckedModels(): List<M>
fun setCheckableType(@LayoutRes vararg checkableItemType: Int)
// 设置哪些type容许进入选择状态
val checkedCount: Int
复制代码
只支持拖拽移动和侧滑删除
步骤:
ItemTouchHelper
支持ItemModel
BindingAdapter提供一个字段来开启ItemTouchHelper支持
var touchEnable = false // 默认关闭
复制代码
而后数据模型要求继承ItemModel
, 根据需求重写函数.
示例:
data class Model(val name: String) : ItemModel() {
override fun getDrag(): Int {
return UP or DOWN
}
override fun getSwipe(): Int {
return RIGHT or LEFT
}
}
复制代码
RIGHT or LEFT
是控制拖拽和侧滑的方向(侧滑不支持UP/DOWN)的常量.
拖拽移动item会自动改变数据模型在数据集合中的位置.
扩展功能
若是想要扩展ItemTouchHelper能够给BindingAdapter的变量itemTouchHelper
赋值
rv.linear().setup {
addType<Model>(R.layout.item)
touchEnable = true
itemTouchHelper = ItemTouchHelper(object : DefaultItemTouchCallback(this) {
// 这里能够重写函数
})
}.models = data
复制代码
经过给view打上tag标签 swipe
能够控制侧滑将会移动的视图.
<RelativeLayout android:layout_width="wrap_content" android:layout_height="80dp" android:orientation="horizontal" android:tag="swipe"/>
复制代码
内部依赖 StateLayout, 该库支持任意 Activity | Fragment | View 实现缺省页功能.
主要特色
本库已经依赖, 无需再次依赖. 使用方法见GitHub.
该布局扩展自 SmartRefreshLayout(该库强烈推荐使用), 支持其全部特性.
本库已引入SmartRefreshLayout 'com.scwang.smart:refresh-layout-kernel:2.0.0-alpha-1'
, 无需再次引入.
针对须要的请求头能够去其开源地址分包引入.
在此基础上增长特性
// 1. 代码建立, 经过扩展函数
val page = rv.page()
// 2. 布局包裹
<com.drake.brv.PageRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/page" app:stateEnabled="true" android:layout_height="match_parent" tools:context="com.drake.brv.sample.fragment.RefreshFragment">
<androidx.recyclerview.widget.RecyclerView android:id="@+id/rv" android:layout_width="match_parent" android:layout_height="match_parent" />
</com.drake.brv.PageRefreshLayout>
复制代码
// 下拉刷新
page.onRefresh {
// 这里能够进行网络请求等异步操做
}
// 上拉加载
page.onLoadMore {
// 这里能够进行网络请求等异步操做
}
复制代码
若是onLoadMore
不调用则上拉加载一样也会回调onRefresh
函数, 由于下拉刷新和上拉加载可能都是走的同一个网络请求.
触发刷新状态(二者都会回调函数onRefresh)
autoRefesh
这是触发的下拉刷新showLoading
这是触发的加载页面, 固然得先设置loadingLayout(或者读取全局缺省页配置)refresh
静默刷新, 不会触发任何动画s第二种方式通常用于初次进入页面时候加载数据, 这三种方式都会致使索引index=startIndex
重置.
其余状态控制
showEmpty()
showError()
showContent
复制代码
配置全局缺省页
这块代码和StateLayout公用
/** * 推荐在Application中进行全局配置缺省页, 固然一样每一个页面能够单独指定缺省页. * 具体查看 https://github.com/liangjingkanji/StateLayout */
StateConfig.apply {
emptyLayout = R.layout.layout_empty
errorLayout = R.layout.layout_error
loadingLayout = R.layout.layout_loading
onLoading {
// 今生命周期能够拿到LoadingLayout建立的视图对象, 能够进行动画设置或点击事件.
}
}
复制代码
单例缺省页配置支持两种方式
<com.drake.brv.PageRefreshLayout ..... app:stateEnabled="true" app:error_layout="@layout/layout_error" app:empty_layout="@layout/layout_empty" app:loading_layout="@layout/layout_loading">
复制代码
page.apply {
loadingLayout = R.layout.layout_loading
emptyLayout = R.layout.layout_empty
errorLayout = R.layout.layout_error
stateEnabled = true
}
复制代码
两个方式能够看到都须要执行stateEnabled = true
这个函数, 不然无效. 若是不设置单例就会显示默认的全局缺省页
想要使用缺省页又要求缺省页不遮盖头布局, 请使用CoordinatorLayout
. 使用NestedScrollView
会致使rv没法复用item.
前面提到 PageRefreshLayout 支持自动分页加载
// 设置分页加载第一页的索引, 默认=1, 触发刷新会重置索引.
PageRefreshLayout.startIndex = 0
page.onRefresh {
// 这是网络请求
post("/path") {
addParames("key", "value")
}.net(activity) {
// 该回调函数参数返回一个布尔类型用于判断是否存在下一页, 决定上拉加载的状态.
addData(data, { adapter.count < data.page })
}
}
复制代码
若是感受网络请求的代码很优雅, 能够关注个人Github网络请求库.