android UI系列专题

kotlin 整合RecyclerView 上拉刷新 下拉加载

2020-05-21  本文已影响0人  Jamesbond_5521

使用代码如下

RefreshListView(refreshLayout,recyclerView).apply {
     recyclerView.layoutManager = LinearLayoutManager(this@RecyclerViewTestActivity)
     onProcess = {
        RetrofitServiceManager.create(PosApi::class.java).getList(page,pageSize).get()
     }
     register(String::class.java,R.layout.test_item){holder, data ->
        (holder[R.id.textView] as TextView).text = data
      }
}

代码构建如下

//加载更多的滑动监听
abstract class onLoadMoreListener : RecyclerView.OnScrollListener() {
    private var countItem = 0
    private var lastItem = 0
    private var isScolled = false //是否可以滑动
    private var layoutManager: RecyclerView.LayoutManager? = null

    /**
     * 加载回调方法
     * @param countItem 总数量
     * @param lastItem  最后显示的position
     */
    protected abstract fun onLoading(countItem: Int, lastItem: Int)
    override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
        //拖拽或者惯性滑动时isScolled设置为true
        isScolled = newState == RecyclerView.SCROLL_STATE_DRAGGING || newState == RecyclerView.SCROLL_STATE_SETTLING
    }

    override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
        if (recyclerView.layoutManager is LinearLayoutManager) {
            layoutManager = recyclerView.layoutManager
            countItem = layoutManager!!.itemCount
            lastItem =  (layoutManager as LinearLayoutManager?)!!.findLastCompletelyVisibleItemPosition()
        }
        if (isScolled && countItem != lastItem && lastItem == countItem - 1) {
            onLoading(countItem, lastItem)
        }
    }
}
//每项不同类型的视图实体
data  class ItemBindView<T:Any>(val itemLayout:Int,val setItemValue: ((holder: JsonViewHolder, data: T) -> Unit)?)
//默认的下拉视图类型
class FotterItem()
//返回的数据对象
class ListData{
    var count:Int = 0
    var data:MutableList<Any> = mutableListOf()
}
//上拉,下拉初始化类
class RefreshListView(val refreshLayout: SwipeRefreshLayout,val recyclerView:RecyclerView){
    var pageSize = 20
    var page = 1
    var count = 0
    var datas:MutableList<Any> = mutableListOf()
    var onBefor:((isRefresh:Boolean)->Unit)? = null
    var onProcess:((isRefresh:Boolean)->ListData)? = null
    var onComplet:((isRefresh:Boolean)->Unit)? = null

    val context:Context = recyclerView.context
    private var registers:MutableMap<Any,Any> = mutableMapOf()
    private var types:MutableList<Any> = mutableListOf()
    private fun notifyDataSetChanged(){
        recyclerView.adapter?.notifyDataSetChanged()
    }

    init {
        //下拉刷新的圆圈是否显示
        refreshLayout.apply {
            isRefreshing = false
            setColorSchemeResources(
                android.R.color.holo_blue_light,
                android.R.color.holo_red_light,
                android.R.color.holo_orange_light
            )
            setProgressBackgroundColorSchemeResource(android.R.color.white)
            setOnRefreshListener {
                start(true)

            }
        }
        recyclerView.apply {
            addOnScrollListener(object : onLoadMoreListener() {
                override fun onLoading(countItem: Int, lastItem: Int) {
                    if (page * pageSize < count) {
                       start(false)
                    }
                }
            })
            adapter = object : RecyclerView.Adapter<JsonViewHolder>() {
                override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): JsonViewHolder {
                    val itemBindView = itemBindView(viewType)
                    val view: View =
                        LayoutInflater.from(context).inflate(itemBindView.itemLayout, parent, false)
                    return JsonViewHolder(view)
                }

                override fun getItemCount(): Int {
                    return datas.size
                }
                /**
                 * 获取itemBindView
                 */
                private fun itemBindView(viewType: Int): ItemBindView<Any> {
                    val clas = types[viewType]
                    val itemBindView = registers[clas] as ItemBindView<Any>
                    return itemBindView
                }

                override fun onBindViewHolder(holder: JsonViewHolder, position: Int) {
                    if(position == 19){
                        Log.i("xiaochangyan",position.toString())
                    }


                    val itemBindView = itemBindView(getItemViewType(position))
                    val json = datas[position]
                    if(JSON.toJSON(json) is JSONObject)
                    holder.initJsonValue(JSON.toJSON(json) as JSONObject)
                    itemBindView.setItemValue?.invoke(holder, json)
                }

                override fun getItemViewType(position: Int): Int {
                    val data = datas[position]
                    val clas = data::class.java
                    return types.indexOf(clas)
                }
            }
        }
        register(FotterItem::class.java,R.layout.foot_layout,null)
    }
    private fun start(isRefresh: Boolean){
        onBefor?.invoke(isRefresh)
        //更正页脚
        if(isRefresh){
            page = 1
        }else{
            page+=1
        }
        GlobalScope.launch(Dispatchers.IO){
            var list:ListData? = null
            try {
                list = onProcess?.invoke(isRefresh)
            }catch (e:java.lang.Exception){
                e.printStackTrace()
            }
            withContext(Dispatchers.Main){
                refreshLayout.isRefreshing = false
                list?.let {
                    count = it.count//设置记录条数
                    if(isRefresh){
                        datas.clear()
                    }else{
                        if(datas.last() is FotterItem){
                            datas.removeAt(datas.lastIndex)
                        }
                    }
                    datas.addAll(it.data)
                    if (page * pageSize < count) {
                        datas.add(FotterItem())
                    }
                    notifyDataSetChanged()
                }
                onComplet?.invoke(isRefresh)
            }
        }
    }
    fun <T:Any> register(clas:Class<T>,itemLayout:Int,setItemValue: ((holder: JsonViewHolder, data: T) -> Unit)?){
        registers[clas] = ItemBindView(itemLayout,setItemValue)
        types.add(clas)
    }
}
/**
 * 统一一个以json为实体的ViewHolder
 */
class JsonViewHolder(view: View) : RecyclerView.ViewHolder(view) {

    val map = mutableMapOf<String, View?>()
    operator fun get(id:Int): View?{
        if(map.containsKey(id.toString())){
            return map[id.toString()]
        }
        val view = itemView.findViewById<View?>(id)
        map[id.toString()] = view
        return view
    }
    operator fun get(tag:String): View?{
        if(map.containsKey(tag)){
            return map[tag]
        }
        val view = itemView.findViewWithTag<View?>(tag) ?: return null
        map[tag] = view
        return view
    }

    operator fun set(tag:String,value:String){
        val view: View = this[tag] ?: return
        when{
            view is TextView -> view.text = value
            view is EditText -> view.setText(value)
        }
    }
    fun initJsonValue(jsonObject: JSONObject){
        for (key in jsonObject.keys){
            if(this[key] ==null)continue
            this[key] = when{jsonObject[key]==null->"" else ->jsonObject[key].toString()}
        }
    }
}
/**
 * 简单的适配器扩展
 */
fun RecyclerView.initAdapter(list: JSONArray, layout:Int, setItemValue: ((holder: JsonViewHolder, data: JSONObject) -> Unit)?){
    this.adapter = object :RecyclerView.Adapter<JsonViewHolder>(){
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): JsonViewHolder {
            val view: View = LayoutInflater.from(this@initAdapter.context).inflate(layout, parent, false)
            return JsonViewHolder(view)
        }
        override fun getItemCount(): Int {
            return list.size
        }
        override fun onBindViewHolder(holder: JsonViewHolder, position: Int) {
            val json = list.getJSONObject(position)
            holder.initJsonValue(json)
            setItemValue?.invoke(holder,json)
        }
    }
}

/**
 * 简单的适配器扩展
 */
fun <T> RecyclerView.initAdapter(list: MutableList<T>, layout:Int, setItemValue: ((holder: JsonViewHolder, data: T) -> Unit)?){
    this.adapter = object :RecyclerView.Adapter<JsonViewHolder>(){
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): JsonViewHolder {
            val view: View = LayoutInflater.from(this@initAdapter.context).inflate(layout, parent, false)
            return JsonViewHolder(view)
        }
        override fun getItemCount(): Int {
            return list.size
        }
        override fun onBindViewHolder(holder: JsonViewHolder, position: Int) {
            val json = list.get(position)
            holder.initJsonValue(JSON.toJSON(json) as JSONObject)
            setItemValue?.invoke(holder,json)
        }
    }
}
fun RecyclerView.notifyDataSetChanged(){
    this.adapter?.notifyDataSetChanged()
}

其他资源

//api
@GET("WGHQ.PayTest/CYPosApi/getList")
fun getList(@Query("page")page:Int,@Query("pageSize")pageSize:Int):Deferred<ListData>
//itemLayout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:gravity="center"
        android:layout_height="50dp"/>
    <View style="@style/MMViewLine"/>
</LinearLayout>
上一篇下一篇

猜你喜欢

热点阅读