Android实现ListView的下拉刷新、上拉加载更多
2016-12-24 14:57
459 查看
Android实现ListView的下拉刷新、上拉加载更多
在Andoird编程中经常使用的控件包括ListView,就个人而言,我还是很喜欢ListView的,在使用ListView的过程中,必不可少的就是下拉刷新、上拉加载更多。下面是我自己写出一个小Demo便于大家理解。希望大家可以理解。共同进步!自己bb那么多,希望大家见谅,我直接上图说话
第一步:先定义一个自定义控件SlipListView继承与ListView,在SlipListView中增加ListView的头布局与脚布局并实现其滑动监听的功能(代码虽然多,但是原理很简单,聪明的你们肯定可以看明白的。)
public class SlipListView extends ListView implements OnScrollListener { private Context mContext; private int startY; private int moveY; private int mHeaderViewHeight; private View mHeaderview; /** * 下拉刷新 */ private static final int downRefresh = 0; /** * 正在刷新 */ private static final int refreshing = 1; /** * 释放刷新 */ private static final int upRefresh = 2; private int currentState = downRefresh; private RotateAnimation mUpAnimation; private RotateAnimation mDownAnimation; private TextView tvTiTile; private ProgressBar pbUp; private ImageView ivRefresh; private RefreshListener mListener; private View mFootView; // 脚布局 private boolean isLoadingMore; // 是否正在加载更多 private int mFootViewHeight; public SlipListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } public SlipListView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public SlipListView(Context context) { super(context); init(); } /** * 初始化界面,及动画 */ private void init() { mContext = getContext(); setOnScrollListener(this); // 初始化头布局 initHeaderView(); // 初始化脚布局 initFootView(); initAnimation(); } /** * 初始化脚布局 */ private void initFootView() { mFootView = View.inflate(mContext, R.layout.layout_foot, null); mFootView.measure(0, 0); mFootViewHeight = mFootView.getMeasuredHeight(); addFooterView(mFootView); } /** * 初始化动画 */ private void initAnimation() { mUpAnimation = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); mUpAnimation.setDuration(300); mUpAnimation.setFillAfter(true); mDownAnimation = new RotateAnimation(-180, -360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); mDownAnimation.setDuration(300); mDownAnimation.setFillAfter(true); } /** * 初始化头布局 */ private void initHeaderView() { mHeaderview = View.inflate(mContext, R.layout.layout_header, null); ivRefresh = (ImageView) mHeaderview.findViewById(R.id.iv_refresh); pbUp = (ProgressBar) mHeaderview.findViewById(R.id.pb_up); tvTiTile = (TextView) mHeaderview.findViewById(R.id.tv_title); mHeaderview.measure(0, 0); mHeaderViewHeight = mHeaderview.getMeasuredHeight(); // 隐藏头布局 mHeaderview.setPadding(0, -mHeaderViewHeight, 0, 0); addHeaderView(mHeaderview); } // 监听listview的滑动事件 @Override public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: startY = (int) ev.getY(); break; case MotionEvent.ACTION_MOVE: moveY = (int) ev.getY(); if (currentState == refreshing) { return super.onTouchEvent(ev); } int valueY = moveY - startY; if (valueY > 0 && getFirstVisiblePosition() == 0) { int result = -mHeaderViewHeight + valueY; mHeaderview.setPadding(0, result, 0, 0); // 判断状态 if (result < 0 && currentState != downRefresh) { currentState = downRefresh; updateHeader(); } else if (result >= 0 && currentState != upRefresh) { currentState = upRefresh; updateHeader(); } return true; } break; case MotionEvent.ACTION_UP: // 松开 if (currentState == downRefresh) { mHeaderview.setPadding(0, -mHeaderViewHeight, 0, 0); } else if (currentState == upRefresh) { mHeaderview.setPadding(0, 0, 0, 0); currentState = refreshing; updateHeader(); } break; default: break; } return super.onTouchEvent(ev); } /** * 更改头布局的状态 */ private void updateHeader() { switch (currentState) { case downRefresh: ivRefresh.startAnimation(mDownAnimation); tvTiTile.setText("下拉刷新"); break; case refreshing: // 正在刷新 ivRefresh.clearAnimation(); ivRefresh.setVisibility(View.INVISIBLE); pbUp.setVisibility(View.VISIBLE); tvTiTile.setText("正在刷新..."); // 利用回调增加listview中的内容 if (mListener != null) { mListener.onRefresh(); } break; case upRefresh: // 释放刷新 ivRefresh.startAnimation(mUpAnimation); tvTiTile.setText("释放刷新"); break; } } public interface RefreshListener { /** * 刷新数据 */ void onRefresh(); /** * 加载更多 */ void onLoadMore(); } /** * 刷新头布局的回调方法 */ public void setOnRefreshListener(RefreshListener mListener) { this.mListener = mListener; } /** * 刷新结束 */ public void setOnRefreshFinah() { if (isLoadingMore) { // 加载更多 mFootView.setPadding(0, -mFootViewHeight, 0, 0); isLoadingMore = false; } currentState = downRefresh; mHeaderview.setPadding(0, -mHeaderViewHeight, 0, 0); ivRefresh.setVisibility(View.VISIBLE); pbUp.setVisibility(View.INVISIBLE); tvTiTile.setText("下拉刷新"); } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { if (isLoadingMore) { return; } // 最新状态是空闲状态, 并且当前界面显示了所有数据的最后一条. 加载更多 if (scrollState == SCROLL_STATE_IDLE && getLastVisiblePosition() >= (getCount() - 1)) { isLoadingMore = true; mFootView.setPadding(0, 0, 0, 0); setSelection(getCount()); if (mListener != null) { mListener.onLoadMore(); } } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { // 滑动过程中 } }
第二步:在布局文件中使用此自定义控件(比较简单)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="${relativePackage}.${activityClass}" > <com.lx.pulllistview.ui.SlipListView android:id="@+id/slv_view" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout>
第三步:定义ListView的Item的布局(里面我将ProgressBar自定义了一个style,你们可以使用默认的)
<?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:orientation="horizontal" > <FrameLayout android:layout_width="60dp" android:layout_height="50dp" android:layout_marginBottom="5dp" android:layout_marginLeft="5dp" android:layout_marginTop="5dp" > <ProgressBar android:id="@+id/pb_up" android:layout_width="match_parent" bac2 android:layout_height="match_parent" android:layout_gravity="center" android:indeterminateDrawable="@drawable/progressbar_shape" /> </FrameLayout> <TextView android:id="@+id/tv_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:gravity="center" android:text="加载更多..." android:textColor="#ff0000" android:textSize="16dp" /> </LinearLayout>
第四步:在MainActivity中调用(不难喲,加油)
public class MainActivity extends Activity { private static final int PULL_DOWN = 0; private static final int LOAD_MORE = 1; private SlipListView slView; private Context mContext; private List<String> mTestList; private MyAdapter mAdapter; private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case PULL_DOWN: mAdapter.notifyDataSetChanged(); slView.setOnRefreshFinah(); break; case LOAD_MORE: break; } super.handleMessage(msg); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mContext = this; // 初始化UI initUI(); // 初始化数据 initData(); initEvent(); // 初始化数据适配器 initAdpater(); } /** * 初始化事件 */ private void initEvent() { slView.setOnRefreshListener(new RefreshListener() { @Override public void onRefresh() { new Thread(new Runnable() { @Override public void run() { SystemClock.sleep(2000); mTestList.add(0, "我是刷新出来的测试数据"); mHandler.sendEmptyMessage(PULL_DOWN); } }).start(); } @Override public void onLoadMore() { new Thread(new Runnable() { @Override public void run() { SystemClock.sleep(2000); mTestList.add("我是加载出来的测试数据1"); mTestList.add("我是加载出来的测试数据2"); mHandler.sendEmptyMessage(PULL_DOWN); } }).start(); } }); } /** * 初始化ListView的适配器 */ private void initAdpater() { mAdapter = new MyAdapter(); slView.setAdapter(mAdapter); } /** * 初始化listview的测试数据 */ private void initData() { mTestList = new ArrayList<String>(); for (int i = 0; i < 30; i++) { mTestList.add("我是ListView的测试数据"); } } /** * 初始化UI */ private void initUI() { slView = (SlipListView) findViewById(R.id.slv_view); } /** * 自定义适配器 */ class MyAdapter extends BaseAdapter { @Override public int getCount() { return mTestList.size(); } @Override public String getItem(int position) { return mTestList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { // 由于item的布局就一个TextView并且数量较少,因此不使用优化了 TextView textView = new TextView(mContext); textView.setText(mTestList.get(position)); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); return textView; } } }
你是不是想说终于结束了,嘿嘿!当你阅读到这里的时候,你的知识与忍耐力已经更上一层楼了。废话不多说了,如果您有疑问请咨询我,最后谢谢大家的观看,你们的支持是给我最大的努力!
相关文章推荐
- Android UI--自定义ListView(实现下拉刷新+加载更多)
- android ListView的上部下拉刷新下部点击加载更多具体实现及拓展
- android ListView的上部下拉刷新下部点击加载更多具体实现及拓展
- Android UI自定义ListView实现下拉刷新和加载更多效果
- Android实现异步从网络加载图片列表和上拉加载更多、下拉刷新列表(使用xListView框架实现)
- android ListView的上部下拉刷新下部点击加载更多具体实现及拓展
- android ListView上拉加载更多 下拉刷新功能实现(采用pull-to-refresh)
- Android中Listview下拉刷新和上拉加载更多的多种实现方案
- Android UI--自定义ListView(实现下拉刷新+加载更多)
- Android实现上拉加载更多以及下拉刷新功能(ListView)
- Android ListView下拉刷新上拉加载更多的实现
- Android UI--自定义ListView(实现下拉刷新+加载更多)
- Android UI--自定义ListView(实现下拉刷新+加载更多)
- android ListView的上部下拉刷新下部点击加载更多具体实现及拓展
- android ListView的上部下拉刷新下部点击加载更多具体实现及拓展
- android ListView的上部下拉刷新下部点击加载更多具体实现及拓展
- Android scrollview中嵌套listview实现listview的下拉刷新上拉加载更多
- android使用PullToRefresh框架实现ListView下拉刷新上拉加载更多
- Android中自定义ListView实现上拉加载更多和下拉刷新
- android ListView上拉加载更多 下拉刷新功能实现(采用pull-to-refresh)