当前位置: 移动技术网 > IT编程>移动开发>Android > Android仿腾讯QQ实现滑动删除 附源码下载

Android仿腾讯QQ实现滑动删除 附源码下载

2019年07月24日  | 移动技术网IT编程  | 我要评论

平顶山学院软件学院,东莞地铁2号线,杨俊苹

看了很多大神们的文章,感觉受益良多,也非常欣赏大家的分享态度,所以决定开始写blog,给大家分享自己的心得。

先看看效果图:

本来准备在listview的每个item的布局上设置一个隐藏的button,当滑动的时候显示。但是因为每次只要存在一个button,发现每个item上的button相互间不好控制。所以决定继承listview然后结合popupwindow。

首先是布局文件:

delete_btn.xml:这里只需要一个button

<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:orientation="vertical" >
  <button 
  android:id="@+id/id_item_btn"
  android:layout_width="60dp"
  android:singleline="true"
  android:layout_height="wrap_content"
  android:text="删除"
  android:background="@drawable/d_delete_btn"
  android:textcolor="#ffffff"
  android:paddingleft="15dp"
  android:paddingright="15dp"
  android:layout_alignparentright="true"
  android:layout_centervertical="true"
  android:layout_marginright="15dp"
  />
</linearlayout> 

主布局文件:activity_main.xml,listview的每个item的样式直接使用了系统的android.r.layout.simple_list_item_1

<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" >

 <com.example.listviewitemslidedeletebtnshow.qqlistview
  android:id="@+id/id_listview"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content" >
 </com.example.listviewitemslidedeletebtnshow.qqlistview>

</relativelayout>

接下来看看qqlistview的实现:

package com.example.listviewitemslidedeletebtnshow;

import android.content.context;
import android.util.attributeset;
import android.view.gravity;
import android.view.layoutinflater;
import android.view.motionevent;
import android.view.view;
import android.view.viewconfiguration;
import android.widget.button;
import android.widget.linearlayout;
import android.widget.listview;
import android.widget.popupwindow;

public class qqlistview extends listview
{

 private static final string tag = "qqlistview";

 // private static final int velocity_sanp = 200;
 // private velocitytracker mvelocitytracker;
 /**
 * 用户滑动的最小距离
 */
 private int touchslop;

 /**
 * 是否响应滑动
 */
 private boolean issliding;

 /**
 * 手指按下时的x坐标
 */
 private int xdown;
 /**
 * 手指按下时的y坐标
 */
 private int ydown;
 /**
 * 手指移动时的x坐标
 */
 private int xmove;
 /**
 * 手指移动时的y坐标
 */
 private int ymove;

 private layoutinflater minflater;

 private popupwindow mpopupwindow;
 private int mpopupwindowheight;
 private int mpopupwindowwidth;

 private button mdelbtn;
 /**
 * 为删除按钮提供一个回调接口
 */
 private delbuttonclicklistener mlistener;

 /**
 * 当前手指触摸的view
 */
 private view mcurrentview;

 /**
 * 当前手指触摸的位置
 */
 private int mcurrentviewpos;

 /**
 * 必要的一些初始化
 * 
 * @param context
 * @param attrs
 */
 public qqlistview(context context, attributeset attrs)
 {
 super(context, attrs);

 minflater = layoutinflater.from(context);
 touchslop = viewconfiguration.get(context).getscaledtouchslop();

 view view = minflater.inflate(r.layout.delete_btn, null);
 mdelbtn = (button) view.findviewbyid(r.id.id_item_btn);
 mpopupwindow = new popupwindow(view, linearlayout.layoutparams.wrap_content,
 linearlayout.layoutparams.wrap_content);
 /**
 * 先调用下measure,否则拿不到宽和高
 */
 mpopupwindow.getcontentview().measure(0, 0);
 mpopupwindowheight = mpopupwindow.getcontentview().getmeasuredheight();
 mpopupwindowwidth = mpopupwindow.getcontentview().getmeasuredwidth();
 }

 @override
 public boolean dispatchtouchevent(motionevent ev)
 {
 int action = ev.getaction();
 int x = (int) ev.getx();
 int y = (int) ev.gety();
 switch (action)
 {

 case motionevent.action_down:
 xdown = x;
 ydown = y;
 /**
 * 如果当前popupwindow显示,则直接隐藏,然后屏蔽listview的touch事件的下传
 */
 if (mpopupwindow.isshowing())
 {
 dismisspopwindow();
 return false;
 }
 // 获得当前手指按下时的item的位置
 mcurrentviewpos = pointtoposition(xdown, ydown);
 // 获得当前手指按下时的item
 view view = getchildat(mcurrentviewpos - getfirstvisibleposition());
 mcurrentview = view;
 break;
 case motionevent.action_move:
 xmove = x;
 ymove = y;
 int dx = xmove - xdown;
 int dy = ymove - ydown;
 /**
 * 判断是否是从右到左的滑动
 */
 if (xmove < xdown && math.abs(dx) > touchslop && math.abs(dy) < touchslop)
 {
 // log.e(tag, "touchslop = " + touchslop + " , dx = " + dx +
 // " , dy = " + dy);
 issliding = true;
 }
 break;
 }
 return super.dispatchtouchevent(ev);
 }

 @override
 public boolean ontouchevent(motionevent ev)
 {
 int action = ev.getaction();
 /**
 * 如果是从右到左的滑动才相应
 */
 if (issliding)
 {
 switch (action)
 {
 case motionevent.action_move:

 int[] location = new int[2];
 // 获得当前item的位置x与y
 mcurrentview.getlocationonscreen(location);
 // 设置popupwindow的动画
 mpopupwindow.setanimationstyle(r.style.popwindow_delete_btn_anim_style);
 mpopupwindow.update();
 mpopupwindow.showatlocation(mcurrentview, gravity.left | gravity.top,
  location[0] + mcurrentview.getwidth(), location[1] + mcurrentview.getheight() / 2
  - mpopupwindowheight / 2);
 // 设置删除按钮的回调
 mdelbtn.setonclicklistener(new onclicklistener()
 {
  @override
  public void onclick(view v)
  {
  if (mlistener != null)
  {
  mlistener.clickhappend(mcurrentviewpos);
  mpopupwindow.dismiss();
  }
  }
 });
 // log.e(tag, "mpopupwindow.getheight()=" + mpopupwindowheight);

 break;
 case motionevent.action_up:
 issliding = false;

 }
 // 相应滑动期间屏幕itemclick事件,避免发生冲突
 return true;
 }

 return super.ontouchevent(ev);
 }

 /**
 * 隐藏popupwindow
 */
 private void dismisspopwindow()
 {
 if (mpopupwindow != null && mpopupwindow.isshowing())
 {
 mpopupwindow.dismiss();
 }
 }

 public void setdelbuttonclicklistener(delbuttonclicklistener listener)
 {
 mlistener = listener;
 }

 interface delbuttonclicklistener
 {
 public void clickhappend(int position);
 }

}

代码注释写得很详细,简单说一下,在dispatchtouchevent中设置当前是否响应用户滑动,然后在ontouchevent中判断是否响应,如果响应则popupwindow以动画的形式展示出来。当然屏幕上如果存在popupwindow则屏幕listview的滚动与item的点击,以及从右到左滑动时屏幕item的click事件。

接下来是mainactivity.java,这里代码很简单不做介绍了。

package com.example.listviewitemslidedeletebtnshow;

import java.util.arraylist;
import java.util.arrays;
import java.util.list;

import android.app.activity;
import android.os.bundle;
import android.view.view;
import android.widget.adapterview;
import android.widget.adapterview.onitemclicklistener;
import android.widget.arrayadapter;
import android.widget.toast;

import com.example.listviewitemslidedeletebtnshow.qqlistview.delbuttonclicklistener;

public class mainactivity extends activity
{
 private qqlistview mlistview;
 private arrayadapter<string> madapter;
 private list<string> mdatas;

 @override
 protected void oncreate(bundle savedinstancestate)
 {
 super.oncreate(savedinstancestate);
 setcontentview(r.layout.activity_main);

 mlistview = (qqlistview) findviewbyid(r.id.id_listview);
 // 不要直接arrays.aslist
 mdatas = new arraylist<string>(arrays.aslist("helloworld", "welcome", "java", "android", "servlet", "struts",
 "hibernate", "spring", "html5", "javascript", "lucene"));
 madapter = new arrayadapter<string>(this, android.r.layout.simple_list_item_1, mdatas);
 mlistview.setadapter(madapter);

 mlistview.setdelbuttonclicklistener(new delbuttonclicklistener()
 {
 @override
 public void clickhappend(final int position)
 {
 toast.maketext(mainactivity.this, position + " : " + madapter.getitem(position), 1).show();
 madapter.remove(madapter.getitem(position));
 }
 });

 mlistview.setonitemclicklistener(new onitemclicklistener()
 {
 @override
 public void onitemclick(adapterview<?> parent, view view, int position, long id)
 {
 toast.maketext(mainactivity.this, position + " : " + madapter.getitem(position), 1).show();
 }
 });
 }
}

楼主使用asm.jar以及gifcamera截的gif,由于button的动画很短感觉截图效果很卡不流畅,大家有什么好的截图,还望推荐。

有兴趣的还是下载源码看看效果,

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网