android滑动删除编辑,Android实现ListView左右滑动删除和编辑

本文介绍如何在Android中为ListView添加左右滑动删除和编辑的功能。通过监听触摸事件,判断滑动方向并移动View,最后通过回调通知用户滑动操作。代码示例展示了自定义ListView的实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

有时候,为了实现项目中的需求,完成设计好的用户交互体验,不的不把这些View重新改造成自己想要的效果。

Android原生的ListView是不支持左右滑动的,但是看到微信电话本上,联系人可以左右滑动进行操作的,就通过自己的设想和思路,并加以实现了。

思路:1.获取到手指放到屏幕时的x,y位置,并判断点击的处于ListView的那个position。

2.判断滑动的方向,如果是上下方向,touch事件就交给ListView处理;如果是左右方向,就禁止ListView进行滑动。

3.根据手指的移动,来移动选中的View。

4.滑动结束后,把View归位。

5.通过传入的监听器,告诉用户是左滑动还是右滑动。

效果图:

4eb892f7d8fe01030de70ceb926990a0.png

0229cdd82cbcf32226ba06ed8dd36edd.png

重新的ListView的代码:

package com.example.wz.view;

import android.annotation.SuppressLint;

import android.content.Context;

import android.os.Handler;

import android.util.AttributeSet;

import android.view.MotionEvent;

import android.view.VelocityTracker;

import android.view.View;

import android.view.ViewConfiguration;

import android.view.WindowManager;

import android.widget.AdapterView;

import android.widget.ListView;

import android.widget.TextView;

import com.example.wz.R;

import com.example.wz.util.MyLog;

import com.example.wz.util.OpenLooper;

import com.example.wz.util.OpenLooper.LoopCallback;

public class MyListView extends ListView {

public MyLog log = new MyLog(this, true);

public float screenWidth;

public int mTouchSlop;

public float density;

public MyListView(Context context) {

super(context);

}

public MyListView(Context context, AttributeSet attrs) {

this(context, attrs, 0);

}

public float transleteSpeed = 2f;

public OpenLooper openLooper = null;

public LoopCallback loopCallback = null;

@SuppressWarnings("deprecation")

public MyListView(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);

this.screenWidth = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getWidth();

this.mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();

this.density = context.getResources().getDisplayMetrics().density;

this.openLooper = new OpenLooper();

this.openLooper.createOpenLooper();

this.loopCallback = new ListLoopCallback(this.openLooper);

this.openLooper.loopCallback = this.loopCallback;

}

public class BodyStatus {

public int None = 0, Down = 1, Move = 2, Up = 3, Homing = 4;

int state = None;

}

public BodyStatus bodyStatus = new BodyStatus();

public class RemoveDirection {

public int None = 0, Left = 1, Right = 2, Homing_Left = 3, Homing_Right = 4;

public int state = None;

}

public RemoveDirection removeDirection = new RemoveDirection();

public class ListLoopCallback extends LoopCallback {

public ListLoopCallback(OpenLooper openLooper) {

openLooper.super();

}

@Override

public void loop(double ellapsedMillis) {

if (bodyStatus.state == bodyStatus.Homing) {

goHoming((float) ellapsedMillis);

}

}

}

public void goHoming(float delta) {

float distance = (float) delta * transleteSpeed;

if (removeDirection.state == removeDirection.Left) {

float currentX = itemView.getScrollX() + distance;

if (currentX > screenWidth) {

distance = distance - (currentX - screenWidth);

}

itemView.scrollBy((int) (distance), itemView.getScrollY());

if (itemView.getScrollX() > screenWidth / 2 + 40 * screenWidth / 1080) {

t2.setTranslationX(itemView.getScrollX() - screenWidth / 2 - 40 * 3f);

} else {

t2.setTranslationX(40 * 3f);

}

} else if (removeDirection.state == removeDirection.Right) {

float currentX = itemView.getScrollX() - distance;

if (currentX < -screenWidth) {

distance = distance - (Math.abs(currentX) - screenWidth);

}

itemView.scrollBy((int) (-distance), itemView.getScrollY());

if (itemView.getScrollX() < -(screenWidth / 2 + 40 * 3f * 2)) {

t1.setTranslationX(-(Math.abs(itemView.getScrollX()) - screenWidth / 2 - 40 * 3f));

} else {

t1.setTranslationX(-40 * 3f);

}

} else if (removeDirection.state == removeDirection.Homing_Left) {

float currentX = itemView.getScrollX() - distance;

if (currentX < 0) {

distance = distance - (Math.abs(currentX));

}

itemView.scrollBy((int) (-distance), itemView.getScrollY());

} else if (removeDirection.state == removeDirection.Homing_Right) {

float currentX = itemView.getScrollX() + distance;

if (currentX > 0) {

distance = distance - currentX;

}

itemView.scrollBy((int) (distance), itemView.getScrollY());

}

if (itemView.getScrollX() == 0 || itemView.getScrollX() >= screenWidth || itemView.getScrollX() <= -screenWidth) {

openLooper.stop();

if (itemView.getScrollX() >= screenWidth) {

mRemoveListener.removeItem(removeDirection, position);

} else if (itemView.getScrollX() <= -screenWidth) {

mRemoveListener.removeItem(removeDirection, position);

}

new Handler().postDelayed(new Runnable() {

@Override

public void run() {

itemView.scrollTo(0, itemView.getScrollY());

bodyStatus.state = bodyStatus.None;

}

}, 300);

}

}

public int touch_down_x;

public int touch_down_y;

public View itemView;

public TextView t1;

public TextView t2;

public int SNAP_VELOCITY = 800;

public int position;

@Override

public boolean dispatchTouchEvent(MotionEvent event) {

int action = event.getAction();

if (action == MotionEvent.ACTION_DOWN) {

// addVelocityTracker(event);

if (bodyStatus.state != bodyStatus.None) {

return super.dispatchTouchEvent(event);

}

this.touch_down_x = (int) event.getX();

this.touch_down_y = (int) event.getY();

position = pointToPosition(touch_down_x, touch_down_y);

if (position == AdapterView.INVALID_POSITION) {

return super.dispatchTouchEvent(event);

}

itemView = getChildAt(position - getFirstVisiblePosition());

t2 = (TextView) itemView.findViewById(R.id.t2);

t1 = (TextView) itemView.findViewById(R.id.t1);

} else if (action == MotionEvent.ACTION_MOVE) {

if (Math.abs(getScrollVelocity()) > SNAP_VELOCITY || (Math.abs(event.getX() - touch_down_x) > mTouchSlop && Math.abs(event.getY() - touch_down_y) < mTouchSlop)) {

isSlide = true;

}

} else if (action == MotionEvent.ACTION_UP) {

int velocityX = getScrollVelocity();

if (Math.abs(velocityX) > SNAP_VELOCITY) {

if (velocityX > SNAP_VELOCITY) {

bodyStatus.state = bodyStatus.Homing;

removeDirection.state = removeDirection.Right;

openLooper.start();

} else {

bodyStatus.state = bodyStatus.Homing;

removeDirection.state = removeDirection.Left;

openLooper.start();

}

} else {

if (itemView.getScrollX() >= screenWidth / 2) {

bodyStatus.state = bodyStatus.Homing;

removeDirection.state = removeDirection.Left;

openLooper.start();

} else if (itemView.getScrollX() <= -screenWidth / 2) {

bodyStatus.state = bodyStatus.Homing;

removeDirection.state = removeDirection.Right;

openLooper.start();

} else {

if (itemView.getScrollX() < 0) {

removeDirection.state = removeDirection.Homing_Right;

} else {

removeDirection.state = removeDirection.Homing_Left;

}

bodyStatus.state = bodyStatus.Homing;

openLooper.start();

}

}

recycleVelocityTracker();

isSlide = false;

}

return super.dispatchTouchEvent(event);

}

public boolean isSlide = false;

@SuppressLint("Recycle")

@Override

public boolean onTouchEvent(MotionEvent event) {

if (isSlide && position != AdapterView.INVALID_POSITION) {

requestDisallowInterceptTouchEvent(true);

addVelocityTracker(event);

int x = (int) event.getX();

int action = event.getAction();

if (action == MotionEvent.ACTION_DOWN) {

} else if (action == MotionEvent.ACTION_MOVE) {

MotionEvent cancelEvent = MotionEvent.obtain(event);

cancelEvent.setAction(MotionEvent.ACTION_CANCEL | (event.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT));

onTouchEvent(cancelEvent);

int deltaX = touch_down_x - x;

touch_down_x = x;

if (itemView.getScrollX() > screenWidth / 2 + 40 * 3f * 2) {

t2.setTranslationX(itemView.getScrollX() - screenWidth / 2 - 40 * 3f);

} else {

t2.setTranslationX(40 * 3f);

}

if (itemView.getScrollX() < -(screenWidth / 2 + 40 * 3f * 2)) {

t1.setTranslationX(-(Math.abs(itemView.getScrollX()) - screenWidth / 2 - 40 * 3f));

} else {

t1.setTranslationX(-40 * 3f);

}

itemView.scrollBy(deltaX, 0);

return true;

}

}

return super.onTouchEvent(event);

}

public RemoveListener mRemoveListener;

public void setRemoveListener(RemoveListener removeListener) {

this.mRemoveListener = removeListener;

}

public interface RemoveListener {

public void removeItem(RemoveDirection direction, int position);

}

public VelocityTracker velocityTracker;

public void addVelocityTracker(MotionEvent event) {

if (velocityTracker == null) {

velocityTracker = VelocityTracker.obtain();

}

velocityTracker.addMovement(event);

}

public int getScrollVelocity() {

if (velocityTracker != null) {

velocityTracker.computeCurrentVelocity(1000);

int velocity = (int) velocityTracker.getXVelocity();

return velocity;

}

return 0;

}

public void recycleVelocityTracker() {

if (velocityTracker != null) {

velocityTracker.recycle();

velocityTracker = null;

}

}

}

测试ListView的Activity代码:

package com.example.wz;

import java.util.ArrayList;

import android.app.Activity;

import android.os.Bundle;

import android.util.DisplayMetrics;

import android.util.Log;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.BaseAdapter;

import android.widget.TextView;

import com.example.wz.view.MyListView;

import com.example.wz.view.MyListView.RemoveDirection;

import com.example.wz.view.MyListView.RemoveListener;

public class TestListActivity extends Activity {

LayoutInflater mInflater;

@Override

protected void onCreate(Bundle savedInstanceState) {

displayMetrics = new DisplayMetrics();

this.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_testlist);

mInflater = getLayoutInflater();

listView = (MyListView) findViewById(R.id.slideCutListView);

showAddressDialog();

}

public DisplayMetrics displayMetrics;

MyListView listView;

public ArrayList items;

public void showAddressDialog() {

items = new ArrayList() {

{

add("item...1");

add("item...2");

add("item...3");

add("item...4");

add("item...5");

add("item...6");

add("item...7");

add("item...8");

add("item...9");

add("item...10");

add("item...11");

add("item...12");

add("item...13");

add("item...14");

add("item...15");

add("item...16");

add("item...17");

add("item...18");

add("item...19");

add("item...20");

}

};

NearbyRelationAdapter nearbyRelationAdapter = new NearbyRelationAdapter();

listView.setAdapter(nearbyRelationAdapter);

listView.setRemoveListener(new RemoveListener() {

@Override

public void removeItem(RemoveDirection direction, int position) {

if (direction.state == direction.Left) {

Log.e("A", "left" + "-" + position);

} else if (direction.state == direction.Right) {

Log.e("A", "right" + "-" + position);

}

}

});

}

public class NearbyRelationAdapter extends BaseAdapter {

@Override

public int getCount() {

return items.size();

}

@Override

public Object getItem(int posotion) {

return items.get(posotion);

}

@Override

public long getItemId(int posotion) {

return posotion;

}

@Override

public View getView(int position, View convertView, ViewGroup parent) {

Holder holder = null;

if (convertView == null) {

holder = new Holder();

convertView = mInflater.inflate(R.layout.view_menu_item1, null);

holder.title = (TextView) convertView.findViewById(R.id.title);

holder.o1 = convertView.findViewById(R.id.o1);

holder.o1.setTranslationX(-displayMetrics.widthPixels);

holder.o2 = convertView.findViewById(R.id.o2);

holder.o2.setTranslationX(displayMetrics.widthPixels);

convertView.setTag(holder);

} else {

holder = (Holder) convertView.getTag();

}

holder.title.setText(items.get(position));

convertView.scrollTo(0, convertView.getScrollY());

return convertView;

}

class Holder {

TextView title;

View o1, o2;

}

}

}

ListView布局文件:

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="@android:color/darker_gray" >

android:id="@+id/slideCutListView"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:cacheColorHint="@android:color/transparent"

android:listSelector="@android:color/transparent" >

android:layout_width="1dp"

android:layout_height="match_parent"

android:layout_centerHorizontal="true"

android:background="#0099cd" />

ListView 的Item布局:

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:background="#fff" >

android:id="@+id/o1"

android:layout_width="match_parent"

android:layout_height="60dp"

android:background="#ff0000" >

android:id="@+id/t1"

android:layout_width="80dp"

android:layout_height="wrap_content"

android:layout_alignParentRight="true"

android:layout_centerVertical="true"

android:gravity="center"

android:padding="10dp"

android:text="删除"

android:textColor="#99000000"

android:textSize="18sp" />

android:id="@+id/o2"

android:layout_width="match_parent"

android:layout_height="60dp"

android:background="#660099cd" >

android:id="@+id/t2"

android:layout_width="80dp"

android:layout_height="wrap_content"

android:layout_alignParentLeft="true"

android:layout_centerVertical="true"

android:gravity="center"

android:padding="10dp"

android:text="编辑"

android:textColor="#99000000"

android:textSize="18sp" />

android:id="@+id/r1"

android:layout_width="match_parent"

android:layout_height="60dp"

android:background="#fff" >

android:id="@+id/title"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_centerVertical="true"

android:gravity="center_vertical"

android:textColor="#99000000"

android:textSize="18sp" />

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值