Android横向ListView

在项目开发中,竖向的listview我们经常用到,但是在特殊情况下,我们需要使用横向的listview,所以一下就是一个

自定义的横向listview,希望对有需要的人有帮助。

 

自定义的横向listview

  1 package com.qdsj.jhongbao.view;
  2 
  3 import java.util.LinkedList;
  4 import java.util.Queue;
  5 
  6 import android.content.Context;
  7 import android.database.DataSetObserver;
  8 import android.graphics.Rect;
  9 import android.util.AttributeSet;
 10 import android.view.GestureDetector;
 11 import android.view.GestureDetector.OnGestureListener;
 12 import android.view.MotionEvent;
 13 import android.view.View;
 14 import android.widget.AdapterView;
 15 import android.widget.ListAdapter;
 16 import android.widget.Scroller;
 17 //com.xiaojian.frame.widgets.HorizontalListView
 18 public class HorizontalListView extends AdapterView<ListAdapter> {
 19      
 20     public boolean mAlwaysOverrideTouch = true;
 21     protected ListAdapter mAdapter;
 22     private int mLeftViewIndex = -1;
 23     private int mRightViewIndex = 0;
 24     protected int mCurrentX;
 25     protected int mNextX;
 26     private int mMaxX = Integer.MAX_VALUE;
 27     private int mDisplayOffset = 0;
 28     protected Scroller mScroller;
 29     private GestureDetector mGesture;
 30     private Queue<View> mRemovedViewQueue = new LinkedList<View>();
 31     private OnItemSelectedListener mOnItemSelected;
 32     private OnItemClickListener mOnItemClicked;
 33     private OnItemLongClickListener mOnItemLongClicked;
 34     private boolean mDataChanged = false;
 35      
 36 
 37     public HorizontalListView(Context context, AttributeSet attrs) {
 38             super(context, attrs);
 39             initView();
 40     }
 41      
 42     private synchronized void initView() {
 43             mLeftViewIndex = -1;
 44             mRightViewIndex = 0;
 45             mDisplayOffset = 0;
 46             mCurrentX = 0;
 47             mNextX = 0;
 48             mMaxX = Integer.MAX_VALUE;
 49             mScroller = new Scroller(getContext());
 50             mGesture = new GestureDetector(getContext(), mOnGesture);
 51     }
 52      
 53     @Override
 54     public void setOnItemSelectedListener(AdapterView.OnItemSelectedListener listener) {
 55             mOnItemSelected = listener;
 56     }
 57      
 58     @Override
 59     public void setOnItemClickListener(AdapterView.OnItemClickListener listener){
 60             mOnItemClicked = listener;
 61     }
 62      
 63     @Override
 64     public void setOnItemLongClickListener(AdapterView.OnItemLongClickListener listener) {
 65             mOnItemLongClicked = listener;
 66     }
 67 
 68     private DataSetObserver mDataObserver = new DataSetObserver() {
 69             @Override
 70             public void onChanged() {
 71                     synchronized(HorizontalListView.this){
 72                             mDataChanged = true;
 73                     }
 74                     invalidate();
 75                     requestLayout();
 76             }
 77             @Override
 78             public void onInvalidated() {
 79                     reset();
 80                     invalidate();
 81                     requestLayout();
 82             }
 83     };
 84 
 85     @Override
 86     public ListAdapter getAdapter() {
 87             return mAdapter;
 88     }
 89 
 90     @Override
 91     public View getSelectedView() {
 92             //TODO: implement
 93             return null;
 94     }
 95 
 96     @Override
 97     public void setAdapter(ListAdapter adapter) {
 98             if(mAdapter != null) {
 99                     mAdapter.unregisterDataSetObserver(mDataObserver);
100             }
101             mAdapter = adapter;
102             mAdapter.registerDataSetObserver(mDataObserver);
103             reset();
104     }
105      
106     private synchronized void reset(){
107             initView();
108             removeAllViewsInLayout();
109             requestLayout();
110     }
111 
112     @Override
113     public void setSelection(int position) {
114             //TODO: implement
115         
116     }
117      
118     private void addAndMeasureChild(final View child, int viewPos) {
119             LayoutParams params = child.getLayoutParams();
120             if(params == null) {
121                     params = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
122             }
123 
124             addViewInLayout(child, viewPos, params, true);
125             child.measure(MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST),
126                             MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.AT_MOST));
127     }
128      
129     @Override
130     protected synchronized void onLayout(boolean changed, int left, int top, int right, int bottom) {
131             super.onLayout(changed, left, top, right, bottom);
132 
133             if(mAdapter == null){
134                     return;
135             }
136             if(mDataChanged){
137                     int oldCurrentX = mCurrentX;
138                     initView();
139                     removeAllViewsInLayout();
140                     mNextX = oldCurrentX;
141                     mDataChanged = false;
142             }
143             if(mScroller.computeScrollOffset()){
144                     int scrollx = mScroller.getCurrX();
145                     mNextX = scrollx;
146             }
147             if(mNextX <= 0){
148                     mNextX = 0;
149                     mScroller.forceFinished(true);
150             }
151             if(mNextX >= mMaxX) {
152                     mNextX = mMaxX;
153                     mScroller.forceFinished(true);
154             }
155             int dx = mCurrentX - mNextX;
156             removeNonVisibleItems(dx);
157             fillList(dx);
158             positionItems(dx);
159             mCurrentX = mNextX;
160             if(!mScroller.isFinished()){
161                     post(new Runnable(){
162                             @Override
163                             public void run() {
164                                     requestLayout();
165                             }
166                     });
167             }
168     }
169      
170     private void fillList(final int dx) {
171             int edge = 0;
172             View child = getChildAt(getChildCount()-1);
173             if(child != null) {
174                     edge = child.getRight();
175             }
176             fillListRight(edge, dx);
177              
178             edge = 0;
179             child = getChildAt(0);
180             if(child != null) {
181                     edge = child.getLeft();
182             }
183             fillListLeft(edge, dx);
184              
185              
186     }
187      
188     private void fillListRight(int rightEdge, final int dx) {
189             while(rightEdge + dx < getWidth() && mRightViewIndex < mAdapter.getCount()) {
190                      
191                     View child = mAdapter.getView(mRightViewIndex, mRemovedViewQueue.poll(), this);
192                     addAndMeasureChild(child, -1);
193                     rightEdge += child.getMeasuredWidth();
194                      
195                     if(mRightViewIndex == mAdapter.getCount()-1) {
196                             mMaxX = mCurrentX + rightEdge - getWidth();
197                     }
198                      
199                     if (mMaxX < 0) {
200                             mMaxX = 0;
201                     }
202                     mRightViewIndex++;
203             }
204              
205     }
206      
207     private void fillListLeft(int leftEdge, final int dx) {
208             while(leftEdge + dx > 0 && mLeftViewIndex >= 0) {
209                     View child = mAdapter.getView(mLeftViewIndex, mRemovedViewQueue.poll(), this);
210                     addAndMeasureChild(child, 0);
211                     leftEdge -= child.getMeasuredWidth();
212                     mLeftViewIndex--;
213                     mDisplayOffset -= child.getMeasuredWidth();
214             }
215     }
216      
217     private void removeNonVisibleItems(final int dx) {
218             View child = getChildAt(0);
219             while(child != null && child.getRight() + dx <= 0) {
220                     mDisplayOffset += child.getMeasuredWidth();
221                     mRemovedViewQueue.offer(child);
222                     removeViewInLayout(child);
223                     mLeftViewIndex++;
224                     child = getChildAt(0);
225                      
226             }
227              
228             child = getChildAt(getChildCount()-1);
229             while(child != null && child.getLeft() + dx >= getWidth()) {
230                     mRemovedViewQueue.offer(child);
231                     removeViewInLayout(child);
232                     mRightViewIndex--;
233                     child = getChildAt(getChildCount()-1);
234             }
235     }
236      
237     private void positionItems(final int dx) {
238             if(getChildCount() > 0){
239                     mDisplayOffset += dx;
240                     int left = mDisplayOffset;
241                     for(int i=0;i<getChildCount();i++){
242                             View child = getChildAt(i);
243                             int childWidth = child.getMeasuredWidth();
244                             child.layout(left, 0, left + childWidth, child.getMeasuredHeight());
245                             left += childWidth + child.getPaddingRight();
246                     }
247             }
248     }
249      
250     public synchronized void scrollTo(int x) {
251             mScroller.startScroll(mNextX, 0, x - mNextX, 0);
252             requestLayout();
253     }
254      
255     @Override
256     public boolean dispatchTouchEvent(MotionEvent ev) {
257             boolean handled = super.dispatchTouchEvent(ev);
258             handled |= mGesture.onTouchEvent(ev);
259             return handled;
260     }
261      
262     protected boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
263                             float velocityY) {
264             synchronized(HorizontalListView.this){
265                     mScroller.fling(mNextX, 0, (int)-velocityX, 0, 0, mMaxX, 0, 0);
266             }
267             requestLayout();
268              
269             return true;
270     }
271      
272     protected boolean onDown(MotionEvent e) {
273             mScroller.forceFinished(true);
274             return true;
275     }
276      
277     private OnGestureListener mOnGesture = new GestureDetector.SimpleOnGestureListener() {
278 
279             @Override
280             public boolean onDown(MotionEvent e) {
281                     return HorizontalListView.this.onDown(e);
282             }
283 
284             @Override
285             public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
286                             float velocityY) {
287                     return HorizontalListView.this.onFling(e1, e2, velocityX, velocityY);
288             }
289 
290             @Override
291             public boolean onScroll(MotionEvent e1, MotionEvent e2,
292                             float distanceX, float distanceY) {
293                      
294                     synchronized(HorizontalListView.this){
295                             mNextX += (int)distanceX;
296                     }
297                     requestLayout();
298                      
299                     return true;
300             }
301 
302             @Override
303             public boolean onSingleTapConfirmed(MotionEvent e) {
304                     for(int i=0;i<getChildCount();i++){
305                             View child = getChildAt(i);
306                             if (isEventWithinView(e, child)) {
307                                     if(mOnItemClicked != null){
308                                             mOnItemClicked.onItemClick(HorizontalListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId( mLeftViewIndex + 1 + i ));
309                                     }
310                                     if(mOnItemSelected != null){
311                                             mOnItemSelected.onItemSelected(HorizontalListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId( mLeftViewIndex + 1 + i ));
312                                     }
313                                     break;
314                             }
315                              
316                     }
317                     return true;
318             }
319              
320             @Override
321             public void onLongPress(MotionEvent e) {
322                     int childCount = getChildCount();
323                     for (int i = 0; i < childCount; i++) {
324                             View child = getChildAt(i);
325                             if (isEventWithinView(e, child)) {
326                                     if (mOnItemLongClicked != null) {
327                                             mOnItemLongClicked.onItemLongClick(HorizontalListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId(mLeftViewIndex + 1 + i));
328                                     }
329                                     break;
330                             }
331 
332                     }
333             }
334 
335        private boolean isEventWithinView(MotionEvent e, View child) {
336         Rect viewRect = new Rect();
337         int[] childPosition = new int[2];
338         child.getLocationOnScreen(childPosition);
339         int left = childPosition[0];
340         int right = left + child.getWidth();
341         int top = childPosition[1];
342         int bottom = top + child.getHeight();
343         viewRect.set(left, top, right, bottom);
344         return viewRect.contains((int) e.getRawX(), (int) e.getRawY());
345     }
346     };
347 
348      
349 
350 }

 

在布局文件中应用该自定义的横向listview,然后和listview一样设置Adapter,这样就生成了一个横向的listview。

 

posted @ 2014-12-02 11:09  Android、Boy  阅读(2037)  评论(0编辑  收藏  举报