之前,自己使用listview一直是长按删除,不过发现qq的消息和ios的都是侧滑删除,觉得效果很好,于是自己就想做一个侧滑删除。在网上找了些资料,有很多不是我理想的侧滑删除,最后还是找到了一个不错的,现在记录一下。

首先是自定义一个listview,这个里面需要重写onInterceptTouchEvent和onTouchEvent两个代码,一个是对滑动进行拦截,如果删除按钮已经显示,点击的不是删除的item,则把按钮隐藏。另一个是对item滑动的事件进行处理。滑动时item移动,显示删除按钮。

package com.zviewtech.videonetclient.mydeleteemo;

import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.ListView;

/**
 * Created by JunkChen on 2016/3/29 0029.
 */
public class SideslipListView extends ListView {
private static final String TAG = "SideslipListView";

    private int mScreenWidth;//屏幕的宽度
    private boolean isDeleteShow;//删除组件是否显示
    private ViewGroup mPointChild;//手指按下位置的item组件
    private int mDeleteWidth;//删除组件的宽度
    private LinearLayout.LayoutParams mItemLayoutParams;//手指按下时所在的item的布局参数
    private int mDownX;//手指初次按下的X坐标
    private int mDownY;//手指初次按下的Y坐标

    private int mPointPosition;//手指按下位置所在的item位置
    private boolean isAllowItemClick;//是否允许item点击

    public SideslipListView(Context context) {
super(context);
        init(context);
    }
public SideslipListView(Context context, AttributeSet attrs) {
super(context, attrs);
        init(context);
    }
public SideslipListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
        init(context);
    }
private void init(Context context) {
// 获取屏幕宽度
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics dm = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(dm);
        mScreenWidth = dm.widthPixels;
        Log.i(TAG, "***********mScreenWidth: " + mScreenWidth);
    }
@Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {//事件拦截
        switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN: {
isAllowItemClick = true;

                //侧滑删除
                mDownX = (int) ev.getX();
                mDownY = (int) ev.getY();
                mPointPosition = pointToPosition(mDownX, mDownY);
                Log.i(TAG, "*******pointToPosition(mDownX, mDownY): " + mPointPosition);
                if (mPointPosition != -1) {
if (isDeleteShow) {
ViewGroup tmpViewGroup = (ViewGroup) getChildAt(mPointPosition - getFirstVisiblePosition());
                        if (!mPointChild.equals(tmpViewGroup)) {
turnNormal();
                        }
}
//获取当前的item
                    mPointChild = (ViewGroup) getChildAt(mPointPosition - getFirstVisiblePosition());

                    mDeleteWidth = mPointChild.getChildAt(1).getLayoutParams().width;
                    mItemLayoutParams = (LinearLayout.LayoutParams) mPointChild.getChildAt(0).getLayoutParams();

                    Log.i(TAG, "*********mItemLayoutParams.height: " + mItemLayoutParams.height +
", mDeleteWidth: " + mDeleteWidth);
                    mItemLayoutParams.width = mScreenWidth;
                    mPointChild.getChildAt(0).setLayoutParams(mItemLayoutParams);
                }
break;
            }
case MotionEvent.ACTION_MOVE: {
int nowX = (int) ev.getX();
                int nowY = (int) ev.getY();
                int diffX = nowX - mDownX;
                Log.i(TAG, "******dp2px(4): " + dp2px(8) + ", dp2px(8): " + dp2px(8) +
", density: " + getContext().getResources().getDisplayMetrics().density);
                if (Math.abs(diffX) > dp2px(4) || Math.abs(nowY - mDownY) > dp2px(4)) {
return true;//避免子布局中有点击的控件时滑动无效
                }
break;
            }
}
return super.onInterceptTouchEvent(ev);
    }
public float dp2px(int dp) {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
                getContext().getResources().getDisplayMetrics());
    }
@Override
    public boolean onTouchEvent(MotionEvent ev) {//事件响应
        switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
performActionDown(ev);
                break;
            case MotionEvent.ACTION_MOVE:
performActionMove(ev);
                break;
            case MotionEvent.ACTION_UP:
performActionUp(ev);
                break;
        }
return super.onTouchEvent(ev);
    }
private void performActionDown(MotionEvent ev) {
mDownX = (int) ev.getX();
        mDownY = (int) ev.getY();
        if (isDeleteShow) {
ViewGroup tmpViewGroup = (ViewGroup) getChildAt(pointToPosition(mDownX, mDownY) - getFirstVisiblePosition());
            Log.i(TAG, "*********mPointChild.equals(tmpViewGroup): " + mPointChild.equals(tmpViewGroup));
            if (!mPointChild.equals(tmpViewGroup)) {
turnNormal();
            }
}
//获取当前的item
        mPointChild = (ViewGroup) getChildAt(pointToPosition(mDownX, mDownY) - getFirstVisiblePosition());

        mDeleteWidth = mPointChild.getChildAt(1).getLayoutParams().width;//获取删除组件的宽度
        Log.i(TAG, "**********pointToPosition(x,y): " + pointToPosition(mDownX, mDownY)
+ ", getFirstVisiblePosition() = " + getFirstVisiblePosition()
+ ", mDeleteWidth = " + mDeleteWidth);
        mItemLayoutParams = (LinearLayout.LayoutParams) mPointChild.getChildAt(0).getLayoutParams();

        mItemLayoutParams.width = mScreenWidth;
        mPointChild.getChildAt(0).setLayoutParams(mItemLayoutParams);
    }
private boolean performActionMove(MotionEvent ev) {
int nowX = (int) ev.getX();
        int nowY = (int) ev.getY();
        int diffX = nowX - mDownX;
        if (Math.abs(diffX) > Math.abs(nowY - mDownY) && Math.abs(nowY - mDownY) < 20) {
if (!isDeleteShow && nowX < mDownX) {//删除按钮未显示时向左滑
                if (-diffX >= mDeleteWidth) {//如果滑动距离大于删除组件的宽度时进行偏移的最大处理
                    diffX = -mDeleteWidth;
                }
mItemLayoutParams.leftMargin = diffX;
                mPointChild.getChildAt(0).setLayoutParams(mItemLayoutParams);
                isAllowItemClick = false;
            } else if (isDeleteShow && nowX > mDownX) {//删除按钮显示时向右滑
                if (diffX >= mDeleteWidth) {
diffX = mDeleteWidth;
                }
mItemLayoutParams.leftMargin = diffX - mDeleteWidth;
                mPointChild.getChildAt(0).setLayoutParams(mItemLayoutParams);
                isAllowItemClick = false;
            }
return true;
        }
return super.onTouchEvent(ev);
    }
private void performActionUp(MotionEvent ev) {
//如果向左滑出超过隐藏的二分之一就全部显示
        if (-mItemLayoutParams.leftMargin >= mDeleteWidth / 2) {
mItemLayoutParams.leftMargin = -mDeleteWidth;
            isDeleteShow = true;
            mPointChild.getChildAt(0).setLayoutParams(mItemLayoutParams);
        } else {
turnNormal();
        }
}
/**
     * 转换为正常隐藏情况
     */
    public void turnNormal() {
mItemLayoutParams.leftMargin = 0;
        mPointChild.getChildAt(0).setLayoutParams(mItemLayoutParams);
        isDeleteShow = false;
    }
/**
     * 是否允许Item点击
     *
     * @return
     */
    public boolean isAllowItemClick() {
return isAllowItemClick;
    }
}

这个listview主要是设置leftMargin这个左偏移来保证按钮的显示和隐藏的。activity里调用的代码也很简单

package com.zviewtech.videonetclient.mydeleteemo;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
    private SideslipListView mSideslipListView;

    /**
     * 初始化数据
     */
    private ArrayList<String> mDataList = new ArrayList<String>() {
{
for (int i = 0; i < 50; i++) {
add("ListView item  " + i);
            }
}
};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mSideslipListView = (SideslipListView) findViewById(R.id.sideslipListView);
        mSideslipListView.setAdapter(new CustomAdapter());//设置适配器
        //设置item点击事件
        mSideslipListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
            public void onItemClick(AdapterView parent, View view, int position, long id) {
if (mSideslipListView.isAllowItemClick()) {
Log.i(TAG, mDataList.get(position) + "被点击了");
                    Toast.makeText(MainActivity.this, mDataList.get(position) + "被点击了",
                            Toast.LENGTH_SHORT).show();
                }
}
});
        //设置item长按事件
        mSideslipListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
            public boolean onItemLongClick(AdapterView parent, View view, int position, long id) {
if (mSideslipListView.isAllowItemClick()) {
Log.i(TAG, mDataList.get(position) + "被长按了");
                    Toast.makeText(MainActivity.this, mDataList.get(position) + "被长按了",
                            Toast.LENGTH_SHORT).show();
                    return true;//返回true表示本次事件被消耗了,若返回
                }
return false;
            }
});
    }
/**
     * 自定义ListView适配器
     */
    class CustomAdapter extends BaseAdapter {
@Override
        public int getCount() {
return mDataList.size();
        }
@Override
        public Object getItem(int position) {
return mDataList.get(position);
        }
@Override
        public long getItemId(int position) {
return position;
        }
@Override
        public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
            if (null == convertView) {
convertView = View.inflate(MainActivity.this, R.layout.item, null);
                viewHolder = new ViewHolder();
                viewHolder.textView = (TextView) convertView.findViewById(R.id.textView);
                viewHolder.txtv_delete = (TextView) convertView.findViewById(R.id.txtv_delete);
                convertView.setTag(viewHolder);
            } else {
viewHolder = (ViewHolder) convertView.getTag();
            }
viewHolder.textView.setText(mDataList.get(position));
            final int pos = position;
            viewHolder.txtv_delete.setOnClickListener(new View.OnClickListener() {
@Override
                public void onClick(View v) {
Toast.makeText(MainActivity.this, mDataList.get(pos) + "被删除了",
                            Toast.LENGTH_SHORT).show();
                    mDataList.remove(pos);
                    notifyDataSetChanged();
                    mSideslipListView.turnNormal();
                }
});
            return convertView;
        }
}
class ViewHolder {
public TextView textView;
        public TextView txtv_delete;
    }
}

其实和普通的listview是一致的,只是在点击时判断滑动变量,如果为true,则不响应点击事件。如果为false,则响应点击事件。

listview的item的布居我要显示出来,因为这和自定义的listview的代码相关,必须是这样的,如果修改,则mDeleteWidth = mPointChild.getChildAt(1).getLayoutParams().width;这里也必须做相应的修改,getChild()的参数和删除按钮的位置一致

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" >

    <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="8dp">

        <TextView
            android:id="@+id/textView"
            android:layout_width="match_parent"
            android:layout_height="48dp"
            android:textSize="18sp"
            android:text="text">

        </TextView>

    </LinearLayout>
    <!--必须指定宽度-->
    <TextView android:id="@+id/txtv_delete" android:layout_width="96dp"
        android:layout_height="match_parent"
        android:textSize="18sp" android:text="删除" android:textColor="#eeeeee" android:gravity="center" android:background="#e53935">
    </TextView>
</LinearLayout>

listview的滑动删除就完成了。

就这么简单。



android listview左滑删除相关推荐

  1. android listview标题置顶,Android仿QQ左滑删除置顶ListView操作

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

  2. android 自定义 滑动删除,Android_Android ListView实现仿iPhone实现左滑删除按钮的简单实例,需要自定义ListView。这里就交Fl - phpStudy...

    Android ListView实现仿iPhone实现左滑删除按钮的简单实例 需要自定义ListView.这里就交FloatDelListView吧. 复写onTouchEvent方法.如下: @Ov ...

  3. Android开发学习之路-PopupWindow和仿QQ左滑删除

    这周作业,要做一个类似QQ的左滑删除效果的ListView,因为不想给每个item都放一个按钮,所以决定用PopupWindow,这里记录一下 先放一下效果图: 先说明一下这里面的问题: ①没有做到像 ...

  4. Android自定义组合控件---教你如何自定义下拉刷新和左滑删除

    绪论 最近项目里面用到了下拉刷新和左滑删除,网上找了找并没有可以用的,有比较好的左滑删除,但是并没有和下拉刷新上拉加载结合到一起,要不就是一些比较水的结合,并不能在项目里面使用,小编一着急自己组合了一 ...

  5. 小程序uniapp实现左滑删除效果

    小程序uniapp实现左滑删除效果 实现效果 1,列表中侧滑删除 2,删除不同时存在 3,上下滑动与侧滑删除不影响 在本页面引入组件并使用 (文件在文章的最下方附上) 在需要左滑删除的地方使用 < ...

  6. 微信小程序左滑删除效果的实现完整源码附效果图

    效果图: 功能描述,小程序列表左滑删除功能的实现完整源代码实现: <view wx:for='{{friends}}' wx:key="" wx:if='{{groupTyp ...

  7. html仿微信滑动删除,使用Vue实现移动端左滑删除效果附源码

    左滑删除在移动端是很常见的一种操作,常见于删除购物车中的商品,删除收藏夹中文章等等场景.我们只需要手指按住要删除的对象,然后轻轻向左滑动,便会出现删除按钮,然后点击删除按钮即可删除对象. 点击下载源码 ...

  8. 微信小程序独家秘笈之左滑删除

    代码地址如下: http://www.demodashi.com/demo/14056.html 一.前期准备工作 软件环境:微信开发者工具 官方下载地址:https://mp.weixin.qq.c ...

  9. 微信小程序实现左滑删除

    wxml代码: <view class="global"><movable-area class="area"><movable- ...

最新文章

  1. puppet 深入讲解
  2. websphere 内存溢出处理
  3. C++之Lambda表达式
  4. boost::spirit模块将 QString 数据类型用作 Qi 属性的测试程序
  5. Dalvik/ART(ANDROID)中的多线程机制(4)
  6. Ant步步为营(4)ant启动tomcat
  7. c#中使用openssl
  8. 框架选择的原因及其说明
  9. java如何调用同目录下的文件_文件目录发生了增删改操作?Java如何实时监控?...
  10. linux fedora frebsd centos linux as 安装出错
  11. wordpress如何在多说评论框中设置圆形旋转头像?
  12. Java 编程之美:并发编程基础晋级篇
  13. B站视频缓存 音频和视频批量合并
  14. java excel添加公式_Java 添加、读取 Excel 公式
  15. charles+安卓模拟器采集豆果美食app
  16. 计算功耗设备待机时间!
  17. 英语原来这么有趣之数词,月份的使用
  18. Linux系列 使用vi文本编辑器
  19. 使用Pyecharts进行奥运会可视化分析!
  20. php打印99乘法表加粗,PHP基础循环语句之打印99乘法表

热门文章

  1. Postfix 邮件服务 - 基础服务
  2. Siamese Neural Networks for One-shot Image Recognition
  3. python字符串之join
  4. 易助工资总额管控上市说明
  5. 15. 3Sum_左右开工,遍历找出符合目标的数字
  6. ios使用支付宝进行支付,注意事项 集成支付宝钱包支付iOS SDK的方法与经验。...
  7. 子图同构算法——Ullmann算法(1)不包含refine procedure的简单穷举算法。
  8. [轉]VS2010 SP1 TFS 2010 SP1 官方正式版下载
  9. android 取消点击GridView的时候出现的那个黄色背景
  10. 初学tornado之MVC版helloworld