横向滑动的listview效果的实现方法,scrollview嵌套水平滑动的li

很多时候,界面需要实现横向滑动的listview效果。网络上有一种方法,自定义了HorizontalListView,用法同正常的listview,可实现水平滑动效果。

但是如果一个界面 为垂直滑动的scrollview嵌套水平滑动的listview的时候,滑动水平listview的时候,会很卡。我最近就遇到了这样的问题,一直把思路放在监听水平和垂直滑动手势,想实现滑动角度小于45的时候 垂直的scrollview 滑动效果被禁止。但是一直没有研究出来。

于是一个偶然的机会,灵光一闪,想到用HorizontalScrollView嵌套gridview,实现水平滑动的效果。果真效果很棒哦。没有卡顿的现象出现。

方法如下:

布局:

<HorizontalScrollView android:layout_width="fill_parent" android:layout_height="wrap_content" android:scrollbars="none" > <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" > <GridView android:id="@+id/server_details_content_view_product_gv" android:layout_width="wrap_content" android:layout_height="wrap_content" > </GridView> </LinearLayout> </HorizontalScrollView>

代码中要设置gridview的属性,否则没有滑动效果

/** 设置GirdView参数,length一般为100到230不等,自己设置适配吧。size为列表的大小*/private void setGridView(GridView gv, int length, int size) {DisplayMetrics dm = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(dm);float density = dm.density;int gridviewWidth = (int) (size * (length + 4) * density);int itemWidth = (int) (length * density);LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(gridviewWidth, LinearLayout.LayoutParams.FILL_PARENT);gv.setLayoutParams(params); // 设置GirdView布局参数,横向布局的关键gv.setColumnWidth(itemWidth); // 设置列表项宽gv.setHorizontalSpacing(5); // 设置列表项水平间距gv.setStretchMode(GridView.NO_STRETCH);gv.setNumColumns(size); // 设置列数量=列表集合数}

设置适配器的时候。适配器的写法同正常的gridview的适配器,,再次不再附代码。如有疑问可以留言哦。

setGridView(vStepsGv, 230,serviceContentList.size());stepsAdapter = new ServerStepsListAdapter(this, serviceContentList);vStepsGv.setAdapter(stepsAdapter);

另外如果不需要外层嵌套垂直滑动的scrollview,这个自定义的listview还是不错的啦!附代码:(用法同正常的listview,如有疑问可以留言哦)

/*** 左右滑动的listview** @author lunizhu**/public class HorizontalListView 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 HorizontalListView(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);}@Overridepublic void setOnItemSelectedListener(AdapterView.OnItemSelectedListener listener) {mOnItemSelected = listener;}@Overridepublic void setOnItemClickListener(AdapterView.OnItemClickListener listener) {mOnItemClicked = listener;}@Overridepublic void setOnItemLongClickListener(AdapterView.OnItemLongClickListener listener) {mOnItemLongClicked = listener;}private DataSetObserver mDataObserver = new DataSetObserver() {@Overridepublic void onChanged() {synchronized (HorizontalListView.this) {mDataChanged = true;}invalidate();requestLayout();}@Overridepublic void onInvalidated() {reset();invalidate();requestLayout();}};@Overridepublic ListAdapter getAdapter() {return mAdapter;}@Overridepublic View getSelectedView() {// TODO: implementreturn null;}@Overridepublic void setAdapter(ListAdapter adapter) {if (mAdapter != null) {mAdapter.unregisterDataSetObserver(mDataObserver);}mAdapter = adapter;mAdapter.registerDataSetObserver(mDataObserver);reset();}private synchronized void reset() {initView();removeAllViewsInLayout();requestLayout();}@Overridepublic void setSelection(int position) {int positionX = position * this.getWidth();int maxWidth = this.getChildCount() * this.getWidth();if (positionX <= 0) {positionX = 0;}if (positionX > maxWidth) {positionX = maxWidth;}scrollTo(positionX);}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));}@Overrideprotected 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() {@Overridepublic 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();}@Overridepublic 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 (HorizontalListView.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() {@Overridepublic boolean onDown(MotionEvent e) {return HorizontalListView.this.onDown(e);}@Overridepublic boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) {return HorizontalListView.this.onFling(e1, e2, velocityX, velocityY);}@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2,float distanceX, float distanceY) {synchronized (HorizontalListView.this) {mNextX += (int) distanceX;}requestLayout();return true;}@Overridepublic boolean onSingleTapConfirmed(MotionEvent e) {for (int i = 0; i < getChildCount(); i++) {View child = getChildAt(i);if (isEventWithinView(e, child)) {if (mOnItemClicked != null) {mOnItemClicked.onItemClick(HorizontalListView.this,child, mLeftViewIndex + 1 + i,mAdapter.getItemId(mLeftViewIndex + 1 + i));}if (mOnItemSelected != null) {mOnItemSelected.onItemSelected(HorizontalListView.this,child, mLeftViewIndex + 1 + i,mAdapter.getItemId(mLeftViewIndex + 1 + i));}break;}}return true;}@Overridepublic 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(HorizontalListView.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());}};}

数最亮的星。如果有可能,我带你去远行。

横向滑动的listview效果的实现方法,scrollview嵌套水平滑动的li

相关文章:

你感兴趣的文章:

标签云: