SwipeRefreshlayout+RecyclerView+binding实现上拉和下拉刷新
首先要先導入SwipeRefreshlayout,SwipeRefreshLayout以前在v4包里,現在改到了androidx
1、添加SwipeRefreshLayout
? ?1、File -> Project Structure 打開Project Structure界面
? ?2、Dependencies -> app -> +
沒找到?!
我使用androidx,直接到官方文檔,里面已經有說明:
2.動手編碼開發
首先是布局:
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android"><!--<data><variable name="yaoCeAdapter" type="android.widget.BaseAdapter"/></data>--><LinearLayoutandroid:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><androidx.swiperefreshlayout.widget.SwipeRefreshLayoutandroid:id="@+id/swipeRefreshLayout"android:layout_width="match_parent"android:layout_height="wrap_content"><androidx.recyclerview.widget.RecyclerViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:id="@+id/recyclerView"/></androidx.swiperefreshlayout.widget.SwipeRefreshLayout></LinearLayout> </layout>item布局:
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"><data><variable name="itemTwo" type="com.daobo.wand.data.viewbean.ItemTwoProperty"/></data><androidx.constraintlayout.widget.ConstraintLayoutandroid:layout_width="match_parent"android:layout_height="45dp"><LinearLayoutandroid:id="@+id/num"android:layout_width="0dp"android:layout_height="wrap_content"android:orientation="vertical"app:layout_constraintHorizontal_weight="0.8"app:layout_constraintRight_toLeftOf="@+id/textOne"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintTop_toTopOf="parent"app:layout_constraintBottom_toBottomOf="parent"android:gravity="center_horizontal"android:background="@drawable/item_text_backgroud"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"android:text="@{itemTwo.indexNum}"android:textColor="@color/colorGray"android:textSize="16sp" /></LinearLayout><LinearLayoutandroid:id="@+id/textOne"android:layout_width="0dp"android:layout_height="wrap_content"android:orientation="vertical"app:layout_constraintHorizontal_weight="2"app:layout_constraintRight_toLeftOf="@+id/textTwo"app:layout_constraintLeft_toRightOf="@+id/num"app:layout_constraintTop_toTopOf="parent"app:layout_constraintBottom_toBottomOf="parent"android:gravity="center_horizontal"android:background="@drawable/item_text_backgroud"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"android:text="@{itemTwo.strPropertyOne}"android:textColor="@color/colorGray"android:textSize="16sp" /></LinearLayout><LinearLayoutandroid:id="@+id/textTwo"android:layout_width="0dp"android:layout_height="wrap_content"android:orientation="vertical"app:layout_constraintHorizontal_weight="4"app:layout_constraintLeft_toRightOf="@+id/textOne"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"app:layout_constraintBottom_toBottomOf="parent"android:gravity="center_horizontal"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"android:text="@{itemTwo.strPropertyTwo}"android:textColor="@color/colorGray"android:textSize="16sp" /></LinearLayout></androidx.constraintlayout.widget.ConstraintLayout> </layout>SwipeRefreshlayout+RecyclerView;SwipeRefreshlayout在帶有刷新接口和刷新動畫封裝,但是上拉加載更多RecyclerView沒有
接口封裝和動畫處理,因此需要自己定義一個footview:
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android"><LinearLayoutandroid:orientation="horizontal"android:layout_width="match_parent"android:layout_height="wrap_content"><ProgressBarandroid:id="@+id/pb_progress"style="?android:attr/progressBarStyle"android:layout_width="match_parent"android:layout_height="38dp"android:layout_gravity="center_horizontal"/></LinearLayout> </layout>layout相關所有的布局都有了,接著就是寫適配器,需要繼承RecyclerView.Adapter,適配器統一使用T作為入參傳入Bean,這樣增加了適配器普適性,同時我們構造中傳入 layoutid,那么你需要什么樣的item布局都可以將layout id傳入進來,對應viewdatabind 的bean id也是傳入進來的。
package com.daobo.wand.adapterimport android.content.Context import android.view.LayoutInflater import android.view.ViewGroup import androidx.databinding.DataBindingUtil import androidx.databinding.ViewDataBinding import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView.ViewHolder import com.daobo.wand.Rclass BaseRecyclerViewAdapter<T>(private val context: Context, private val listData: List<T>,private val layoutId: Int, private val variableId: Int) : RecyclerView.Adapter<ViewHolder>() {private val TYPE_CONTENT = 0//正常內容private val TYPE_FOOTER = 1//加載Viewoverride fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {//TODO("not implemented")//To change body of created functions use File | Settings | File Templates.return if (viewType==TYPE_FOOTER){FootViewHolder(DataBindingUtil.inflate(LayoutInflater.from(context), R.layout.load_more_foot, parent, false))}else{BaseViewHolder(DataBindingUtil.inflate(LayoutInflater.from(context), layoutId, parent, false))}}override fun getItemCount(): Int {//TODO("not implemented")// To change body of created functions use File | Settings | File Templates.return listData.size + 1}override fun onBindViewHolder(holder: ViewHolder, position: Int) {//TODO("not implemented")// To change body of created functions use File | Settings | File Templates.//holder instanceof BaseViewHolderif (getItemViewType(position) == TYPE_CONTENT) {var binding : ViewDataBinding = DataBindingUtil.getBinding(holder.itemView)!!binding.setVariable(variableId, listData[position])binding.executePendingBindings()}}override fun getItemViewType(position: Int): Int {if (position == listData.size){return TYPE_FOOTER //判斷滑到最底部時,返回的ViewType為TYPE_CONTENT。}return TYPE_CONTENT}open class BaseViewHolder(dataBinding: ViewDataBinding) : ViewHolder(dataBinding.root)open class FootViewHolder(dataBinding: ViewDataBinding) : ViewHolder(dataBinding.root) }由于RecyclerView沒有上拉監聽的處理,我們需要自定義一個監聽類,類繼承RecyclerView.OnScrollListener
package com.daobo.wand.childmenu.listenerimport androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView.*abstract class onLoadMoreListener : OnScrollListener() {private var countItem: Int = 0private var lastItem: Int = 0private 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) {/* 測試這三個參數的作用if (newState==SCROLL_STATE_IDLE){//log:"SCROLL_STATE_IDLE,空閑"}else if (newState==SCROLL_STATE_DRAGGING){//log:"SCROLL_STATE_DRAGGING,拖拽"}else if (newState==SCROLL_STATE_SETTLING){//log:"test","SCROLL_STATE_SETTLING,固定"}else{//log:"其它"} *///拖拽或者慣性滑動時isScolled設置為trueisScolled = newState == SCROLL_STATE_DRAGGING || newState == SCROLL_STATE_SETTLING}override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {if (recyclerView.layoutManager is LinearLayoutManager) {layoutManager = recyclerView.layoutManagercountItem = layoutManager!!.itemCountlastItem =(layoutManager as LinearLayoutManager).findLastCompletelyVisibleItemPosition()}if (isScolled && countItem != lastItem && lastItem == countItem - 1) {onLoading(countItem, lastItem)}} }然后就是我們的使用了,我是放在fragment中使用的:
package com.daobo.wand.childmenu.fragmentimport android.content.Context import android.os.Bundle import android.os.Handler import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Toast import androidx.fragment.app.Fragment import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders import androidx.recyclerview.widget.RecyclerView import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import com.daobo.wand.BR import com.daobo.wand.R import com.daobo.wand.adapter.ListAdapter import com.daobo.wand.data.YaoCeViewModel import com.daobo.wand.data.bean.YaoCe import com.daobo.wand.data.viewbean.ItemThreeProperty import com.daobo.wand.databinding.FragmentYaoCeBinding import com.daobo.wand.utils.DataBeanToViewUtil import androidx.recyclerview.widget.LinearLayoutManager import com.daobo.wand.adapter.BaseRecyclerViewAdapter import com.daobo.wand.childmenu.listener.onLoadMoreListenerclass YaoCeFragment constructor(context : Context) : Fragment() {var mContext : Context = contextprivate var mSwipeRefreshLayout : SwipeRefreshLayout? = nullprivate var mRecyclerView : RecyclerView? = nullprivate var mLinearLayoutManager: LinearLayoutManager? = nullprivate var recyclerViewAdapter : BaseRecyclerViewAdapter<ItemThreeProperty>? = nullprivate var yaoCeViewModel : YaoCeViewModel? = nulloverride fun onCreateView(inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?): View? {var fragmentYaoCeBinding : FragmentYaoCeBinding = FragmentYaoCeBinding.inflate(inflater,container, false)//bind 組件mSwipeRefreshLayout = fragmentYaoCeBinding.swipeRefreshLayoutmRecyclerView = fragmentYaoCeBinding.recyclerView//下拉刷新的圓圈是否顯示mSwipeRefreshLayout!!.isRefreshing = false//設置下拉時圓圈的顏色(可以由多種顏色拼成)mSwipeRefreshLayout!!.setColorSchemeResources(android.R.color.holo_blue_light,android.R.color.holo_red_light,android.R.color.holo_orange_light);//設置下拉時圓圈的背景顏色(這里設置成白色)mSwipeRefreshLayout!!.setProgressBackgroundColorSchemeResource(android.R.color.white)//初始化 空list datavar mListYaoCeData : List<YaoCe> = ArrayList<YaoCe>()//初始化 空的 屬性展示 listvar listViewProperty : MutableList<ItemThreeProperty> = ArrayList<ItemThreeProperty>()//添加title信息addListItemTitle(listViewProperty)recyclerViewAdapter = BaseRecyclerViewAdapter<ItemThreeProperty>(mContext, listViewProperty,R.layout.linear_text_three_item, BR.itemThree)yaoCeViewModel = ViewModelProviders.of(this)[YaoCeViewModel::class.java]//做數據綁定和監聽yaoCeViewModel!!.getYaoCe().observe(this, Observer<List<YaoCe>>{ yaoceList ->// update UI, data changeif (yaoceList != null && yaoceList.isNotEmpty()){mListYaoCeData = yaoceListvar listProperty = DataBeanToViewUtil.ListYaoCeBean2View(mListYaoCeData)listViewProperty.clear()addListItemTitle(listViewProperty)for (property in listProperty) {listViewProperty.add(property)}recyclerViewAdapter!!.notifyDataSetChanged()}})//設置adapter 變量initRecylerView()//設置監聽initRefreshListener()//返回 view rootreturn fragmentYaoCeBinding.root}fun initRecylerView () {mLinearLayoutManager = LinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, false)mRecyclerView!!.layoutManager = mLinearLayoutManagermRecyclerView!!.adapter = recyclerViewAdapter}fun initRefreshListener () {mSwipeRefreshLayout!!.setOnRefreshListener {//TODO("not implemented")// refresh DataloadRefreshData()}mRecyclerView!!.addOnScrollListener(object : onLoadMoreListener(){override fun onLoading(countItem: Int, lastItem: Int) {//TODO("not implemented")// loadMoreDataHandler().run {postDelayed(Runnable(){yaoCeViewModel!!.loadMoreData()Toast.makeText(mContext, "加載完畢", Toast.LENGTH_SHORT).show()}, 3000)}}})}fun addListItemTitle(listViewProperty : MutableList<ItemThreeProperty>) {//添加title信息var itemThreeProperty = ItemThreeProperty()itemThreeProperty.indexNum = "序號"itemThreeProperty.strPropertyOne = "數值"itemThreeProperty.strPropertyTwo = "代號描述"itemThreeProperty.strPropertyThree = "信息"listViewProperty.add(itemThreeProperty)}fun loadRefreshData () {//設置刷新結束yaoCeViewModel!!.refreshData()Handler().run {postDelayed(Runnable(){if (mSwipeRefreshLayout!!.isRefreshing) {mSwipeRefreshLayout!!.isRefreshing = falseToast.makeText(mContext, "刷新完畢", Toast.LENGTH_SHORT).show();}}, 3000)}}}yaoceModel+livedata封裝:
package com.daobo.wand.dataimport androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import com.daobo.wand.data.bean.YaoCe import kotlin.concurrent.thread/*** 遙測* @author xiaolong.li* @time 2020-02-14*/ class YaoCeViewModel : ViewModel() {var list : MutableList<YaoCe> = ArrayList<YaoCe>()//遙測信息private val listYaoCeData: MutableLiveData<List<YaoCe>> by lazy {MutableLiveData<List<YaoCe>>().also {loadData()}}/*** 獲取數據*/fun getYaoCe() : LiveData<List<YaoCe>> {return listYaoCeData}private fun loadData() {// Do an asynchronous operation to fetch data.//寫死數據thread(start = true) {for(i in 1..30){val yaoCe = YaoCe()yaoCe.strMsg = "遙測 test"yaoCe.strValue = "10"yaoCe.numDesc = "點數"list.add(yaoCe)}listYaoCeData.postValue(list)}}fun refreshData() {thread(start = true) {list.clear()val yaoCe = YaoCe()yaoCe.strMsg = "遙測 fresh add"yaoCe.strValue = "10"yaoCe.numDesc = "點數"list.add(yaoCe)for(i in 1..20){val yaoCe = YaoCe()yaoCe.strMsg = "遙測 test"yaoCe.strValue = "10"yaoCe.numDesc = "點數"list.add(yaoCe)}listYaoCeData.postValue(list)}}fun loadMoreData () {thread(start = true) {for(i in 1..5){val yaoCe = YaoCe()yaoCe.strMsg = "遙測 loadmore add"yaoCe.strValue = "10"yaoCe.numDesc = "點數"list.add(yaoCe)}listYaoCeData.postValue(list)}} }希望可以指導大家開發上下拉數據處理,很簡單,效果也很好!
?
?
總結
以上是生活随笔為你收集整理的SwipeRefreshlayout+RecyclerView+binding实现上拉和下拉刷新的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: TP-Link TL-H39RT 无线路
- 下一篇: 中班教案《神笔马良》