横着的Listview

来源:互联网 发布:sql统计重复数据个数 编辑:程序博客网 时间:2024/04/29 22:45
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<ListAdapter> { 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<View> mRemovedViewQueue = new LinkedList<View>(); 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<getChildCount();i++){ View child = getChildAt(i); int childWidth = child.getMeasuredWidth(); child.layout(left, 0, left + childWidth, child.getMeasuredHeight()); left += childWidth + child.getPaddingRight();  }  }  } public synchronized void scrollTo(int x) { mScroller.startScroll(mNextX, 0, x - mNextX, 0); requestLayout();  } @Override public boolean dispatchTouchEvent(MotionEvent ev) { boolean handled = super.dispatchTouchEvent(ev); handled |= mGesture.onTouchEvent(ev); return handled;  } protected boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { synchronized(HorizontialListView.this){ mScroller.fling(mNextX, 0, (int)-velocityX, 0, 0, mMaxX, 0, 0);  } requestLayout();  return true;  } protected boolean onDown(MotionEvent e) { mScroller.forceFinished(true); return true;  } private OnGestureListener mOnGesture = new GestureDetector.SimpleOnGestureListener() { @Override  public boolean onDown(MotionEvent e) {  Log.i("lkl","ondown@@@@@@" ); return HorizontialListView.this.onDown(e); } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { Log.i("lkl","onFling@@@@@@" ); return HorizontialListView.this.onFling(e1, e2, velocityX, velocityY);  } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { Log.i("lkl","onscroll@@@@@@" ); synchronized(HorizontialListView.this){ mNextX += (int)distanceX;  } requestLayout(); return true;  } @Override public boolean onSingleTapConfirmed(MotionEvent e) { Log.i("lkl","onSingletapConfrimed@@@@@@" ); for(int i=0;i<getChildCount();i++){ View child = getChildAt(i);  if (isEventWithinView(e, child)) { if(mOnItemClicked != null){ mOnItemClicked.onItemClick(HorizontialListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId( mLeftViewIndex + 1 + i ));  }  if(mOnItemSelected != null){ mOnItemSelected.onItemSelected(HorizontialListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId( mLeftViewIndex + 1 + i ));  }  break;  }  }  return true;  } @Override public void onLongPress(MotionEvent e) { int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View child = getChildAt(i); if (isEventWithinView(e, child)) { if (mOnItemLongClicked != null) { mOnItemLongClicked.onItemLongClick(HorizontialListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId(mLeftViewIndex + 1 + i));  }  break;  }  }  } private boolean isEventWithinView(MotionEvent e, View child) {  Rect viewRect = new Rect();   int[] childPosition = new int[2];    child.getLocationOnScreen(childPosition);    int left = childPosition[0];    int right = left + child.getWidth();   int top = childPosition[1];  int bottom = top + child.getHeight();      viewRect.set(left, top, right, bottom); return viewRect.contains((int) e.getRawX(), (int) e.getRawY());   }  };  }

下面是调用

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;  }   };  }