Android实现左滑删除列表功能

本文实例为大家分享了Android自定义左滑删除列表的具体代码,供大家参考,具体内容如下

1、布局文件view_left_slide_remove.xml

包含一个RelativeLayout和TextView,RelativeLayout是实际界面,TextView是删除按钮。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="40dp">
  <RelativeLayout
    android:id="@+id/view_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
  <TextView
    android:id="@+id/tv_remove"
    android:layout_width="@dimen/left_slide_remove_width"
    android:layout_height="match_parent"
    android:layout_alignParentRight="true"
    android:gravity="center"
    android:text="删除"
    android:textSize="16sp"
    android:textColor="@color/white"
    android:background="#ffff4b30"
    android:visibility="gone"/>
</RelativeLayout>

2、自定义Adapter

LeftSlideRemoveAdapter类实现了BaseAdapter。
在getView方法中引用了view_left_slide_remove布局,提供getSubView来导入真正的布局。
OnItemRemoveListener是删除监听器。

public static abstract class LeftSlideRemoveAdapter extends BaseAdapter {
 protected Context mContext;
 private OnItemRemoveListener mListener;

 public LeftSlideRemoveAdapter(Context context) {
 this.mContext = context;
 }

 @Override
 public final View getView(final int position, View convertView, ViewGroup parent) {
 ViewHolder holder;
 if (convertView == null) {
  LayoutInflater inflater = LayoutInflater.from(mContext);
  convertView = inflater.inflate(R.layout.view_left_slide_remove, parent, false);

  holder = new ViewHolder();
  holder.viewContent = (RelativeLayout) convertView.findViewById(R.id.view_content);
  holder.tvRmove = (TextView) convertView.findViewById(R.id.tv_remove);
  convertView.setTag(holder);

  // viewChild是实际的界面
  holder.viewChild = getSubView(position, null, parent);
  holder.viewContent.addView(holder.viewChild);
 } else {
  holder = (ViewHolder) convertView.getTag();
  getSubView(position, holder.viewChild, parent);
 }
 holder.tvRmove.setOnClickListener(new View.OnClickListener(){
  @Override
  public void onClick(View v) {
  if (mListener != null) {
   mListener.onItemRemove(position);
   notifyDataSetChanged();
  }
  }
 });
 return convertView;
 }

 public abstract View getSubView(int position, View convertView, ViewGroup parent);
}

private static class ViewHolder {
 RelativeLayout viewContent;
 View viewChild;
 View tvRmove;
}

public static interface OnItemRemoveListener {
 public void onItemRemove(int position);
}

3、自定义左滑删除列表

在dispatchTouchEvent方法里面捕捉MotionEvent事件。
在onTouchEvent方法里面滑动界面。
VelocityTracker类记录手势。
Scroller类进行滑动操作。

public class LeftSlideRemoveListView extends ListView {
  private final static int SNAP_VELOCITY = 600;

  private Scroller mScroller;
  private VelocityTracker mVelocityTracker;

  private int mTouchSlop;
  private boolean mIsSlide = false;
  private int mDelta = 0;
  private int mDownX;
  private int mDownY;
  private int mMaxDistence;
  private int mSlidePosition = INVALID_POSITION;
  private OnItemRemoveListener adapterListener;

  private OnItemRemoveListener mRemoveListener = new OnItemRemoveListener() {
    @Override
    public void onItemRemove(int position) {
      if (adapterListener != null) {
        adapterListener.onItemRemove(position);
      }
      clear();
      mSlidePosition = INVALID_POSITION;
    }
  };
  private LeftSlideRemoveAdapter mRemoveAdapter;

  private View mCurrentContentView, mCurrentRemoveView;

  public LeftSlideRemoveListView(Context context) {
    this(context, null);
  }

  public LeftSlideRemoveListView(Context context, AttributeSet attrs) {
    super(context, attrs);

    mScroller = new Scroller(context);
    mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();

    mMaxDistence = context.getResources().getDimensionPixelSize(
        R.dimen.left_slide_remove_width);
  }

  @Override
  public boolean dispatchTouchEvent(MotionEvent ev) {
    switch (ev.getAction()) {
      case MotionEvent.ACTION_DOWN:
        addVelocityTracker(ev);

        if (!mScroller.isFinished()) {
          return super.dispatchTouchEvent(ev);
        }
        // 起始位置,当前position
        mDownX = (int) ev.getX();
        mDownY = (int) ev.getY();
        int position = pointToPosition(mDownX, mDownY);
        if (position == mSlidePosition) break;

        mSlidePosition = position;

        if (mSlidePosition == INVALID_POSITION ) {
          return super.dispatchTouchEvent(ev);
        }

        // 恢复状态
        clear();

        // 获取当前界面
        View childView = getChildAt(mSlidePosition - getFirstVisiblePosition());
        mCurrentContentView = childView.findViewById(R.id.view_content);
        mCurrentRemoveView = childView.findViewById(R.id.tv_remove);

        break;
      case MotionEvent.ACTION_MOVE:
        if (mCurrentContentView == null) break;

        if (Math.abs(getScrollVelocity()) > SNAP_VELOCITY
            || (Math.abs(ev.getX() - mDownX) > mTouchSlop
            && Math.abs(ev.getY() - mDownY) < mTouchSlop)) {
          // 开始滑动
          mIsSlide = true;
        }
        break;
      case MotionEvent.ACTION_UP:
        if (mCurrentContentView == null && mIsSlide) break;

        // 如果左滑小于4/5,按钮不显示
        if (mDelta < mMaxDistence * 4 / 5) {
          mCurrentRemoveView.setVisibility(View.GONE);
          scrollRight();
        } else if (mDelta < mMaxDistence) {
          scrollLeft();
        }
        recycleVelocityTracker();
        mIsSlide = false;
        break;
    }

    return super.dispatchTouchEvent(ev);
  }

  @Override
  public boolean onTouchEvent(MotionEvent ev) {
    if (mIsSlide && mSlidePosition != INVALID_POSITION) {
      final int action = ev.getAction();
      int x = (int) ev.getX();
      switch (action) {
        case MotionEvent.ACTION_MOVE:
          addVelocityTracker(ev);

          int deltaX = mDownX - x;
          mDownX = x;

          mDelta += deltaX;

          if (mDelta < 0) {
            mCurrentContentView.scrollTo(0, 0);

            mDelta = 0;
            mCurrentRemoveView.setVisibility(View.GONE);
          } else if (mDelta >= mMaxDistence) {
            mDelta = mMaxDistence;
            mCurrentContentView.scrollTo(mMaxDistence, 0);
            mCurrentRemoveView.setVisibility(View.VISIBLE);
            mCurrentRemoveView.setTranslationX(0);
          } else {
            mCurrentContentView.scrollBy(deltaX, 0);
            mCurrentRemoveView.setVisibility(View.VISIBLE);
            mCurrentRemoveView.setTranslationX(mMaxDistence - mDelta);
          }
          break;
      }
      return true;
    }
    return super.onTouchEvent(ev);
  }

  // 右滑
  private void scrollRight() {
    final int delta = mDelta;
    mScroller.startScroll(delta, 0, -delta, 0, Math.abs(delta));
    mDelta = 0;
    postInvalidate();
  }

  // 左滑
  private void scrollLeft() {
    final int delta = mMaxDistence - mDelta;
    mScroller.startScroll(mDelta, 0, delta, 0, Math.abs(delta));
    mDelta = mMaxDistence;
    postInvalidate();
  }

  @Override
  public void computeScroll() {
    if (mScroller.computeScrollOffset()) {
      mCurrentContentView.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
      mCurrentRemoveView.setTranslationX(mMaxDistence - mScroller.getCurrX());

      postInvalidate();

      if (mScroller.isFinished()) {
        mCurrentContentView.scrollTo(mDelta, 0);
        mCurrentRemoveView.setTranslationX(0);
      }
    }
  }

  private void addVelocityTracker(MotionEvent event) {
    if (mVelocityTracker == null) {
      mVelocityTracker = VelocityTracker.obtain();
    }

    mVelocityTracker.addMovement(event);
  }

  private int getScrollVelocity() {
    mVelocityTracker.computeCurrentVelocity(1000);
    int velocity = (int) mVelocityTracker.getXVelocity();
    return velocity;
  }

  private void recycleVelocityTracker() {
    if (mVelocityTracker != null) {
      mVelocityTracker.recycle();
      mVelocityTracker = null;
    }
  }

  private void clear() {
    if (mCurrentContentView != null) {
      mDelta = 0;
      mCurrentContentView.scrollTo(0, 0);
      mCurrentContentView = null;

      mCurrentRemoveView.setVisibility(View.GONE);
      mCurrentRemoveView = null;
    }
  }

  @Override
  public void setAdapter(ListAdapter adapter) {
    if (adapter instanceof LeftSlideRemoveAdapter) {
      super.setAdapter(adapter);

      mRemoveAdapter = (LeftSlideRemoveAdapter) adapter;
      mRemoveAdapter.mListener = mRemoveListener;
    } else {
      throw new IllegalArgumentException("Must be LeftSlideRemoveAdapter");
    }
  }

  public void setOnItemRemoveListener(OnItemRemoveListener listener) {
    adapterListener = listener;
  }
}

4、测试例子

ContractAdapter继承LeftSlideRemoveAdapter类。
LeftSlideRemoveActivity中使用LeftSlideRemoveListView类。

public class LeftSlideRemoveActivity extends Activity {
  private List<Map<String, String>> mContentList = new ArrayList<Map<String, String>>();

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_left_slide_remove);

    Map<String, String> item = new HashMap<String, String>();
    item.put("name", "Peter");
    item.put("address", "ShangHai");
    mContentList.add(item);

    item = new HashMap<String, String>();
    item.put("name", "Lily");
    item.put("address", "BeiJing");
    mContentList.add(item);

    item = new HashMap<String, String>();
    item.put("name", "Jack");
    item.put("address", "GuangZhou");
    mContentList.add(item);

    item = new HashMap<String, String>();
    item.put("name", "Mike");
    item.put("address", "ShengZhen");
    mContentList.add(item);

    LeftSlideRemoveListView lv = (LeftSlideRemoveListView) findViewById(R.id.id_listview);
    lv.setAdapter(new ContractAdapter(this));
    lv.setOnItemRemoveListener(new LeftSlideRemoveListView.OnItemRemoveListener() {
      @Override
      public void onItemRemove(int position) {
        mContentList.remove(position);
      }
    });
  }

  private class ContractAdapter extends LeftSlideRemoveListView.LeftSlideRemoveAdapter {

    public ContractAdapter(Context context) {
      super(context);
    }

    @Override
    public int getCount() {
      return mContentList.size();
    }

    @Override
    public Object getItem(int position) {
      return position;
    }

    @Override
    public long getItemId(int position) {
      return position;
    }

    @Override
    public View getSubView(int position, View convertView, ViewGroup parent) {
      ViewHolder holder;
      if (convertView == null) {
        convertView = getLayoutInflater().inflate(
            R.layout.listview_item_customdapter, parent, false);
        holder = new ViewHolder();
        holder.tvName = (TextView) convertView.findViewById(R.id.tv_name);
        holder.tvAddress = (TextView) convertView.findViewById(R.id.tv_address);

        convertView.setTag(holder);
      } else {
        holder = (ViewHolder) convertView.getTag();
      }
      Map<String, String> itemData = mContentList.get(position);
      holder.tvName.setText(itemData.get("name"));
      holder.tvAddress.setText(itemData.get("address"));

      return convertView;
    }
  }

  private class ViewHolder {
    TextView tvName;
    TextView tvAddress;
  }

}

显示如下

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android仿QQ左滑删除置顶ListView操作

    最近闲来无事,于是研究了一下qq的左滑删除效果,尝试着实现了一下,先上效果图: 大致思路原理: - 通过设置margin实现菜单的显示与隐藏 - 监听onTouchEvent,处理滑动事件 上代码 import android.content.Context; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.view.MotionEvent; import android.v

  • Android 实现左滑出现删除选项

    滑动删除的部分主要包含两个部分, 一个是内容区域(用于放置正常显示的view),另一个是操作区域(用于放置删除按钮).默认情况下,操作区域是不显示的,内容区域的大小是填充整个容 器,操作区域始终位于内容区域的右面.当开始滑动的时候,整个容器中的所有子view都像左滑动,如果操作区域此时是不可见的,设置为可见. 实现思路就是自定义一个layout SwipeLayout继承自FrameLayout.SwipeLayout包含两个子view,第一个子view是内容区域,第二个子view是操作 区域.

  • Android自定义组合控件之自定义下拉刷新和左滑删除实例代码

    绪论 最近项目里面用到了下拉刷新和左滑删除,网上找了找并没有可以用的,有比较好的左滑删除,但是并没有和下拉刷新上拉加载结合到一起,要不就是一些比较水的结合,并不能在项目里面使用,小编一着急自己组合了一个,做完了和QQ的对比了一下,并没有太大区别,今天分享给大家,其实并不难,但是不知道为什么网上没有比较好的Demo,当你的项目真的很急的时候,又没有比较好的Demo,那么"那条友谊的小船儿真是说翻就翻啊",好了,下面先来具体看一下实现后的效果吧: 代码已经上传到Github上了,小伙伴们记

  • Android使用CardView作为RecyclerView的Item并实现拖拽和左滑删除

    引言 CardView是Android 5.0系统之后引入的众多控件之一,实现之后的效果也是比较酷的,它经常被用在RecyclerView和ListView中的Item中.今天我们就来了解一下CardView的属性,然后使用CardView和RecyclerView结合实现一个可以拖拽Item的布局. CardView的属性 CardView继承自FrameLayout,所以子控件的布局规则和FrameLayout的一样,是按照层次堆叠的 下面是CardView的一些常用属性: CardView

  • Android ListView实现仿iPhone实现左滑删除按钮的简单实例

    需要自定义ListView.这里就交FloatDelListView吧. 复写onTouchEvent方法.如下: @Override public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN:<BR> // 获取按下的条目视图(child view) int childCount = getChildCount(); int[] listViewCo

  • Android仿微信实现左滑显示删除按钮功能

    在实际项目中删除列表中的某一项是非常常见的功能,传统的做法可以使用长按监听器等,而现在流行的做法是左滑弹出删除按钮,微信,QQ等都是这么做的,下面做一个示例,代码如下: 主页面MainActivity:代码比较简单常规 package com.home.testslideview; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.os.Bundle; im

  • Android仿QQ列表左滑删除操作

    最近学习了如何做一个像QQ的左滑RecyclerView的item显示选项的,主要是用到Scroller 我们首先新建一个自己的RecyclerView 定义好一些要用的的变量 重写构造方法,把前两个构造方法改为如下,使无论如何构造都要执行第三个构造方法 在第三个构造方法里初始化Scroller public class LeftSwipeMenuRecyclerView extends RecyclerView { //置顶按钮 private TextView tvTop; //删除按钮 p

  • Android使用PullToRefresh完成ListView下拉刷新和左滑删除功能

    ListView下刷新刷功能相信从事Android开发的猿友们并不陌生,包括现在Google亲儿子SwipeRefreshLayout实现效果在一些APP上也能看见(不过个人不喜欢官方的刷新效果).本文就带领一些刚入门android的朋友或者一起爱分享的朋友来简单的实现ListView的下拉刷新和左滑删除效果. 一.本文主要内容: 使用PullToRefresh完成ListView下拉.上拉刷新: 扩展PullToRefresh完美的实现ListView左滑删除效果: 注意:本文中的PullTo

  • Android仿QQ首页ListView左滑置顶、删除功能

    Android 仿QQ首页ListView左滑置顶.删除等实现源码,具体内容如下 效果图 实现源码:package com.duguang.baseanimation.ui.listivew.deletelistview; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue; import android.

  • Android下拉刷新上拉加载更多左滑动删除

    一.前言 老规矩,别的不说,这demo是找了很相关知识集合而成的,可以说对我这种小白来说是绞尽脑汁!程序员讲的是无图无真相! 现在大家一睹为快! 二.比较关键的还是scroller这个类的 package com.icq.slideview.view; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue;

随机推荐