android基于SwipeRefreshLayout实现类QQ的侧滑删除
作者:_独爱夜色 发布时间:2023-05-22 14:49:19
前言
记得去年做一个聊天项目需要实现类似QQ的下拉刷新并且有侧滑删除的功能,在网上找了很久都没有QQ的完美,多多少少存在各种的问题,最后把下拉刷新的功能去掉后,只保留了侧滑删除的功能才找到个完美的。回去后和一朋友讨论,朋友找了以后说了一句,这种功能没有8K以上的是写不出来的(⊙﹏⊙)b。现在看来当时真的太天真了。而如今自己也没有8K还是尝试去写写,顺便当练练手。
还是效果图优先
效果图当中看不出来事件滑动的解决方案(或者是我不会如何录制手指在屏幕上滑动方向和点击,知道的大神请告诉下,谢谢)具体的可以去下方的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


猜你喜欢
- 1、Java主要特点简单性、跨平台性、分布性、安全性、健壮性、平 * 立与可移植性、多线程、动态性、面向对象的编程语言、支持垃圾自动收集处理等
- Console.WriteLine("This is a Client, host name is {0}", Dns.
- 本节我们基于一个发表文章的案例来说明SpringBoot如何elasticsearch集成。elasticsearch本身可以是一个独立的服
- 一、电子邮件详解假设自己的电子邮件是me@163.com,对方的邮件是you@163.com我们编写好文件填写好对方文件,点击发送,这些电子
- 在spring的注解 @RequestMapping 之下可以直接获取 HttpServletRequest 来获得诸如request he
- 本文实例讲述了C#使用List类实现动态变长数组的方法。分享给大家供大家参考。具体如下:C#中的list可以当做数组使用,而且无需定义长度,
- 由于项目这种类型的图片按钮比较多,所以重写了ImageButton类。package me.henji.widget;import andr
- 因为目前工程无法使用第三方,只能搞一个 * 缓存了 * 缓存分为内存缓存,本地缓存,网络缓存;缓存的步骤依次是网络,内存,本地,然后取的顺序为内
- EventLoopGroup介绍在前面一篇文章中提到了,EventLoopGroup主要负责2个事情,这里再重复下:它主要包含2个方面的功能
- 公司最近也开始基于android4.0 ICS修改框架了,公司的手机暂时不适合拿回家测试,也没有kernel的权限。从个人的角度看,我手上现
- 引言在平时的工作中多多少少都会接触到注册中心,当你的应用从单机到拆分成多个服务,每个服务又有多个实例的情况时,那么对服务IP地址管理的要求就
- springboot项目出现”java: 错误: 无效的源发行版:17“问题解决方案下面是报错页面问
- 1. 将对象转换为JSON字符串,返回值为一个JSON字符串public static String toJson(Object value
- C#中+=是什么意思在C#中, "+="有两种运用场合。第一种,用在数值后面作为逻辑运算符,自加变量,如:int i=0
- 一、进程内部的线程同步1、使用lock,用法如下:private static readonly object SeqLock = new
- 前一段时间,在做摄像头拍照上传,摄像头拍的照片为base64编码格式的字符串,需要上传至项目中,则需要使用到将base64编码字符串转换为图
- MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移
- 你可能在上篇文章中《深入多线程之:双向信号与竞赛的用法分析》注意到了这个模式:两个Waiting 循环都要下面的构造:lock(_locke
- ==,equals()与hashcode()"=="在讲解之前,我们是怎么接触到==的,我们在作比较时经常用到 ==,
- 所谓泛型:就是允许在定义类、接口指定类型形参,这个类型形参在将在声明变量、创建对象时确定(即传入实际的类型参数,也可称为类型实参)泛型类或接