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

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

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

思路:
1.获取到手指放到屏幕时的x,y位置,并判断点击的处于ListView的那个position。
2.判断滑动的方向,如果是上下方向,touch事件就交给ListView处理;如果是左右方向,就禁止ListView进行滑动。
3.根据手指的移动,来移动选中的View。
4.滑动结束后,把View归位。
5.通过传入的监听器,告诉用户是左滑动还是右滑动。

效果图:

重新的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<String> items; public void showAddressDialog() { items = new ArrayList<String>() { { 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布局文件:

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/darker_gray" > <com.example.wz.view.MyListView android:id="@+id/slideCutListView" android:layout_width="match_parent" android:layout_height="match_parent" android:cacheColorHint="@android:color/transparent" android:listSelector="@android:color/transparent" > </com.example.wz.view.MyListView> <TextView android:layout_width="1dp" android:layout_height="match_parent" android:layout_centerHorizontal="true" android:background="#0099cd" /> </RelativeLayout>

ListView 的Item布局:

<?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="wrap_content" android:background="#fff" > <RelativeLayout android:id="@+id/o1" android:layout_width="match_parent" android:layout_height="60dp" android:background="#ff0000" > <TextView 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" /> </RelativeLayout> <RelativeLayout android:id="@+id/o2" android:layout_width="match_parent" android:layout_height="60dp" android:background="#660099cd" > <TextView 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" /> </RelativeLayout> <RelativeLayout android:id="@+id/r1" android:layout_width="match_parent" android:layout_height="60dp" android:background="#fff" > <TextView 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" /> </RelativeLayout> </RelativeLayout>

代码中用到的其他的类,在上一篇文章中有: http://www.jb51.net/article/83822.htm

转载来自:http://blog.csdn.net/qxs965266509

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

时间: 2024-09-19 09:34:11

Android实现ListView左右滑动删除和编辑的相关文章

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

有时候,为了实现项目中的需求,完成设计好的用户交互体验,不的不把这些View重新改造成自己想要的效果. Android原生的ListView是不支持左右滑动的,但是看到微信电话本上,联系人可以左右滑动进行操作的,就通过自己的设想和思路,并加以实现了. 思路: 1.获取到手指放到屏幕时的x,y位置,并判断点击的处于ListView的那个position. 2.判断滑动的方向,如果是上下方向,touch事件就交给ListView处理:如果是左右方向,就禁止ListView进行滑动. 3.根据手指的移

Android 使用Scroller实现绚丽的ListView左右滑动删除Item效果

在上一篇文章中Android 带你从源码的角度解析Scroller的滚动实现原理从源码的角度介绍了Scroller的滚动实现原理,相信大家对Scroller的使用有一定的了解,这篇文章就给大家带来使用Scroller的小例子,来帮助大家更加熟悉的掌握Scroller的使用,掌握好了Scroller的使用我们就能实现很多滑动的效果.例如侧滑菜单,launcher,ListView的下拉刷新等等效果,我今天实现的是ListView的item的左右滑动删除item的效果,现在很多朋友看到这个效果应该是

Android 使用NineOldAndroids实现绚丽的ListView左右滑动删除Item效果

转载请注明本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/18311877),请尊重他人的辛勤劳动成果,谢谢! 今天还是给大家带来自定义控件的编写,自定义一个ListView的左右滑动删除Item的效果,这个效果之前已经实现过了,有兴趣的可以看下Android 使用Scroller实现绚丽的ListView左右滑动删除Item效果,之前使用的是滑动类Scroller来实现的,但是看了下通知栏的左右滑动删除效果,确实很

详解Android中实现ListView左右滑动删除条目的方法_Android

使用Scroller实现绚丽的ListView左右滑动删除Item效果这里来给大家带来使用Scroller的小例子,同时也能用来帮助初步解除的读者更加熟悉的掌握Scroller的使用,掌握好了Scroller的使用我们就能实现很多滑动的效果.例如侧滑菜单,launcher,ListView的下拉刷新等等效果,我今天实现的是ListView的item的左右滑动删除item的效果,现在很多朋友看到这个效果应该是在Android的通知栏下拉中看到这个滑动删除的效果吧,我看到这个效果是在我之前的三星手机

详解Android中实现ListView左右滑动删除条目的方法

使用Scroller实现绚丽的ListView左右滑动删除Item效果 这里来给大家带来使用Scroller的小例子,同时也能用来帮助初步解除的读者更加熟悉的掌握Scroller的使用,掌握好了Scroller的使用我们就能实现很多滑动的效果.例如侧滑菜单,launcher,ListView的下拉刷新等等效果,我今天实现的是ListView的item的左右滑动删除item的效果,现在很多朋友看到这个效果应该是在Android的通知栏下拉中看到这个滑动删除的效果吧,我看到这个效果是在我之前的三星手

安卓应用开发-android 添加listview无法滑动

问题描述 android 添加listview无法滑动 我在主页面设置了三个子页面,并且加上了手势控制,本来左右滑动切换页面没有问题,但是加上了listview之后就不能实现左右滑动的效果了,求解决! 解决方案 Android listView 滑动加载 解决方案二: 这个要牵扯到 事件分发 了,你就相当于listview将触摸事件消费了,所以外层viewpager得不到事件了,你要去学习哈android事件分发 解决方案三: 上下滑事件交给ListView,左右滑事件交给子页面,如楼上所说,你

Android仿微信列表滑动删除 如何实现滑动列表SwipeListView_Android

接上一篇,本篇主要讲如何实现滑动列表SwipeListView. 上篇完成了滑动控件SwipeItemView,这个控件是一个自定义的ViewGroup,作为列表的一个item,为列表提供一些方法让这个SwipeItemView能滑动其视图内容,同时滑动过程中会有顺滑的动画效果.而本篇讲的SwipeListView则是这个列表的具体实现了.当然啦,这个SwipeListView继承自ListView,为了实现我们需要的功能,重点就是重写ListView的onTouchEvent()以及onInt

Android仿微信列表滑动删除之可滑动控件(一)_Android

这次是列表滑动删除的第三波,仿微信的列表滑动删除.先上个效果图:   前面的文章里面说过开源框架SwipeListView的实现原理是每个列表item中包含上下两层view,普通状态下上层的view覆盖着下层的view,当用户滑开上层的view,下层的view就显示出来了.但是仔细观察微信列表的item,很明显并非这个实现方案,微信的item应该一个单层view,只不过这个item超出了所在的ListView的宽度,在用户滑动item的时候,item超出屏幕的view则会显示在屏幕之上,这种滑动

Android仿QQ列表滑动删除操作_Android

这篇山寨一个新版QQ的列表滑动删除,上篇有说到QQ的滑动删除,推测原理就是ListView本身每个item存在一个Button,只不过普通的状态下隐藏掉了,检测到向左的滑动事件的时候弹出隐藏的Button,不过再切换Button状态的时候会给Button一个出现和隐藏的动画.下面实现这个ListView.  首先有个难点就是通过ListView获取它某个item的View,对于ViewGroup,可以直接调用getChildAt()方法获取对应的子view,但是在ListView直接使用getC