listview左右滑动

    xiaoxiao2022-06-29  36

    转载自http://blog.csdn.net/lonelyroamer/article/details/42439875

    以前做成功过,最近再次研究也没成功,因为项目是eclipse的,现在用studio开发,留作以后有时间去研究

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

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

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

    先看一下运行的demo效果,

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

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

    [java]  view plain  copy   <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()方法。

    [java]  view plain  copy   @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

    [java]  view plain  copy   /**   * 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()方法,否则视图重用的时候会混乱

    [java]  view plain  copy   @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不能滑动。

    [cpp]  view plain  copy 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中添加如下代码:

    [java]  view plain  copy 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();           }       }   [java]  view plain  copy 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);                 }

    2、SlideItem不正常关闭(Adapter数据集的改变,action的改变、adapter的改变),导致Front  view不能响应事件的问题(2015-01-09)

    解决办法:将SlideListView的setAdapter方法改成如下:

    [java]  view plain  copy @Override   public void setAdapter(ListAdapter adapter) {       mAdapter = null;       if (adapter != null && adapter instanceof SlideBaseAdapter) {           mAdapter = (SlideBaseAdapter) adapter;           mAdapter.setSlideMode(mSlideMode);           mAdapter.setSlideLeftAction(mSlideLeftAction);           mAdapter.setSlideRightAction(mSlideRightAction);       }       super.setAdapter(adapter);          if (mTouchListener.isOpend()) {           mTouchListener.closeOpenedItem();       } else {           mTouchListener.reset();       }          if (adapter != null) {           adapter.registerDataSetObserver(new DataSetObserver() {               @Override               public void onChanged() {                   super.onChanged();                   if (DEUBG) {                       Log.e(TAG, "Adapter data has changed");                   }                   if (mTouchListener.isOpend()) {                       mTouchListener.closeOpenedItem();                   } else {                       mTouchListener.reset();                   }               }           });       }   }  

    3、Android2.3.3以下使用Nineoldandroids第三方库中属性动画的bug,导致Item划开后,backview不能点击。

    这个问题找了很久,才终于发现是问题。属性动画是Android3.0以后才添加的,所以才有人写了Nineoldandroids,用于3.0以下方便的使用属性动画。但是看了Nineoldandroids的代码,发现2.3.3以下并不是真正能达到属性动画的效果。运行了Github上面的SwipeListView(它也使用了Nineoldandroids库),发现在2.3.3以下也有这个BUG。

    这个BUG已经解决,2.3.3以下可以使用了,但是效果不算太好。

    最新的版本已上传到Github,虽然没什么人用,但是也算是自己的一番心血

    Github:https://github.com/LonelyRoamer/SlideListView

    4、回复 mavenly 

    主动打开和关闭你可以参考下,我最近很忙,没时间修改,可能这样做还有问题,以后我会在自己把这个功能加上。

    (1)、主动打开

    在SlideTouchListener加入下面的方法

    [java]  view plain  copy void openDirect(int position, boolean left) {       mDownPosition = position;       mSlideItem = new SlideItem(position);          SlideMode slideMode = mSlideListView.getSlideAdapter().getSlideModeInPosition(mSlideItem.position - mSlideListView.getHeaderViewsCount());       if (left) {// 要打开左边           if (slideMode == SlideMode.LEFT || slideMode == SlideMode.BOTH) {// SlideMode support left               mSlideItem.offset = 1;           }       } else {           if (slideMode == SlideMode.RIGHT || slideMode == SlideMode.BOTH) {// SlideMode support right               mSlideItem.offset = -1;           }       }       move(mSlideItem.offset);       autoScroll(mSlideItem.offset, true);   }   在SlideListView中调用即可主动打开指定位置

    [java]  view plain  copy public void openDirect(int position, boolean left) {       int opendPosition = mTouchListener.getOpendPosition();       if (opendPosition == position) {           return;       }       closeDirect();       mTouchListener.openDirect(position, left);   }  

    (2)、主动关闭

    将SlideListView中的 closeDirect() 改为public即可

    (3)、滑动有时候会卡 具体原因我也不清楚。我应用在我的项目中,没有发现。你看下Item的布局复杂程序。还有可能和手机的系统、性能也有关。我在模拟器Android3.0以上,都发现挺好的。

    转载请注明原文地址: https://ju.6miu.com/read-1125190.html

    最新回复(0)