android实现简单左滑删除控件
时间:2022-07-27
本文章向大家介绍android实现简单左滑删除控件,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
本文为大家分享了一个简单的android左滑删除控件,供大家参考,具体内容如下
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.PointF;
import android.support.v4.view.ViewConfigurationCompat;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
public class SwipeLayout extends ViewGroup{
public static String TAG = "SwipeLayout";
//可以滚动的距离
int mSwipeWidth;
PointF firstPoint;
PointF lastPoint;
float mTouchSlop;
ValueAnimator openAnimator;
ValueAnimator closeAnimator;
public SwipeLayout(Context context) {
this(context,null);
}
public SwipeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(ViewConfiguration.get(getContext()));
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int left=0;
int childCount = getChildCount();
for (int i=0;i<childCount;++i){
View child = getChildAt(i);
//按顺序从左往右排
// if (i==0){
// child.layout(0,0,child.getMeasuredWidth(),child.getMeasuredHeight());
// }else {
child.layout(left,0,left+child.getMeasuredWidth(),child.getMeasuredHeight());
// }
left += child.getMeasuredWidth();
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int childCount = getChildCount();
View mainChild = getChildAt(0);
int width=0;
int height=0;
mSwipeWidth = 0;
// measureChild(mainChild,widthMeasureSpec,heightMeasureSpec);
measure(widthMeasureSpec,heightMeasureSpec);
//滑动距离是 从index开始 所有控件的宽度之和
if (childCount 1) {
for (int i = 1; i < childCount; ++i) {
mSwipeWidth += getChildAt(i).getMeasuredWidth();
}
}
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthValue = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightValue = MeasureSpec.getSize(heightMeasureSpec);
switch (heightMode){
case MeasureSpec.AT_MOST:
case MeasureSpec.UNSPECIFIED:
//没有指定大小 按照第一个子控件的大小来设置
height = mainChild.getMeasuredHeight();
break;
case MeasureSpec.EXACTLY:
height = heightValue;
break;
}
switch (widthMode){
case MeasureSpec.AT_MOST:
case MeasureSpec.UNSPECIFIED:
//没有指定大小 按照第一个子控件的大小来设置
width = mainChild.getMeasuredWidth();
break;
case MeasureSpec.EXACTLY:
width = widthValue;
break;
}
// for (int i=1;i<childCount;++i){
// measureChild(getChildAt(i),widthMeasureSpec,MeasureSpec.makeMeasureSpec(height,MeasureSpec.EXACTLY));
// }
setMeasuredDimension(width,height);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
firstPoint = new PointF(ev.getX(),ev.getY());
lastPoint = new PointF(ev.getX(),ev.getY());
break;
case MotionEvent.ACTION_MOVE:
float moveDistance = ev.getX()-firstPoint.x;
//移动距离大于制定值 认为进入控件的滑动模式
if (Math.abs(moveDistance) mTouchSlop ){
//让父控件不拦截我们的事件
getParent().requestDisallowInterceptTouchEvent(true);
//拦截事件
return true;
}
}
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()){
case MotionEvent.ACTION_MOVE:
float moveDistance = ev.getX()-lastPoint.x;
lastPoint = new PointF(ev.getX(),ev.getY());
// 这里要注意 x大于0的时候 往左滑动 小于0往右滑动
scrollBy((int) -moveDistance ,0);
//边界判定 超过了边界 直接设置为边界值
if (getScrollX() mSwipeWidth){
scrollTo(mSwipeWidth,0);
}else if (getScrollX()<0){
scrollTo(0,0);
}
break;
case MotionEvent.ACTION_UP:
//没动 不理他
if (getScrollX()== mSwipeWidth ||getScrollX()==0){
return false;
}
float distance = ev.getX()-firstPoint.x;
//滑动距离超过 可滑动距离指定值 继续完成滑动
if (Math.abs(distance) mSwipeWidth *0.3 ){
if (distance 0){
smoothClose();
}else if (distance<0){
smoothOpen();
}
}else {
if (distance 0){
smoothOpen();
}else if (distance<0){
smoothClose();
}
}
return true;
}
return super.onTouchEvent(ev);
}
public void smoothOpen(){
clearAnimator();
openAnimator = ValueAnimator.ofInt(getScrollX(), mSwipeWidth);
openAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Integer integer = (Integer) animation.getAnimatedValue();
scrollTo(integer,0);
}
});
openAnimator.start();
}
public void smoothClose(){
clearAnimator();
closeAnimator = ValueAnimator.ofInt(getScrollX(),0);
closeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Integer integer = (Integer) animation.getAnimatedValue();
scrollTo(integer,0);
}
});
closeAnimator.start();
}
public void open(){
scrollTo(mSwipeWidth,0);
}
public void close(){
scrollTo(0,0);
}
//执行滑动动画必须先清除动画 不然会鬼畜
private void clearAnimator(){
if (closeAnimator!=null && closeAnimator.isRunning()){
closeAnimator.cancel();
closeAnimator = null;
}
if (openAnimator!=null && openAnimator.isRunning()) {
openAnimator.cancel();
openAnimator = null;
}
}
public void toggle(){
if (getScrollX()==0){
open();
}else {
close();
}
}
}
使用
<com.example.chenweiqi.simplerefreshview.widget.SwipeLayout
android:id="@+id/swipeLayout"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:background="#F3F3F3"
<Button
android:id="@+id/btn"
android:text="123"
android:layout_width="match_parent"
android:layout_height="50dp" /
<Button
android:background="#FF0000"
android:text="shanchu"
android:layout_width="80dp"
android:layout_height="match_parent" /
<TextView
android:gravity="center"
android:textAlignment="center"
android:background="#0F0"
android:text="123"
android:layout_width="30dp"
android:layout_height="match_parent" /
</com.example.chenweiqi.simplerefreshview.widget.SwipeLayout
效果
以上就是本文的全部内容,希望对大家的学习有所帮助。
- 【自然框架】QuickPager分页控件,新增一种分页方式——伪URL分页(Postback版)
- 我们的漏洞Webug 3.0中级进阶攻略(上)
- 【自然框架】QuickPager分页控件的总体介绍和在线演示
- 在C++中反射调用.NET(三) 使用非泛型集合的委托方法C++中的列表对象list C++传递集合数据给.NET创建泛型List实例反射静态方法反射调用索引器当委托遇到协变和逆变C++/CLI
- 如何使用树莓派自制网络监视器
- 利用雅虎小型企业服务平台的目录遍历漏洞查看客户的信用卡信息
- 【自然框架】QuickPager asp.net 分页控件的Ajax分页方式。
- 骑行在华盛顿 针对320万次共享单车骑行数据的分析
- 【自然框架】QuickPagerSQL——专门生成分页用的SQL的类库
- 【数据科学】数据科学中的 Spark 入门
- 【自然框架】QuickPager分页控件的单独的源码 V2.0.4.2。
- 用 iPhoneX 的 FaceID 刷脸解锁真的靠谱吗?
- 【自然框架】用CMS的栏目举例,聊一聊从“一层”到“三层”的变化
- java如何自定义鼠标指针
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 给你点信心——LeetCode题目7:整数反转
- Python -二叉树 创建与遍历算法(很详细,转自国外教程)
- APP流量来源追踪方式——Android篇
- 从浏览器输入网址回车到看到页面过程到底经历了什么?
- Flutter Bloc 官方文档(BlocBuilder翻译)
- OpenGL ES 3.0 | 统一变量和属性的概念与(在程序中的)获取流程、统一变量缓冲区对象详解、std140块规范、用 命名统一变量块 建立 统一变量缓冲区对象 的流程 和 相关API 和...
- 深入浅出SVM(PART III)
- 高频原题——LeetCode题目8:字符串转换整数 (atoi)
- 不转字符串判断——LeetCode题目9:回文数
- 关于双指针的简单理解
- 面试题噩梦之一——LeetCode题目10:正则表达式匹配
- 什么时候触发GC
- 找找数学上的规律——LeetCode题目11:盛最多水的容器
- Java学习笔记, 不断更新
- 这题真是送分——LeetCode题目12:整数转罗马数字