繼承SwipeRefreshLayout實現上拉載入更多功能
阿新 • • 發佈:2019-01-08
Android 的SwipeRefreshLayout是一個比較好的下拉重新整理控制元件,現在已經有越來越多的企業開始使用這個控制元件了。但是遺憾的是這個控制元件並沒有上拉載入更多的功能,所以自己抽空,根據網上已有的例子,自己寫了一個。
首先必須要做的是建立一個類繼承SwipeRefreshLayout,這裡我把它命名為:XZHRefreshLayout
/** * TODO:Created by XuZhenhao on 2016/12/6. */ public class XZHRefreshLayout extends SwipeRefreshLayout { private boolean isLoading = false; private ListView mListView; private View mListFooter; private OnLoadListener mLoadListener; public XZHRefreshLayout(Context context) { this(context, null); } public XZHRefreshLayout(Context context, AttributeSet attrs) { super(context, attrs); //這裡初始化FooterView,並給裡面的一個菊花圖片新增一個動畫 mListFooter = LayoutInflater.from(context).inflate(R.layout.list_footer, null, false); Animation anim = AnimationUtils.loadAnimation(context, R.anim.img_animation); LinearInterpolator lin = new LinearInterpolator(); anim.setInterpolator(lin); mListFooter.findViewById(R.id.progress_iv).startAnimation(anim); } //這裡set回撥函式 public void setOnLoadListener(OnLoadListener loadListener) { this.mLoadListener = loadListener; } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); //這裡判斷ViewGroup裡面是不是有個子View,並且第一個是不是ListView int childCount = getChildCount(); if (childCount > 0) { View child = getChildAt(0); if (child instanceof ListView) { mListView = (ListView) child; } } } //用於新增和移除FooterView public void setLoad(boolean isLoad) { isLoading = isLoad; if (isLoad) { mListView.addFooterView(mListFooter); } else { mListView.removeFooterView(mListFooter); } } //記錄手指觸控式螢幕幕的上一個Y座標值 private float lastY; @Override public boolean onInterceptTouchEvent(MotionEvent ev) { int action = ev.getAction(); float currentY = ev.getY(); switch (action) { case MotionEvent.ACTION_DOWN: break; case MotionEvent.ACTION_MOVE: //如果當前的Y座標小於上一個Y座標的值說明是向上滑動,,並且子ListView不為null,並且沒有FooterView if (currentY < lastY && mListView != null && mListView.getFooterViewsCount() == 0) { //如果當前listView的最後一個item的position等於可見範圍內最後一個item的position, //並且螢幕中的item總數小於11,當前沒有載入FooterView if (mListView.getAdapter().getCount() - 1 == mListView.getLastVisiblePosition() && mListView.getChildCount() >= 11 && !isLoading) { setLoad(true);//新增FooterView mLoadListener.onLoad();//執行回撥函式 } } break; } lastY = currentY; return super.onInterceptTouchEvent(ev); } //回撥 public interface OnLoadListener { void onLoad(); } }
最核心的程式碼已經實現了,網上有很多Demo是在onScroll方法中實現的,但是我發現在滑動到底部時,onScroll方法一直在執行,那麼這樣的話會導致我們一直的執行回撥函式,因為這裡的回撥函式是用來載入資料的,從而會導致不停地獲取資料,不停的新增和移除FooterView,並且導致ListView的點選事件失效,所以我將其移到了onInterceptTouchEvent(MotionEvent ev)裡面去執行。
下面上Activity的程式碼:
public class MessageListActivity extends AppCompatActivity { private Toolbar SMSToolbar; private XZHRefreshLayout refreshLayout; private ListView lvSMSList; private MessageListAdapter adapter; private List smsList; private MRLTDao dao; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_message_list); initData(); initView(); } /** * TODO: 初始化控制元件 */ private void initView() { SMSToolbar = (Toolbar) findViewById(R.id.sms_list_toolbar); SMSToolbar.setTitle("簡訊列表"); SMSToolbar.setNavigationIcon(ContextCompat.getDrawable(this, R.mipmap.btn_back)); SMSToolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onBackPressed(); } }); //實現我們自定義的下拉重新整理控制元件 refreshLayout = (XZHRefreshLayout) findViewById(R.id.refresh_sms_ly); refreshLayout.setColorSchemeColors(ContextCompat.getColor(this, android.R.color.holo_blue_bright), ContextCompat.getColor(this, android.R.color.holo_green_light), ContextCompat.getColor(this, android.R.color.holo_orange_light), ContextCompat.getColor(this, android.R.color.holo_red_light)); //監聽下拉重新整理事件 refreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { new Handler().postDelayed(new Runnable() { @Override public void run() { smsList.clear(); smsList.addAll(dao.querySMSALL(0)); adapter.notifyDataSetChanged(); refreshLayout.setRefreshing(false); } }, 1500); } }); //我們寫的回撥函式,在裡面做查詢資料的方法 refreshLayout.setOnLoadListener(new XZHRefreshLayout.OnLoadListener() { @Override public void onLoad() { new Handler().postDelayed(new Runnable() { @Override public void run() { //我這裡是用了一個Sqlite,大家可以根據自己的實際應用在這裡做資料的查詢,相信大家一般都不可能會有問題。 if (dao != null && smsList != null) { List<SmsEntity> datas = dao.querySMSALL(smsList.size()); if (datas.size() > 0) {//如果查詢到有資料,就新增到資料來源裡面去。 smsList.addAll(datas); adapter.notifyDataSetChanged(); }else{//如果沒有資料,就彈一個吐司 MyToast.show(MessageListActivity.this,"沒有更多資料!"); } } refreshLayout.setLoad(false); } }, 1000); } }); lvSMSList = (ListView) findViewById(R.id.sms_list_lv); adapter = new MessageListAdapter(this, smsList); lvSMSList.setAdapter(adapter); lvSMSList.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { SmsEntity entity = (SmsEntity) adapter.getItem(position); showSMSDialog(entity); } }); } /** * TODO: 初始化資料 */ private void initData() { if (smsList == null) smsList = new ArrayList<>(); if (dao == null) dao = new MRLTDao(getApplicationContext()); smsList = dao.querySMSALL(0); } @Override protected void onDestroy() { super.onDestroy(); } //點選item彈一個Dialog,顯示當前Item的內容 private void showSMSDialog(SmsEntity entity) { if (entity == null) { return; } final AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(entity.getSendcode()); builder.setMessage("接收時間:"+entity.getCreate_time()+"\n"+entity.getContent()); builder.setPositiveButton("知道了", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); } }); builder.create().show(); } }
總的來說Activity裡面完全沒有啥技術含量,只是有可能程式碼寫的其醜無比。
下面上XML:
1.Activity的XML檔案
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/activity_message_list" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.yihuacomputer.sdmrlt.ui.MessageListActivity"> <android.support.v7.widget.Toolbar android:id="@+id/sms_list_toolbar" android:layout_width="match_parent" android:layout_height="50dp" android:background="@color/cpb_blue" app:titleTextColor="@color/cpb_white" /> <com.yihuacomputer.sdmrlt.ui.view.XZHRefreshLayout android:id="@+id/refresh_sms_ly" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@+id/sms_list_toolbar"> <ListView android:id="@+id/sms_list_lv" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="12dp" android:paddingRight="12dp" android:scrollbars="none"> </ListView> </com.yihuacomputer.sdmrlt.ui.view.XZHRefreshLayout> </RelativeLayout>
2.ListView的Item的XML
<?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="match_parent"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingBottom="4dp"
android:paddingTop="4dp"
android:weightSum="10">
<ImageView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:src="@mipmap/will" />
<RelativeLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="9"
android:layout_marginLeft="4dp">
<TextView
android:id="@+id/item_sms_rvd_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/colorPrimaryDark"
android:maxLength="15"
android:textSize="16sp" />
<TextView
android:id="@+id/item_sms_time_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/colorPrimaryDark"
android:textSize="16sp"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true" />
<TextView
android:id="@+id/item_sms_content_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/item_sms_rvd_tv"
android:maxLines="1"
android:textColor="@color/menu_fragment_background"
android:textSize="14sp" />
</RelativeLayout>
</LinearLayout>
3.FooterView的XML檔案
<?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="45dp"
android:gravity="center"
android:orientation="horizontal">
<ImageView
android:id="@+id/progress_iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/gpu" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="正在載入..."/>
</LinearLayout>
所有的XML檔案裡面就用到了兩個Image,大家隨便去找兩個就可以了,我是解壓了手機QQ的App後這裡面找的。
好了所有的東西基本已經實現,大家還可以在這個基礎上擴充套件一下,比如加一個動畫,讓FooterView被移除的時候好看一點,不要那麼突兀的就消失了,如果大家實現了,希望能留個言讓我學習學習!!!公司沒有錄屏工具,我就不上圖了。