轮子精神 : RefreshListView

轮子精神 : RefreshListView


    新的LAC设想中需要一个类似IOS中的'Pull to Refresh ListView'功能,即是当ListView显示到最后一列时,向上拖动ListView将开始加载后续数据列,如下图所示:

   

    一直以为Android应该自带了这个view,但翻了一下,竟然没有,至少API8中没有...赶紧google下,嗯,很多前人都做过了,很好,不过...LAC中只需要最下面的pull刷新功能,上面那个还真不需要,但所有的例子中要不是上下都有,要不只有上面,这..这不满足我的需求啊...(好吧,是我毛病太多..) 
    于是,发扬" 轮子精神"--咱自己做个不行吗...于是就有了下面的代码.

RefreshListView
  1 package jie.java.android.view.refreshlistview;
  2 
  3 import android.content.Context;
  4 import android.util.AttributeSet;
  5 import android.util.Log;
  6 import android.view.Gravity;
  7 import android.view.MotionEvent;
  8 import android.view.View;
  9 import android.view.ViewGroup;
 10 import android.widget.AbsListView;
 11 import android.widget.LinearLayout;
 12 import android.widget.AbsListView.OnScrollListener;
 13 import android.widget.ListView;
 14 import android.widget.ProgressBar;
 15 import android.widget.TextView;
 16 
 17 public class RefreshListView extends ListView implements OnScrollListener {
 18 
 19     private class FooterView extends LinearLayout {
 20         private TextView title = null;
 21         private ProgressBar progress = null;
 22         
 23         public FooterView(Context context) {
 24             super(context);
 25             
 26             initViews();
 27         }
 28         
 29         public FooterView(Context context, AttributeSet attrs) {
 30             super(context, attrs);
 31             
 32             initViews();
 33         }
 34         
 35         private void initViews() {
 36 /*            
 37             LinearLayout layout = new LinearLayout(this.getContext());
 38             layout.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.MATCH_PARENT));
 39             layout.setGravity(Gravity.CENTER_HORIZONTAL);
 40             
 41             layout.setOrientation(HORIZONTAL);
 42 */            
 43             //this.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL));
 44             progress = new ProgressBar(this.getContext());
 45             progress.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
 46             progress.setPadding(80, 10, 20, 10);
 47             title = new TextView(this.getContext());
 48             title.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));// CONTENT));
 49             title.setGravity(Gravity.CENTER_VERTICAL);
 50             //title.setText("test");
 51 //            progress.setMinimumHeight(40);
 52             
 53             this.addView(progress);
 54             this.addView(title);
 55             
 56 //            this.addView(layout);
 57         }
 58         
 59         public void setVisible(boolean isVisible) {
 60             progress.setVisibility(isVisible ? View.VISIBLE : View.GONE);
 61             title.setVisibility(isVisible ? View.VISIBLE : View.GONE);
 62             //this.setVisibility(isVisible ? View.VISIBLE : View.GONE);
 63         }
 64             
 65         public void setText(String text) {
 66             title.setText(text);
 67         }
 68     }
 69     
 70     public interface OnRefreshListener {
 71         public void onRefresh(int firstVisibleItem, int visibleItemCount, int totalItemCount);
 72 
 73         public void onBeginRefresh();
 74 
 75         public void onEndRefresh();
 76 
 77         public void onStopRefresh();
 78     }    
 79     
 80     private FooterView footer = null;
 81     
 82     private boolean isBottom = false;
 83     private int footerHeight = 0;    
 84     private int mLastMotionY = -1;
 85 
 86     private int firstVisibleItem = -1;
 87     private int visibleItemCount = -1;
 88     private int totalItemCount = -1;
 89     private boolean hasNotify = false;    
 90     
 91     private OnRefreshListener refreshListener = null;
 92     
 93     
 94     public RefreshListView(Context context) {
 95         super(context);
 96         
 97         initFooter();
 98     }
 99     
100     public RefreshListView(Context context, AttributeSet attrs) {
101         super(context, attrs);
102         initFooter();
103     }
104 
105     public RefreshListView(Context context, AttributeSet attrs, int defStyle) {
106         super(context, attrs, defStyle);
107         initFooter();
108     }
109 
110     private void initFooter() {
111         footer = new FooterView(this.getContext());
112         
113         footer.setVisible(false);
114         this.addFooterView(footer);
115         
116         measureView(footer);
117         
118         footerHeight = footer.getMeasuredHeight();
119         
120         this.setOnScrollListener(this);
121     }
122     
123     private void measureView(View child) {
124         ViewGroup.LayoutParams p = child.getLayoutParams();
125         if (p == null) {
126             p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
127         }
128 
129         int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);
130         int lpHeight = p.height;
131         int childHeightSpec;
132         if (lpHeight > 0) {
133             childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
134         } else {
135             childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
136         }
137         child.measure(childWidthSpec, childHeightSpec);
138     }    
139     
140     public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
141     
142         if(totalItemCount > 0 && (totalItemCount > visibleItemCount) && ((firstVisibleItem + visibleItemCount) == totalItemCount)) {
143             isBottom = true;
144             
145             this.firstVisibleItem = firstVisibleItem;
146             this.visibleItemCount = visibleItemCount;
147             this.totalItemCount = totalItemCount;        
148         }
149         else {
150             isBottom = false;
151         }    
152     }
153 
154     public void onScrollStateChanged(AbsListView view, int scrollState) {
155     }
156 
157     @Override
158     public boolean onTouchEvent(MotionEvent ev) {        
159         if(isBottom) {
160             
161             if(mLastMotionY == -1) {
162                 mLastMotionY = (int) ev.getRawY();
163             }            
164             
165             if(ev.getAction() == MotionEvent.ACTION_MOVE) {
166 
167                 footer.setVisible(isBottom);
168                 int pad = (int) (((mLastMotionY - ev.getRawY()) - footerHeight ) / 1.75);
169                 footer.setPadding(0, 0, 0, pad);
170                 
171                 if(!hasNotify && refreshListener != null) {
172                     refreshListener.onBeginRefresh();
173                     hasNotify = true;
174                 }                
175             }
176             else if(ev.getAction() == MotionEvent.ACTION_DOWN) {
177                 mLastMotionY = (int) ev.getRawY();// ev.getY();
178             }
179             else if(ev.getAction() == MotionEvent.ACTION_UP) {
180                 
181                 if(refreshListener != null) {
182                     refreshListener.onRefresh(this.firstVisibleItem, this.visibleItemCount, this.totalItemCount);
183                 }
184                 
185                 footer.setPadding(0, 0, 0, 0);
186                 footer.setVisible(false);
187                 
188                 if(refreshListener != null) {
189                     refreshListener.onEndRefresh();
190                 }        
191                 hasNotify = false;
192             }
193         }
194         else {
195             if(ev.getAction() == MotionEvent.ACTION_UP) {
196                 if(refreshListener != null) {
197                     refreshListener.onStopRefresh();
198                 }
199                 hasNotify = false;
200             }
201         }
202         
203         return super.onTouchEvent(ev);
204     }
205 
206     public void setOnRefreshListener(OnRefreshListener listener) {
207         refreshListener = listener;
208     }
209     
210     public void setText(String text) {
211         footer.setText(text);
212     }
213 }
214 

    下面是测试代码.
MainActivity
 1 package jie.java.android.test_listview;
 2 
 3 import java.util.ArrayList;
 4 
 5 import jie.java.android.view.refreshlistview.RefreshListView;
 6 import android.os.Bundle;
 7 import android.app.Activity;
 8 import android.util.Log;
 9 import android.view.Menu;
10 import android.widget.ArrayAdapter;
11 
12 public class MainActivity extends Activity {
13 
14     private RefreshListView listView = null;
15     
16     
17     private ArrayList<String> astring = new ArrayList<String>();
18     private int count = 9;//2;
19     
20     @Override
21     public void onCreate(Bundle savedInstanceState) {
22         super.onCreate(savedInstanceState);
23         setContentView(R.layout.activity_main);
24         
25         listView = (RefreshListView) this.findViewById(R.id.refreshListView1);
26         listView.setOnRefreshListener(new RefreshListView.OnRefreshListener() {
27             
28             public void onRefresh(int firstVisibleItem, int visibleItemCount, int totalItemCount) {
29                 onListViewRefresh(firstVisibleItem, visibleItemCount, totalItemCount);
30             }
31 
32             public void onBeginRefresh() {
33                 Log.d("this", "onBeginRefresh()");
34                 onListViewBeginRefresh();
35             }
36 
37             public void onEndRefresh() {
38                 Log.d("this", "onEndRefresh()");
39             }
40 
41             public void onStopRefresh() {
42                 Log.d("this", "onStopRefresh()");                
43             }
44         });        
45         
46         initListViewData();
47     }
48     
49     protected void onListViewBeginRefresh() {
50         listView.setText("Release to refresh!");
51     }
52     
53     protected void onListViewRefresh(int firstVisibleItem, int visibleItemCount, int totalItemCount) {
54         
55 //        for(Integer i = totalItemCount - 1; i < totalItemCount + visibleItemCount; ++ i) {
56 //            astring.add(Integer.toString(++ count));
57 //        }       
58         astring.add(Integer.toString(++ count));
59         listView.setSelection(firstVisibleItem + visibleItemCount - 1);
60     }
61 
62     private void initListViewData() {
63         
64         for(Integer i = 0; i < count; ++ i) {
65             astring.add(i.toString());
66         }
67         
68         ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1, astring);
69         listView.setAdapter(adapter);
70     }
71 
72     @Override
73     public boolean onCreateOptionsMenu(Menu menu) {
74         getMenuInflater().inflate(R.menu.activity_main, menu);
75         return true;
76     }
77 }
78 

    不知为何代码比google来的都短了许多,估计是我考虑的不全面吧,但基本满足俺的需求了...最好的一点,咱的不用额外的layout文件,就两个子控件,直接就内置了...



你可能感兴趣的:(轮子精神 : RefreshListView)