自定义Listview实现横向的HorizontalListView

jopen 11年前

先看一下效果图

自定义Listview实现横向的HorizontalListView

介可不是什么ScrollView哦,android系统自带的ListView都是竖着的,这个是横着的,自定义的ListView,不说了上代码

package com.zhangyu.activity;   import java.util.LinkedList;   import java.util.Queue;   import android.content.Context;   import android.database.DataSetObserver;   import android.graphics.Rect;   import android.util.AttributeSet;  import android.util.Log;   import android.view.GestureDetector;   import android.view.GestureDetector.OnGestureListener;   import android.view.MotionEvent;   import android.view.View;   import android.widget.AdapterView;   import android.widget.ListAdapter;  import android.widget.Scroller;   public class HorizontialListView extends AdapterView {    public boolean mAlwaysOverrideTouch = true;    protected ListAdapter mAdapter;     private int mLeftViewIndex = -1;     private int mRightViewIndex = 0;     protected int mCurrentX;     protected int mNextX;     private int mMaxX = Integer.MAX_VALUE;     private int mDisplayOffset = 0;     protected Scroller mScroller;     private GestureDetector mGesture;     private Queue mRemovedViewQueue = new LinkedList();    private OnItemSelectedListener mOnItemSelected;     private OnItemClickListener mOnItemClicked;     private OnItemLongClickListener mOnItemLongClicked;     private boolean mDataChanged = false;     public HorizontialListView(Context context, AttributeSet attrs) {     super(context, attrs);       initView();          }    private synchronized void initView() {      mLeftViewIndex = -1;     mRightViewIndex = 0;     mDisplayOffset = 0;     mCurrentX = 0;      mNextX = 0;      mMaxX = Integer.MAX_VALUE;     mScroller = new Scroller(getContext());     mGesture = new GestureDetector(getContext(), mOnGesture);         }    @Override    public void setOnItemSelectedListener(AdapterView.OnItemSelectedListener listener) {     mOnItemSelected = listener;          }     @Override     public void setOnItemClickListener(AdapterView.OnItemClickListener listener){     mOnItemClicked = listener;          }     @Override     public void setOnItemLongClickListener(AdapterView.OnItemLongClickListener listener) {     mOnItemLongClicked = listener;          }     private DataSetObserver mDataObserver = new DataSetObserver() {     @Override      public void onChanged() {      synchronized(HorizontialListView.this){       mDataChanged = true;              }       invalidate();      requestLayout();            }       @Override     public void onInvalidated() {      reset();       invalidate();      requestLayout();           }          };     @Override     public ListAdapter getAdapter() {     return mAdapter;          }     @Override    public View getSelectedView() {     //TODO: implement           return null;          }     @Override     public void setAdapter(ListAdapter adapter) {     if(mAdapter != null) {      mAdapter.unregisterDataSetObserver(mDataObserver);           }      mAdapter = adapter;     mAdapter.registerDataSetObserver(mDataObserver);     reset();         }    private synchronized void reset(){     initView();     removeAllViewsInLayout();        requestLayout();          }    @Override    public void setSelection(int position) {     //TODO: implement    }   private void addAndMeasureChild(final View child, int viewPos) {      LayoutParams params = child.getLayoutParams();      if(params == null) {       params = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);       }      addViewInLayout(child, viewPos, params, true);       child.measure(MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST),        MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.AT_MOST));            }     @Override      protected synchronized void onLayout(boolean changed, int left, int top, int right, int bottom) {      super.onLayout(changed, left, top, right, bottom);      if(mAdapter == null){       return;              }       if(mDataChanged){       int oldCurrentX = mCurrentX;       initView();       removeAllViewsInLayout();       mNextX = oldCurrentX;       mDataChanged = false;             }       if(mScroller.computeScrollOffset()){       int scrollx = mScroller.getCurrX();       mNextX = scrollx;             }        if(mNextX <= 0){       mNextX = 0;       mScroller.forceFinished(true);             }       if(mNextX >= mMaxX) {       mNextX = mMaxX;       mScroller.forceFinished(true);             }       int dx = mCurrentX - mNextX;      removeNonVisibleItems(dx);      fillList(dx);      positionItems(dx);      mCurrentX = mNextX;      if(!mScroller.isFinished()){       post(new Runnable(){        @Override        public void run() {         requestLayout();                 }                  });       }      }      private void fillList(final int dx) {      int edge = 0;      View child = getChildAt(getChildCount()-1);      if(child != null) {       edge = child.getRight();             }        fillListRight(edge, dx);      edge = 0;      child = getChildAt(0);      if(child != null) {       edge = child.getLeft();             }       fillListLeft(edge, dx);            }      private void fillListRight(int rightEdge, final int dx) {      while(rightEdge + dx < getWidth() && mRightViewIndex < mAdapter.getCount()) {       View child = mAdapter.getView(mRightViewIndex, mRemovedViewQueue.poll(), this);       addAndMeasureChild(child, -1);       rightEdge += child.getMeasuredWidth();       if(mRightViewIndex == mAdapter.getCount()-1) {        mMaxX = mCurrentX + rightEdge - getWidth();               }        if (mMaxX < 0) {        mMaxX = 0;               }        mRightViewIndex++;             }            }      private void fillListLeft(int leftEdge, final int dx) {      while(leftEdge + dx > 0 && mLeftViewIndex >= 0) {       View child = mAdapter.getView(mLeftViewIndex, mRemovedViewQueue.poll(), this);        addAndMeasureChild(child, 0);       leftEdge -= child.getMeasuredWidth();        mLeftViewIndex--;         mDisplayOffset -= child.getMeasuredWidth();             }            }           private void removeNonVisibleItems(final int dx) {       View child = getChildAt(0);      while(child != null && child.getRight() + dx <= 0) {       mDisplayOffset += child.getMeasuredWidth();       mRemovedViewQueue.offer(child);       removeViewInLayout(child);       mLeftViewIndex++;       child = getChildAt(0);              }        child = getChildAt(getChildCount()-1);       while(child != null && child.getLeft() + dx >= getWidth()) {       mRemovedViewQueue.offer(child);       removeViewInLayout(child);       mRightViewIndex--;        child = getChildAt(getChildCount()-1);             }            }     private void positionItems(final int dx) {      if(getChildCount() > 0){        mDisplayOffset += dx;        int left = mDisplayOffset;         for(int i=0;i     

上面这段代码是自定义的ListView

下面看一下adapter

package com.zhangyu.activity;    import android.app.Activity;   import android.os.Bundle;  import android.view.LayoutInflater;  import android.view.View;  import android.view.ViewGroup;  import android.widget.BaseAdapter;  import android.widget.TextView;    public class HorizontalListViewDemo extends Activity {     @Override   protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);        setContentView(R.layout.main);        HorizontialListView listview = (HorizontialListView) findViewById(R.id.listview);    listview.setAdapter(mAdapter);       }      private static String[] dataObjects = new String[]{ "Text #1",    "Text #2",    "Text #3" };       private BaseAdapter mAdapter = new BaseAdapter() {      @Override    public int getCount() {     return dataObjects.length;    }      @Override    public Object getItem(int position) {     return null;    }      @Override    public long getItemId(int position) {     return 0;    }      @Override    public View getView(int position, View convertView, ViewGroup parent) {     View retval = LayoutInflater.from(parent.getContext()).inflate(R.layout.viewitem, null);     TextView title = (TextView) retval.findViewById(R.id.title);     title.setText(dataObjects[position]);          return retval;    }       };            }
里面的数据自己填充哦

</GETCHILDCOUNT();I++){></view></view></listadapter></pre>