android listview左滑删除

释放双眼,带上耳机,听听看~!

之前,自己使用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文章

Android EditText获取焦点和失去焦点监听事件

2020-3-12 12:12:06

Android文章

android 字符串的拆分

2020-3-12 13:34:42

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
有新消息 消息中心
搜索