首页 > 代码库 > ListView下拉刷新

ListView下拉刷新

自定义ListView:

技术分享
  1 package com.yuanlei.my.listviewrefresh.view;
  2 
  3 import android.content.Context;
  4 import android.util.AttributeSet;
  5 import android.util.Log;
  6 import android.view.LayoutInflater;
  7 import android.view.MotionEvent;
  8 import android.view.View;
  9 import android.view.ViewGroup;
 10 import android.view.animation.RotateAnimation;
 11 import android.widget.AbsListView;
 12 import android.widget.ImageView;
 13 import android.widget.ListView;
 14 import android.widget.ProgressBar;
 15 import android.widget.TextView;
 16 
 17 import com.yuanlei.my.listviewrefresh.R;
 18 
 19 import java.text.SimpleDateFormat;
 20 import java.util.Date;
 21 
 22 /**
 23  * Created by 袁磊 on 2016/11/4.
 24  */
 25 public class ReFreshListView extends ListView implements AbsListView.OnScrollListener {
 26     View header;//顶部布局文件
 27     int headerHeight;//顶部布局文件的高度
 28     int firstVisibleItem;//当前第一个可见的Item的位置
 29     int scrollState;//listView当前滚动状态
 30     boolean isRemark;//标记,当前是在listView最顶端摁下的
 31     int startY;//摁下时的Y值
 32 
 33     int state;//当前的状态
 34     final int NONE = 0;//正常状态
 35     final int PULL = 1;//提示下拉状态
 36     final int RELESE = 2;//提示释放状态
 37     final int REFRESHING = 3;//刷新状态
 38 
 39     private IRefreshListener iRefreshListener;//刷新数据的接口
 40 
 41     public ReFreshListView(Context context) {
 42         super(context);
 43         initView(context);
 44 
 45     }
 46 
 47     public ReFreshListView(Context context, AttributeSet attrs) {
 48         super(context, attrs);
 49         initView(context);
 50     }
 51 
 52     public ReFreshListView(Context context, AttributeSet attrs, int defStyleAttr) {
 53         super(context, attrs, defStyleAttr);
 54         initView(context);
 55     }
 56 
 57     /**
 58      * 初始化界面,添加顶部布局文件到ListView
 59      *
 60      * @param context
 61      */
 62     private void initView(Context context) {
 63         LayoutInflater inflater = LayoutInflater.from(context);
 64         header = inflater.inflate(R.layout.header_layout, null);
 65         measureView(header);
 66         headerHeight = header.getMeasuredHeight();
 67         Log.i("TAG", "headerHeight=" + headerHeight);
 68         topPadding(-headerHeight);
 69         this.addHeaderView(header);
 70         this.setOnScrollListener(this);
 71     }
 72 
 73     /**
 74      * 通知父布局,占用的宽,高
 75      *
 76      * @param view
 77      */
 78     private void measureView(View view) {
 79         ViewGroup.LayoutParams p = view.getLayoutParams();
 80         if (p == null) {
 81             p = new ViewGroup.LayoutParams(ViewGroup.
 82                     LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
 83         }
 84         int width = ViewGroup.getChildMeasureSpec(0, 0, p.width);
 85         int height;
 86         int tempHeight = p.height;
 87         if (tempHeight > 0) {
 88             height = MeasureSpec.makeMeasureSpec(tempHeight, MeasureSpec.EXACTLY);
 89         } else {
 90             height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
 91         }
 92         view.measure(width, height);
 93     }
 94 
 95     /**
 96      * 设置header布局上边距
 97      *
 98      * @param topPadding
 99      */
100     private void topPadding(int topPadding) {
101         header.setPadding(header.getPaddingLeft(), topPadding, header.getPaddingRight(), header.getPaddingBottom());
102         header.invalidate();
103     }
104 
105     @Override
106     public void onScrollStateChanged(AbsListView view, int scrollState) {
107         this.scrollState = scrollState;
108     }
109 
110     @Override
111     public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
112         this.firstVisibleItem = firstVisibleItem;
113     }
114 
115     @Override
116     public boolean onTouchEvent(MotionEvent ev) {
117         switch (ev.getAction()) {
118             case MotionEvent.ACTION_DOWN:
119                 if (firstVisibleItem == 0) {
120                     isRemark = true;
121                     startY = (int) ev.getY();
122                 }
123                 break;
124             case MotionEvent.ACTION_MOVE:
125                 onMove(ev);
126                 break;
127             case MotionEvent.ACTION_UP:
128                 if (state == RELESE) {
129                     state = REFRESHING;
130                     //加载最新数据
131                     refreshViewByState();
132                     iRefreshListener.onRefresh();
133                 } else if (state == PULL) {
134                     state = NONE;
135                     isRemark = false;
136                     refreshViewByState();
137                 }
138                 break;
139         }
140         return super.onTouchEvent(ev);
141     }
142 
143     /**
144      * 判断移动过程操作
145      *
146      * @param ev
147      */
148     private void onMove(MotionEvent ev) {
149         if (!isRemark) {
150             return;
151         }
152         int tempY = (int) ev.getY();
153         int space = tempY - startY;
154         int topPadding = space - headerHeight;
155         switch (state) {
156             case NONE:
157                 if (space > 0) {
158                     state = PULL;
159                     refreshViewByState();
160                 }
161                 break;
162             case PULL:
163                 topPadding(topPadding);
164                 if (space > headerHeight + 30 && scrollState == SCROLL_STATE_TOUCH_SCROLL) {
165                     state = RELESE;
166                     refreshViewByState();
167                 }
168                 break;
169             case RELESE:
170                 topPadding(topPadding);
171                 if (space < headerHeight + 30) {
172                     state = PULL;
173                     refreshViewByState();
174                 } else if (space <= 0) {
175                     state = NONE;
176                     isRemark = false;
177                     refreshViewByState();
178                 }
179                 break;
180         }
181     }
182 
183     /**
184      * 根据当前状态,改变界面显示
185      */
186     private void refreshViewByState() {
187         TextView tip = (TextView) header.findViewById(R.id.tv_header_hint);
188         ImageView arrow = (ImageView) header.findViewById(R.id.iv_header_arrow);
189         ProgressBar progress = (ProgressBar) findViewById(R.id.pb_header_refresh);
190         RotateAnimation anim = new RotateAnimation(0, 180,
191                 RotateAnimation.RELATIVE_TO_SELF, 0.5f,
192                 RotateAnimation.RELATIVE_TO_SELF, 0.5f);
193         anim.setDuration(500);
194         anim.setFillAfter(true);
195         RotateAnimation anim1 = new RotateAnimation(180, 0,
196                 RotateAnimation.RELATIVE_TO_SELF, 0.5f,
197                 RotateAnimation.RELATIVE_TO_SELF, 0.5f);
198         anim1.setDuration(500);
199         anim1.setFillAfter(true);
200         switch (state) {
201             case NONE:
202                 arrow.clearAnimation();
203                 topPadding(-headerHeight);
204                 break;
205             case PULL:
206                 arrow.setVisibility(View.VISIBLE);
207                 progress.setVisibility(View.GONE);
208                 tip.setText("下拉可以刷新");
209                 arrow.clearAnimation();
210                 arrow.setAnimation(anim1);
211                 break;
212             case RELESE:
213                 arrow.setVisibility(View.VISIBLE);
214                 progress.setVisibility(View.GONE);
215                 tip.setText("松开可以刷新");
216                 arrow.clearAnimation();
217                 arrow.setAnimation(anim);
218                 break;
219             case REFRESHING:
220                 topPadding(50);
221                 arrow.setVisibility(View.GONE);
222                 progress.setVisibility(View.VISIBLE);
223                 tip.setText("正在刷新");
224                 arrow.clearAnimation();
225                 break;
226         }
227     }
228 
229     /**
230      * 获取完数据后
231      */
232     public void refreshComplete() {
233         state = NONE;
234         isRemark = false;
235         refreshViewByState();
236         TextView lastUpdateTime = (TextView) header.findViewById(R.id.tv_header_time);
237         SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日hh:mm:ss");
238         Date date = new Date(System.currentTimeMillis());
239         String time = format.format(date);
240         lastUpdateTime.setText(time);
241     }
242 
243     public void setInterface(IRefreshListener iRefreshListener) {
244         this.iRefreshListener = iRefreshListener;
245     }
246 
247     /**
248      * 刷新数据的接口
249      */
250     public interface IRefreshListener {
251         void onRefresh();
252     }
253 }
ReFreshListView
技术分享
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:orientation="vertical">
 6 
 7     <RelativeLayout
 8         android:layout_width="match_parent"
 9         android:layout_height="wrap_content"
10         android:layout_marginBottom="10dp"
11         android:layout_marginTop="10dp">
12 
13         <LinearLayout
14             android:id="@+id/ll_header"
15             android:layout_width="wrap_content"
16             android:layout_height="wrap_content"
17             android:layout_centerInParent="true"
18             android:gravity="center"
19             android:orientation="vertical">
20 
21             <TextView
22                 android:id="@+id/tv_header_hint"
23                 android:layout_width="wrap_content"
24                 android:layout_height="wrap_content"
25                 android:text="下拉可以刷新" />
26 
27             <TextView
28                 android:id="@+id/tv_header_time"
29                 android:layout_width="wrap_content"
30                 android:layout_height="wrap_content"
31                 android:text="0000年00月00日" />
32         </LinearLayout>
33 
34         <ImageView
35             android:id="@+id/iv_header_arrow"
36             android:layout_width="wrap_content"
37             android:layout_height="wrap_content"
38             android:layout_centerVertical="true"
39             android:layout_marginRight="20dp"
40             android:layout_toLeftOf="@id/ll_header"
41             android:src="http://www.mamicode.com/@mipmap/pull_to_refresh_arrow" />
42 
43         <ProgressBar
44             android:id="@+id/pb_header_refresh"
45             style="?android:attr/progressBarStyleSmall"
46             android:layout_width="wrap_content"
47             android:layout_height="wrap_content"
48             android:layout_centerVertical="true"
49             android:layout_marginRight="20dp"
50             android:layout_toLeftOf="@id/ll_header"
51             android:visibility="gone" />
52     </RelativeLayout>
53 
54 
55 </LinearLayout>
header布局

使用:

MainActivity:

技术分享
 1 package com.yuanlei.my.listviewrefresh;
 2 
 3 import android.os.Bundle;
 4 import android.os.Handler;
 5 import android.support.v7.app.AppCompatActivity;
 6 
 7 import com.yuanlei.my.listviewrefresh.view.ReFreshListView;
 8 
 9 import java.util.ArrayList;
10 import java.util.List;
11 
12 public class MainActivity extends AppCompatActivity implements ReFreshListView.IRefreshListener {
13     private ReFreshListView refreshLvContent;
14     private MyAdapter adapter;
15     private List<Bean> list;
16 
17     @Override
18     protected void onCreate(Bundle savedInstanceState) {
19         super.onCreate(savedInstanceState);
20         setContentView(R.layout.activity_main);
21         refreshLvContent = (ReFreshListView) findViewById(R.id.lv_main_content);
22         setData();
23         showData(list);
24     }
25 
26     private void setData() {
27         list = new ArrayList<>();
28         for (int i = 0; i < 10; i++) {
29             Bean bean = new Bean();
30             bean.setIcon(R.mipmap.ic_launcher);
31             bean.setText("默认的数据" + i + "");
32             list.add(bean);
33         }
34     }
35 
36     private void showData(List<Bean> list) {
37         if (adapter == null) {
38             refreshLvContent.setInterface(this);
39             adapter = new MyAdapter(list, this);
40             refreshLvContent.setAdapter(adapter);
41         } else {
42             adapter.onDataChange(list);
43         }
44     }
45 
46     private void setRefreshData() {
47         for (int i = 0; i < 2; i++) {
48             Bean bean = new Bean();
49             bean.setIcon(R.mipmap.ic_launcher);
50             bean.setText("刷新的数据+++++" + i + "");
51             list.add(0, bean);
52         }
53     }
54 
55     @Override
56     public void onRefresh() {
57         Handler handler = new Handler();
58         handler.postDelayed(new Runnable() {
59             @Override
60             public void run() {
61                 setRefreshData();//获取最新数据
62                 showData(list);//通知界面 显示
63                 refreshLvContent.refreshComplete();//通知ListView刷新数据完毕
64             }
65         }, 2000);
66     }
67 }
View Code
技术分享
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent">
 5 
 6     <com.yuanlei.my.listviewrefresh.view.ReFreshListView
 7         android:id="@+id/lv_main_content"
 8         android:layout_width="match_parent"
 9         android:layout_height="match_parent" />
10 </RelativeLayout>
布局

Bean:

技术分享
 1 package com.yuanlei.my.listviewrefresh;
 2 
 3 /**
 4  * Created by 袁磊 on 2016/11/4.
 5  */
 6 public class Bean {
 7     private int icon;
 8     private String text;
 9 
10     public String getText() {
11         return text;
12     }
13 
14     public void setText(String text) {
15         this.text = text;
16     }
17 
18     public int getIcon() {
19         return icon;
20     }
21 
22     public void setIcon(int icon) {
23         this.icon = icon;
24     }
25 }
View Code

MyAdapter:

技术分享
 1 package com.yuanlei.my.listviewrefresh;
 2 
 3 import android.content.Context;
 4 import android.view.LayoutInflater;
 5 import android.view.View;
 6 import android.view.ViewGroup;
 7 import android.widget.BaseAdapter;
 8 import android.widget.ImageView;
 9 import android.widget.TextView;
10 
11 import java.util.List;
12 
13 /**
14  * Created by 袁磊 on 2016/11/4.
15  */
16 public class MyAdapter extends BaseAdapter {
17     private List<Bean> list;
18     private LayoutInflater inflater;
19 
20     public MyAdapter(List<Bean> list, Context context) {
21         this.list = list;
22         inflater = LayoutInflater.from(context);
23     }
24 
25     public void onDataChange(List<Bean> list) {
26         this.list = list;
27         this.notifyDataSetChanged();
28     }
29 
30     @Override
31     public int getCount() {
32         return list == null ? 0 : list.size();
33     }
34 
35     @Override
36     public Object getItem(int position) {
37         return list.get(position);
38     }
39 
40     @Override
41     public long getItemId(int position) {
42         return position;
43     }
44 
45     @Override
46     public View getView(int position, View convertView, ViewGroup parent) {
47         Holder holder = null;
48         if (convertView == null) {
49             convertView = inflater.inflate(R.layout.item_list, null);
50             holder = new Holder();
51             holder.ivIcon = (ImageView) convertView.findViewById(R.id.iv_item_list);
52             holder.tvText = (TextView) convertView.findViewById(R.id.tv_item_list);
53             convertView.setTag(holder);
54         } else {
55             holder = (Holder) convertView.getTag();
56         }
57         holder.ivIcon.setImageResource(list.get(position).getIcon());
58         holder.tvText.setText(list.get(position).getText());
59         return convertView;
60     }
61 
62     class Holder {
63         ImageView ivIcon;
64         TextView tvText;
65     }
66 }
View Code
技术分享
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:gravity="center_vertical"
 6     android:orientation="horizontal">
 7 
 8     <ImageView
 9         android:id="@+id/iv_item_list"
10         android:layout_width="wrap_content"
11         android:layout_height="wrap_content"
12         android:src="http://www.mamicode.com/@mipmap/ic_launcher" />
13 
14     <TextView
15         android:id="@+id/tv_item_list"
16         android:layout_width="0dp"
17         android:layout_height="wrap_content"
18         android:layout_weight="1"
19         android:text="默认数据"
20         android:textSize="16sp" />
21 
22 </LinearLayout>
item布局

技术分享

ListView下拉刷新