Android条目拖拽删除功能实例代码

项目中需求,要做条目条目拖拽删除效果,实际效果和QQ消息删除一样,侧滑有制定和删除。

效果图

第一步效果图

1.0自定义控件 SwipeLayout 继承FrameLayout重写里面三个构造方法,分别调用initView().

2.0在布局中使用自定义控件

3.0在initView()方法中,创建拖拽辅辅助工具 ViewDragHelper()

该方法需要传入回调 MyCallBack()

4.0,创建MyCallBack()回调,继承ViewDragHelper.Callback

在回调中 覆盖tryCaptureView方法,返回true 允许child被拖拽,被 覆盖clampViewPositionHorizontal 返回left系统提供拖拽位置

5.0 onInterceptTouchEvent 返回:让ViewDragHelper判断是否需要拦截事件

6.0  onTouchEvent 返回true 并且让ViewDragHelper分析事件

具体代码:

布局:

<cn.itheima.swipelayout.SwipeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:id="@+id/activity_main"
 android:layout_width="match_parent"
 android:layout_height="wrap_content">
 <!--正文部分-->
 <RelativeLayout
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:background="#fff"
  android:orientation="horizontal">
  <TextView
   android:id="@+id/item_tv_name"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:padding="10dp"
   android:text="张三"
   android:textSize="20sp" />
 </RelativeLayout>
 <!--按钮部分-->
 <LinearLayout
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:orientation="horizontal">
  <TextView
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:background="#888888"
   android:padding="10dp"
   android:text="呼叫"
   android:textSize="20sp" />
  <TextView
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:background="#f00"
   android:padding="10dp"
   android:text="删除"
   android:textSize="20sp" />
 </LinearLayout>
</cn.itheima.swipelayout.SwipeLayout> 

SwipeLayout 代码:

public class SwipeLayout extends FrameLayout {
 private ViewDragHelper mDragHelper;
 public SwipeLayout(Context context) {
  super(context);
  initView();
 }
 public SwipeLayout(Context context, AttributeSet attrs) {
  super(context, attrs);
  initView();
 }
 public SwipeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  initView();
 }
 private void initView() {
  mDragHelper = ViewDragHelper.create(this,new MyCallBack());
 }
 // 让ViewDragHelper就是拖拽辅助工具 返回true 则表示要拦截触摸事件
 @Override
 public boolean onInterceptTouchEvent(MotionEvent ev) {
  //让拖拽辅助工具判断是否需要拦截 事件
  return mDragHelper.shouldInterceptTouchEvent(ev);
 }
 @Override
 public boolean onTouchEvent(MotionEvent event) {
  //让拖拽辅助工具分析事件 分析用户手势
  mDragHelper.processTouchEvent(event);
  return true;
 }
 private class MyCallBack extends ViewDragHelper.Callback{
  /**
   * 如果返回 true 则表示 child 允许被拖拽
   */
  @Override
  public boolean tryCaptureView(View child, int pointerId) {
   return true;
  }
  /**
   * 固定被拖拽控件的水平位置,
   * 参数里的 left 是系统推荐移动到的位置,可以进行修正,
   * 方法返回的值就是 child 将要移动到的位置
   */
  @Override
  public int clampViewPositionHorizontal(View child, int left, int dx) {
   return left;
  }
 }
} 

第二步:

1.0创建onFinishInflate方法获取子控件,并且判断健壮性

/*
  控件初始化时执行,可以用于获取子控件
  */
 @Override
 protected void onFinishInflate() {
  // 健壮性检查
  if (getChildCount()!=2){
   throw new RuntimeException("SwipeLayout 必须存放两个子控件");
  }
  if (!(getChildAt(0) instanceof ViewGroup)||!(getChildAt(1) instanceof ViewGroup)){
   throw new RuntimeException("SwipeLayout 的子控件必须是 ViewGroup");
  }
  mContent = (ViewGroup) getChildAt(0);
  mDeletePanel = (ViewGroup) getChildAt(1);
 } 

2.0创建onSizeChanged方法,在控件大小改变的时候调用,获取控件的宽高,和删除的面板的最大移动范围

/**
  * 当控件大小改变的时候调用这个方法
  */
 @Override
 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  super.onSizeChanged(w, h, oldw, oldh);
  int mWith = w;
  int mHeigth = h;
  //界面创建过程中,不能使用 getWidth 方法
  int mRang = mDeletePanel.getMeasuredWidth();
 } 

3.0在onLayout中指定侧拉面板的位置

//指定侧拉面板的位置
 @Override
 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
  super.onLayout(changed, left, top, right, bottom);
  mDeletePanel.layout(mWith,0,mWith+mRang,mHeigth);
 } 

4.0在onViewPositionChanged方法中实现联动效果

/**
  * 当被拖拽的控件已经移动过后,会调用这个方法,可以用于处理控件间的联动效果
  * @left 被拖拽控件的真实移动位置
  * @dx 被拖拽控件的真实偏移大小
  */
  @Override
  public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
   if (changedView==mContent){
    // 移动正文的同时也要移动侧栏
    mDeletePanel.offsetLeftAndRight(dx);
   }else{
    mContent.offsetLeftAndRight(dx);
   }
  } 

5.0在 clampViewPositionHorizontal方法中  固定被拖拽控件的水平位置,

/**
   * 固定被拖拽控件的水平位置,
   * 参数里的 left 是系统推荐移动到的位置,可以进行修正,
   * 方法返回的值就是 child 将要移动到的位置
   */
  @Override
  public int clampViewPositionHorizontal(View child, int left, int dx) {
   if (child==mContent){
    if (left>0){
     left=0;
    }else if (left<-mRang){
      left=-mRang;
    }
   }else{
    if (left>mWith){//mWith是屏幕的宽度
     left=mWith;
    }else if (left<mWith-mRang){
     left=mWith-mRang;
    }
   }
   return left;
  } 

第三步:

效果图

1.0onViewReleased中根据来开局里面,判断是否打开还是关闭

2.0  在  moveContent中第一次滑动

3.0computeScroll中,继续滑动,直到滑动到指定的位置

4.0注意在onViewPositionChanged中手动刷新界面,调用invalidate方法

如果不手动刷新界面,效果展示不出来

/**
  * 当用户松手时执行
  * @xvel 松手时在 X 方向的移动速度,如果为 正数 则说明是向右移动,如果是 负数 则说明是向左移动,如果为零,说明是静止状态
  */
  @Override
  public void onViewReleased(View releasedChild, float xvel, float yvel) {
   if (xvel>0){
    //向右移动
    close();
   }else if (xvel<0){
    //向左移动
    opend();
   }else if (xvel>-mRang/2){// 静止状态
    close();// 展开不到一半,关闭面板
   }else{
    opend();
   }
  }
 }
 /**
 * 打开面板
 */
 private void opend() {
  int left=-mRang;
  moveContent(left);
 }
 /**
 * 关闭面板
 */
 private void close() {
  int left=0;
  moveContent(left);
 }
 private void moveContent(int left) {
  // 开启平滑滚动,如果返回 true 则说明要继续刷新界面,保持滚动
  if(mDragHelper.smoothSlideViewTo(mContent,left,0)){
   invalidate();
  }
 }
 @Override
 public void computeScroll() {
  // 继续平滑滚动,如果返回 true 则说明要继续刷新界面,保持滚动
  if (mDragHelper.continueSettling(true)){
   invalidate();
  }
 } 

第四步:

1.0现给ListView赋值   在这就省略

2.0在SwipeLayout中使用枚举记录面板的状态

 private enum Status{
 CLOSED,OPENED,DRAGING;
}
 private Status status = Status.CLOSED;
 public Status getStatus() {
  return status;
 } 

3.0// 记录上一个打开的面板。注意:一定要是 静态变量

private static SwipeLayout preSwipeLayout;

4.0在onViewPositionChanged中创建一个方法操作关闭面板

// 关闭上一个打开的面板
closePre();

5.0closePre()在这个方法中,判断当前面板的状态,并且根据状态,关闭上一个打开的面板

// 判断当前面板是否正在打开,如果正在打开则将上一个打开的面板关闭
 private void closePre() {
  //记录旧状态
  Status preStatus=status;
  if (mContent.getLeft()==-mRang){
   //记录当前面板已经打开
   status=status.OPENED;
  }else if (mContent.getLeft()==0){
   //当前面板已经关闭
   status=status.CLOSED;
  }else {
   status=status.DRAGING;
  }
  // 如果当前面板旧状态为关闭,并且新状态为拖拽,那么此时可以关闭之前打开的面板
  if (preStatus==status.CLOSED&&status==status.DRAGING){
   if (preSwipeLayout!=null&&preSwipeLayout!=this){
    // 关闭上一个面板
    preSwipeLayout.close();
   }
   // 将当前面板标记为 打开的面板
   preSwipeLayout=this;
  }
 } 

总结

以上所述是小编给大家介绍的Android条目拖拽删除功能实例代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • Android中RecyclerView实现滑动删除与拖拽功能

    前言 从Android 5.0开始,谷歌推出了新的控件RecyclerView,相对于早它之前的ListView,优点多多,功能强大,也给我们的开发着提供了极大的便利,今天自己学习一下RecyclerView轻松实现滑动删除及拖拽的效果. 如下图. 相信研究过RecyclerView的同学,应该很清楚该怎么实现这样的效果,若是用ListView,这样的效果实现起来可能就有点麻烦,但是在强大的RecyclerView面前这样的的效果只需很少的代码,因为谷歌给我们提供了强大的工具类ItemTouch

  • android RecyclerView实现条目Item拖拽排序与滑动删除

    效果演示 需求和技术分析 RecyclerView Item拖拽排序::长按RecyclerView的Item或者触摸Item的某个按钮. RecyclerView Item滑动删除:RecyclerView Item滑动删除:RecyclerView的Item滑动删除. 实现方案与技术 利用ItemTouchHelper绑定RecyclerView.ItemTouchHelper.Callback来实现UI更新,并且实现动态控制是否开启拖拽功能和滑动删除功能. 实现步骤 继承抽象类ItemTo

  • android的RecyclerView实现拖拽排序和侧滑删除示例

    在平时开发应用的时候,经常会遇到列表排序.滑动删除的需求.如果列表效果采用的是 ListView 的话,需要经过自定义 View 才能实现效果:但是如果采用的是 RecyclerView 的话,系统 API 就已经为我们提供了相应的功能. 接下来,我们就来看一下怎么用系统 API 来实现排序和删除的效果. 创建 ItemTouchHelper 创建一个 ItemTouchHelper 对象,然后其调用 attachToRecyclerView 方法: RecyclerView recyclerV

  • Android仿QQ未读消息--红点拖拽删除【源代码】

    本Demo是一款仿qq未读消息拖拽删除的例子,继承RelativeLayout的WaterDrop实现了圆形图标功能.继承ImageView的CircleImageView圆形图片功能.效果非常不错.很适合有圆形设计的哥们.效果图片如下 CircleImageView核心代码 private void updateShaderMatrix() { float scale; float dx = 0; float dy = 0; mShaderMatrix.set(null); if (mBitm

  • android RecyclerView侧滑菜单,滑动删除,长按拖拽,下拉刷新上拉加载

    本文介绍的库中的侧滑效果借鉴自SwipeMenu,并对SipwMenu的源码做了修改与Bug修复,然后才开发出的SwipeRecyclerView. 需要说明的是,本库没有对RecyclerView做大的修改,只是ItemView的封装.看起来是对RecyclerView的修改,其实仅仅是为RecyclerView添加了使用的方法API而已. 本库已经更新了三个版本了,会一直维护下去,根据小伙伴的要求,以后也会添加一些其它功能. SwipeRecyclerView将完美解决这些问题: 以下功能全

  • android自定义view之模拟qq消息拖拽删除效果

    这个模拟功能的实现主要依靠了PATH和二阶贝塞尔曲线.首先上一张图来简单看一下: 这个模拟功能有以下几个特点: 在开始的时候点击圆以外的区域不会触发拖动事件 点击圆的时候可以拖拽,此时会有一个拉伸效果,连接大圆和小圆 拉伸到一定距离(自己设定)以后两个圆会断开,此时即使再拖拽进距离之内的时候也不会再产生已经断开的连接 在距离之内松手的时候会回弹会原位置,并伴有一个弹跳动画 介绍了这么多,看过我前边文章的朋友应该会有一个基本思路. 暴露接口 这个模拟功能共分为三部分,一个是那个小圆,固定的位置,一

  • Android recyclerview实现拖拽排序和侧滑删除

    Recyclerview现在基本已经替代Listview了,RecyclerView也越来越好用了  当我们有实现条目的拖拽排序和侧滑删除时  可以直接时候Recyclerview提供的API就可以直接实现了 先贴上主要代码 private void initveiw() { ArrayList<String> items = new ArrayList<>(Arrays.asList("itme1", "item2", "itme

  • Android条目拖拽删除功能实例代码

    项目中需求,要做条目条目拖拽删除效果,实际效果和QQ消息删除一样,侧滑有制定和删除. 效果图 第一步效果图 1.0自定义控件 SwipeLayout 继承FrameLayout重写里面三个构造方法,分别调用initView(). 2.0在布局中使用自定义控件 3.0在initView()方法中,创建拖拽辅辅助工具 ViewDragHelper() 该方法需要传入回调 MyCallBack() 4.0,创建MyCallBack()回调,继承ViewDragHelper.Callback 在回调中

  • js实现QQ邮箱邮件拖拽删除功能

    本文实例为大家分享了js实现QQ邮箱邮件拖拽删除的具体代码,供大家参考,具体内容如下 步骤分析: 根据数据结构生成HTML结构 全选和单选功能的实现,以及当其为选中状态时它的父级的颜色变化的 点击删除,删除结构同时删除数据 给每一个li绑定mousedown,tip显示,并且定位在鼠标位置 鼠标移动时,tip跟随,取消默认行为 碰撞检测是否拖到"已删除"项 鼠标松开.删除结构和数据 过程实现 HTML代码 <body> <div class="wrap&qu

  • 基于Vue2实现移动端图片上传、压缩、拖拽排序、拖拽删除功能

    用Vue2实现移动端图片上传.压缩.拖拽排序.拖拽删除功能 图片上传图片压缩拖拽排序.拖拽删除 之前在公司开发过一段时间的移动端H5页面,有个功能就是要上传图片+压缩.参考了一下网上的方法,外加自己摸索的过程,最终实现了这个功能.后面在家闲的时候又加多了个长按选中图片,并且可以拖拽排序.拖拽到指定位置删除的功能. github地址:代码地址 下面直接进入正题: 图片上传 图片上传用的是HTML的input标签实现的.核心就是把获取到的文件通过FileReader转换成图片,代码如下: <inpu

  • GRID拖拽行的实例代码

    ---------------------GRID拖拽行的实例代码  单行拖拽--------------------------------------- 复制代码 代码如下: //创建第一个GRIDvar firstGrid = new Ext.grid.GridPanel({ddGroup : 'secondGridDdGroup',//这里是第二个GRID的ddGroupstore       : firstGridStore,enableDragDrop : true,//True表示

  • Android 百度地图POI搜索功能实例代码

    在没介绍正文之前先给大家说下poi是什么意思. 由于工作的关系,经常在文件中会看到POI这三个字母的缩写,但是一直对POI的概念和含义没有很详细的去研究其背后代表的意思.今天下班之前,又看到了POI这三个字母,决定认认真真的搜索一些POI具体的含义. POI是英文的缩写,原来的单词是point of interest, 直译成中文就是兴趣点的意思.兴趣点这个词最早来自于导航地图厂商.地图厂商为了提供尽可能多的位置信息,花费了很大的精力去寻找诸如加油站,餐馆,酒店,景点等目的地,这些目的地其实都可

  • Java FTP上传下载删除功能实例代码

    在没给大家上完整代码之前先给大家说下注意点: FTP上传下载,容易出现乱码,记得转换 package com.yinhai.team.action; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; impo

  • Android模拟强制下线通知功能实例代码

    package com.itheima74.broadcastbestpractice; import android.content.Intent; import android.os.Bundle; import android.os.SystemClock; import android.support.v4.content.LocalBroadcastManager; import android.view.View; /** * 模拟强制下线通知 * 1.登录成功后10秒发送一条本地自

  • PHP ajax+jQuery 实现批量删除功能实例代码小结

    目录结构 piliangshan.php <?php require_once './db_conn.php'; $sql = "select * from user"; $result = mysqli_query($conn, $sql); ?> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>全选演示</tit

  • JS+CSS制作DIV层可(最小化/拖拽/排序)功能实现代码

    复制代码 代码如下: <HTML> <HEAD> <TITLE>JS+CSS制作的DIV层最小化和随意拖拽排序功能</TITLE> <style type="text/css"> body { margin:10px; } #dragHelper { position:absolute;/*重要*/ border:2px dashed #000000; background-color:#FFFFFF; filter: alp

  • android实现拖拽裁剪功能

    本文实例为大家分享了android拖拽框,裁剪出图片的具体代码,供大家参考,具体内容如下 import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.MotionEvent; i

随机推荐