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

作者:王虎的博客 时间:2022-06-19 22:47:37 

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

效果图

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

第一步效果图

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

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;
 }

第三步:

效果图

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

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条目拖拽删除功能实例代码网站的支持!

来源:http://blog.csdn.net/wangxiaohuhu1314/article/details/76973904

标签:android,拖拽删除
0
投稿

猜你喜欢

  • Android日期选择器实现年月日三级联动

    2022-12-13 03:35:59
  • Android使用Item Swipemenulistview实现仿QQ侧滑删除功能

    2021-08-16 19:47:35
  • Java经典面试题最全汇总208道(三)

    2023-11-15 23:30:42
  • Android资源文件与层次式导航超详细讲解

    2022-07-14 16:28:22
  • maven之packaging标签的使用

    2021-10-25 05:14:42
  • Java字符串常量池示例详解

    2021-10-11 10:55:02
  • Android实现拍照及图片裁剪(6.0以上权限处理及7.0以上文件管理)

    2022-05-19 09:18:14
  • Android OkHttp实现全局过期token自动刷新示例

    2023-01-24 10:31:57
  • Spring Security OAuth2 实现登录互踢的示例代码

    2023-09-04 19:09:28
  • Android如何在原生App中嵌入Flutter

    2022-03-11 17:06:06
  • Springboot处理配置CORS跨域请求时碰到的坑

    2023-12-20 11:40:45
  • mybatis 运行时加载自定义mapper文件方式

    2023-08-16 10:00:16
  • C#指针变量与unsafe的实现

    2022-09-05 09:34:10
  • Android Studio 通过登录功能介绍SQLite数据库的使用流程

    2023-09-22 00:37:29
  • 深度剖析java动态静态代理原理源码

    2021-10-25 08:10:31
  • 仅用5分钟极速入门Dubbo使用教程

    2022-08-08 12:08:55
  • Android使用GridView实现日历的简单功能

    2023-10-07 07:14:31
  • Java利用Jackson序列化实现数据脱敏详解

    2023-12-22 17:47:38
  • 教你安装配置Android Studio

    2023-07-09 03:26:17
  • C#中WebClient实现文件下载

    2022-10-11 18:04:57
  • asp之家 软件编程 m.aspxhome.com