当前位置: 代码迷 >> Android >> Android ListView 侧滑成效实现(滑动展开、滑动删除)
  详细解决方案

Android ListView 侧滑成效实现(滑动展开、滑动删除)

热度:67   发布时间:2016-04-28 02:57:56.0
Android ListView 侧滑效果实现(滑动展开、滑动删除)

转载请注明出处:http://blog.csdn.net/lonelyroamer/article/details/42439875


项目需要ListView滑动删除的效果,首先肯定是拿来主义,在网上搜了一遍,发现这样的东西真不少,比较有名的Github上的SwipeListView。但是个人尝试了一下,发现它的bug不少,并且达不到我想要的效果。于是又尝试了一下其他的例子,发现基本效果都有,但是都有不少问题。要么事件冲突,要么OnItemListView或者某个Button响应不了。没办法,只能自己着手写一个。

最开始,写了一个最简单的,只支持右边的侧滑,并且只支持一种滑动的模式,先在项目里面用上。然后想将这个项目完善起来,断断续续的写了一段时间。期间Android5.0发布了,新出的控件RecyclerView 将要取代ListView的地位。顿时觉得自己做了无用功,然后就中断了。

但是后面发现RecyclerView毕竟是新出的控件,很多基于ListView的第三方库,RecyclerView并没有(用的人少,自然没人去写)。于是又把这个捡起来重新写,说不定以后会用得到。


先看一下运行的demo效果,



实现的具体细节就不描述了,后面会上传完整的代码。说一下使用的问题。

1、在你的layout文件中添加改控件:

    <com.roamer.slidelistview.SlideListView        xmlns:slide="http://schemas.android.com/apk/res-auto"        android:id="@+id/list_view"        android:layout_width="match_parent"        android:layout_height="match_parent"        slide:slideAnimationTime="200"        slide:slideLeftAction="scroll"        slide:slideMode="both"        slide:slideRightAction="scroll" />

2、继承SlideBaseAdapter,重写里面的getFrontViewId(),getLeftBackViewId(),getRightBackViewId()方法。

	@Override	public int getFrontViewId(int position) {		return R.layout.row_front_view;	}	@Override	public int getLeftBackViewId(int position) {		return R.layout.row_left_back_view;	}	@Override	public int getRightBackViewId(int position) {		return R.layout.row_right_back_view;	}
一个Item可不可以侧滑,取决于三点,优先级从上到下。

(1)、你是否为该Item提供了LeftBackView或者RightBackView

(2)、在SlideBaseAdapter中有一个方法,可以改变某个位置的SlideMode,你可以单独改变某个position的SlideMode

	/**	 * At first,your whole item slide mode is base on the SlideListView's	 * SlideMode.<br/>	 * but your can change the slide mode at one or more position in this	 * adapter by override this method	 * 	 * @param position	 * @return	 */	public SlideMode getSlideModeInPosition(int position) {		return mSlideMode;	}

(3)、你的SlideListView设置的SlideMode的值


3、SlideAction表示侧滑展开的方式,目前有两种SCROLL和REVEAL。效果分别如下:

SCROLL:


REVEAL:


4、如果你的front view 和back view组合起来有多种视图,那么你还必须重写getItemViewType()和getViewTypeCount()方法,否则视图重用的时候会混乱

	@Override	public int getFrontViewId(int position) {		return R.layout.row_front_view;	}	@Override	public int getLeftBackViewId(int position) {		if (position % 2 == 0) {			return R.layout.row_left_back_view;		}		return R.layout.row_right_back_view;	}	@Override	public int getRightBackViewId(int position) {		return R.layout.row_right_back_view;	}	@Override	public int getItemViewType(int position) {		if (position % 2 == 0) {			return 0;		}		return 1;	}	@Override	public int getViewTypeCount() {		return 2;	}

如果该代码对你有帮助,不胜荣幸。如果有BUG,欢迎指正。

有人说你上传个资源还要分,好吧,这次不要分。下载戳这里




BUG FIX

1、OnScrollListener不正确回调导致的问题(2015-01-06 10点)

Android3.0以下,ListView的OnScrollListener回调的状态会不正确,参考http://blog.csdn.net/ygc87/article/details/8078798.

这样就会导致当滑动到顶部或者底部,然后在继续滑动的时候,isInScrolling得不到正确的状态值。下一次滑动的时候会导致Item不能滑动。

	private OnScrollListener mInnerOnScrollListener = new OnScrollListener() {		@Override		public void onScrollStateChanged(AbsListView view, int scrollState) {			if (scrollState == SCROLL_STATE_IDLE) {				isInScrolling = false;			} else {				isInScrolling = true;			}			if (mOnScrollListener != null) {				mOnScrollListener.onScrollStateChanged(view, scrollState);			}		}		@Override		public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {			if (mOnScrollListener != null) {				mOnScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);			}		}	};

解决办法:

在SlideListView中添加如下代码:

private static Field sTouch_Mode_Field;	static {		try {			sTouch_Mode_Field = AbsListView.class					.getDeclaredField("mTouchMode");			sTouch_Mode_Field.setAccessible(true);		} catch (NoSuchFieldException e) {			e.printStackTrace();		}	}
	void checkScrolling() {		if (!isInScrolling) {			return;		}		if(sTouch_Mode_Field == null){			return;		}		int touchMode = 0;		try {			touchMode = sTouch_Mode_Field.getInt(this);		} catch (IllegalAccessException e1) {			e1.printStackTrace();		} catch (IllegalArgumentException e1) {			e1.printStackTrace();		}		if (DEUBG) {			Log.d(TAG, "mTouchMode:" + touchMode);		}		if (touchMode == -1) {// touchMode==TOUCH_MODE_REST			isInScrolling = false;		}	}

在SlideTouchListener的onInterceptTouchEvent方法中添加下面标红的代码:

                // don't allow swiping if this is on the header or footer or
                // IGNORE_ITEM_VIEW_TYPE or enabled is false on the adapter
                boolean allowSlide = mSlideListView.getAdapter().isEnabled(position) && mSlideListView.getAdapter().getItemViewType(position) >= 0;
                if (allowSlide) {
                    if (Build.VERSION.SDK_INT <= 11) {// below 3.0
                        mSlideListView.checkScrolling();
                    }

                    mDownPosition = position;
                    mActivePointerId = event.getPointerId(0);
                    mDownMotionX = (int) event.getX();
                    initOrResetVelocityTracker();
                    mVelocityTracker.addMovement(event);
                }




  相关解决方案