Android实现ListView左右滑动删除和编辑
程序员文章站
2024-02-29 22:09:04
有时候,为了实现项目中的需求,完成设计好的用户交互体验,不的不把这些view重新改造成自己想要的效果。
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>
代码中用到的其他的类,在上一篇文章中有:
转载来自:
以上就是本文的全部内容,希望对大家的学习有所帮助。
上一篇: Android 高仿斗鱼滑动验证码
下一篇: PHP基于GD库的图像处理方法小结
推荐阅读
-
Android实现ListView左右滑动删除和编辑
-
Android App中ListView仿QQ实现滑动删除效果的要点解析
-
详解Android中实现ListView左右滑动删除条目的方法
-
Android ListView实现上拉加载下拉刷新和滑动删除功能
-
详解Android中实现ListView左右滑动删除条目的方法
-
Android ListView实现上拉加载下拉刷新和滑动删除功能
-
Android开发在RecyclerView上面实现"拖放"和"滑动删除"-2
-
Android一步步带你在RecyclerView上面实现"拖放"和"滑动删除"功能
-
Android开发在RecyclerView上面实现"拖放"和"滑动删除"-2
-
Android中判断listview是否滑动到顶部和底部的实现方法