android基于SwipeRefreshLayout实现类QQ的侧滑删除

作者:_独爱夜色 时间:2023-05-22 14:49:19 

前言

记得去年做一个聊天项目需要实现类似QQ的下拉刷新并且有侧滑删除的功能,在网上找了很久都没有QQ的完美,多多少少存在各种的问题,最后把下拉刷新的功能去掉后,只保留了侧滑删除的功能才找到个完美的。回去后和一朋友讨论,朋友找了以后说了一句,这种功能没有8K以上的是写不出来的(⊙﹏⊙)b。现在看来当时真的太天真了。而如今自己也没有8K还是尝试去写写,顺便当练练手。

还是效果图优先

android基于SwipeRefreshLayout实现类QQ的侧滑删除

效果图当中看不出来事件滑动的解决方案(或者是我不会如何录制手指在屏幕上滑动方向和点击,知道的大神请告诉下,谢谢)具体的可以去下方的GitHub上下载看。

还是先看怎么用

首先传送门地址 SwipeMenuRefreshView

此项目中引用了一个侧滑菜单的库具体的地址 AndroidSwipeLayout (这是一个非常强大的库可以上下左右的滑动展示,具体可以去其GitHub上了解)

引用


compile 'com.nero.ren:SwipeMenu:1.2.0'

布局文件


<ren.widget.refresh.SwipeMenuRefreshView
   android:id="@+id/refresh"
   android:layout_width="match_parent"
   android:layout_height="match_parent">

<ListView
     android:id="@+id/listview"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical" />
 </ren.widget.refresh.SwipeMenuRefreshView>

Item布局文件


<com.daimajia.swipe.SwipeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 android:layout_width="match_parent"
 android:layout_height="80dp"
 app:clickToClose="true">

//侧滑出来的布局
 <LinearLayout
   android:id="@+id/bottom_wrapper_2"
   android:layout_width="wrap_content"
   android:layout_height="80dp"
   android:tag="Bottom4">

<TextView
     android:id="@+id/top"
     android:layout_width="70dp"
     android:layout_height="match_parent"
     android:background="#cfcfcf"
     android:gravity="center"
     android:text="置顶" />

<TextView
     android:id="@+id/noread"
     android:layout_width="100dp"
     android:layout_height="match_parent"
     android:background="#ffa500"
     android:gravity="center"
     android:text="标记未读" />

<TextView
     android:id="@+id/delete"
     android:layout_width="70dp"
     android:layout_height="match_parent"
     android:background="#FF0000"
     android:gravity="center"
     android:text="删除" />
 </LinearLayout>

//默认展示的布局
 <RelativeLayout
   android:layout_width="match_parent"
   android:layout_height="80dp">

<TextView
     android:id="@+id/text"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_centerVertical="true"
     android:text="aaaaa"
     android:textSize="18sp" />
 </RelativeLayout>

</com.daimajia.swipe.SwipeLayout>

具体实现

1、实现思路

思路其实也很简单就是在实现自定义SwipeRefreshLayout重写onInterceptTouchEvent根据左右还是上下滑动进行事件的拦截和下发

2、判断滑动方向

主要根据用户滑动的夹角来判断是上下滑动还是左右滑动。判断后设置一个标记,下一次滑动的时候如果上下滑动(Listiview)的滑动那么就调用父类的的onInterceptTouchEvent方法正常滑动,此时事件在到达侧滑菜单的时候已经被消费了所有不会滑出侧滑菜单。如果是左右滑动则return false 不拦截事件交由子控件处理,这是左右滑动Listview是不会做消费所以会到达让侧滑菜单来处理。


case MotionEvent.ACTION_DOWN:
       pressX = (int) ev.getX(); //记录按下的X坐标
       pressY = (int) ev.getY();//记录按下的Y坐标
       break;
  case MotionEvent.ACTION_MOVE:
       //判断滑动距离是否是正常的滑动
       if (Math.abs(ev.getY() - pressY) < touchSlop && Math.abs(ev.getX() - pressX) < touchSlop)
         return super.onInterceptTouchEvent(ev);
       //如果用户是滑动listview则交由父类onInterceptTouchEvent处理
       if (interceptStatus == REFRESH_STATUS)
         return super.onInterceptTouchEvent(ev);
         //用户如果是滑出SwipeLayout则不拦截时间交由SwipeLayout处理
       else if (interceptStatus == SWIPE_MENU_OPEN)
         return false;
       //根据滑动角度判断用户是滑出SwipeLayout还是Listview
       double angle = Math.atan((ev.getY() - pressY) / (ev.getX() - pressX));//计算滑动的角度
       int degrees = (int) Math.toDegrees(angle);
       degrees = Math.abs(degrees);
       //大于45度则判断为Listview滑动
       if (degrees > 45) {
         Log.d(TAG, "正在上下滑动");
         //如果当前是SwipeLayout内点击的事件序列则不允许滑动
         if (interceptStatus == SWIPE_MENU_CLOSE)
           return true;
         interceptStatus = REFRESH_STATUS; //标记为Listview滑动
         return super.onInterceptTouchEvent(ev);
       } else { //小于45度则判断为SwipeLayout滑动
         Log.e(TAG, "正在左右滑动");
         currentSwipeLayout = getCurrentSwipeLayout(); //获取当前滑出的SwipeLayout
         interceptStatus = SWIPE_MENU_OPEN; //标记为SwipeLayout滑动
         return false;
       }

3点击事件处理

点击事件分为几种情况

1.用户普通的item点击:此情况下不做任何处理

2.当滑出侧滑菜单栏以后,点击其他的item时,这是判断是否是当前滑出的侧滑菜单的position如若不是在down事件的时候变将其关闭并且 return true当在onInterceptTouchEvent中retur true 后此后所有的事件,直到手指抬起时的所有操作都交由自身的onTouchEvent处理而在onTouchEvent中也不做任何操作直接拦截即可达到需要的效果

判断是否是点击的当前滑出菜单的Item


   if (currentSwipeLayout != null && currentSwipeLayout.getOpenStatus() != SwipeLayout.Status.Close) { //如果当前有打开或者正在打开的SwipeLayout
         Log.d(TAG, "currentSwipeLayout.getOpenStatus() " + currentSwipeLayout.getOpenStatus());
         interceptStatus = SWIPE_MENU_CLOSE;//此次用户操作为关闭SwipeLayout
         Rect rect = new Rect();
         currentSwipeLayout.getHitRect(rect);
         //判断当前点击X Y坐标是否在当前SwipeLayout中,即用户是否点击这个SwipeLayout,有就不拦截时间交由SwipeLayout自己处理
         if (rect.contains(pressX, pressY)) {
           return false;
         }    

onInterceptTouchEvent中down事件
    case MotionEvent.ACTION_DOWN:
          //如果没有就关闭并且拦截此时间顺序中所有事件
         currentSwipeLayout.close();
         return true;

onTouchEvent中的move事件
    case MotionEvent.ACTION_MOVE:
       if (interceptStatus == SWIPE_MENU_CLOSE)//如果是SwipeLayout关闭事件序列则拦截事件
         return true;

3.当用户点击的是当前侧滑菜单,这里又有两种情况如果点击的范围不是侧滑菜单的范围则return false这时如果抬手时是在侧滑菜单的范围内将会触发点击事件(如果有)如果没有在此范围则关闭侧滑菜单。如果此期间有move事件即用户有滑动会进入之前说的move判断逻辑。

简而言之就是按下的范围是滑出侧滑菜单的Item则不拦截交由儿子你说了算,如果有滑动就由父类进行开始说的判断,然后进行相应逻辑,此时就不是儿子说了算。


//判断当前点击X Y坐标是否在当前SwipeLayout中,即用户是否点击这个SwipeLayout,有就不拦截时间交由SwipeLayout自己处理
         if (rect.contains(pressX, pressY)) {
           return false;
         }
         //如果没有就关闭并且拦截此时间顺序中所有事件
         currentSwipeLayout.close();
         return true;

结语

此文设计事件分发的许多知识,加上这几个控件都有自己的方法所有有许多内容不太容易说的清楚(甚至自己都不一定弄的很清楚)加之本人表达能力不算好,所以可能云里雾里的,如果有兴趣的朋友们可以去GitHub下载源码看看。最后在给一次地址 SwipeMenuRefreshView

来源:http://www.jianshu.com/p/c25f6d2ff518?utm_source=tuicool&utm_medium=referral

标签:android,侧滑删除
0
投稿

猜你喜欢

  • Flutter中http请求抓包的完美解决方案

    2023-08-22 18:47:47
  • java后台接收app上传的图片的示例代码

    2022-11-03 00:04:15
  • Java初学之继承与多态

    2022-11-29 15:13:04
  • android view实现横向滑动选择

    2022-04-26 11:28:48
  • Android本地实现搜索历史记录

    2023-08-15 22:25:17
  • 快速了解c# 结构体

    2022-10-19 05:38:45
  • Java 数据结构深入理解ArrayList与顺序表

    2023-02-15 14:24:07
  • Spring mvc拦截器实现原理解析

    2023-06-06 15:26:33
  • 解析Android框架之Volley源码

    2021-09-30 19:44:28
  • 关于feign.codec.DecodeException异常的解决方案

    2022-01-28 15:50:19
  • maven多个仓库查询的优先级顺序案例讲解

    2023-08-16 02:33:23
  • Spring4整合Hibernate5详细步骤

    2022-03-15 16:53:07
  • C#实现单例模式的几种方法总结

    2023-10-13 16:33:55
  • C++异步操作future和aysnc与function和bind

    2023-06-21 06:48:50
  • c#入门之类型转换详解

    2022-03-17 01:36:52
  • java生成随机字符串的两种方法

    2022-09-09 22:49:26
  • Java多线程编程中使用Condition类操作锁的方法详解

    2023-10-19 13:30:55
  • Intellij Idea中批量导入第三方jar包的全过程

    2022-01-29 03:14:26
  • Java多线程之读写锁分离设计模式

    2021-06-08 07:20:48
  • Unity EasyTouch摇杆插件使用示例详解

    2023-01-26 17:09:17
  • asp之家 软件编程 m.aspxhome.com