首页 > 系统 > Android > 正文

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

2019-12-12 06:25:14
字体:
来源:转载
供稿:网友

有时候,为了实现项目中的需求,完成设计好的用户交互体验,不的不把这些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>

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

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

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

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表