Android 可拖拽的View,限制在父布局中随意拖拽;拖拽结束后可左右吸边;

2024-06-08 21:20

本文主要是介绍Android 可拖拽的View,限制在父布局中随意拖拽;拖拽结束后可左右吸边;,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

实现方法一:自定义View

可随意拖动拖拽的View,限制拖动范围是父布局中;


import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.widget.ImageView;public class DragActionButton extends ImageView {private int parentHeight;private int parentWidth;private int lastX;private int lastY;private ViewGroup parent;public DragActionButton(Context context) {super(context);}public DragActionButton(Context context, AttributeSet attrs) {super(context, attrs);}public DragActionButton(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}@Overridepublic boolean onTouchEvent(MotionEvent event) {int rawX = (int) event.getRawX();int rawY = (int) event.getRawY();switch (event.getAction() & MotionEvent.ACTION_MASK) {case MotionEvent.ACTION_DOWN:getParent().requestDisallowInterceptTouchEvent(true);lastX = rawX;lastY = rawY;if (getParent() != null) {parent = (ViewGroup) getParent();parentHeight = parent.getHeight();parentWidth = parent.getWidth();}break;case MotionEvent.ACTION_MOVE:if (parentHeight <= 0.2 || parentWidth <= 0.2) {break;}int dx = rawX - lastX;int dy = rawY - lastY;//这里修复一些华为手机无法触发点击事件int distance = (int) Math.sqrt(dx * dx + dy * dy);if (distance == 0) {break;}float x = getX() + dx;float y = getY() + dy;//检测是否到达边缘 左上右下x = x < 0 ? 0 : x + getWidth() > parentWidth  ? parentWidth - getWidth() : x;y = y < 0 ? 0 : y + getHeight() > parentHeight ? parentHeight - getHeight() : y;setX(x);setY(y);lastX = rawX;lastY = rawY;Log.i("ACTION_MOVE", "getX=" + getX() + ";getY=" + getY() + ";parentWidth=" + parentWidth+ ";parentHeight=" + parentHeight);break;case MotionEvent.ACTION_UP:case MotionEvent.ACTION_CANCEL:this.setAlpha(1.0f);Log.i("ACTION_UP", "getX=" + getX() + ";getY=" + getY());break;}return true;}}

下面是可以左右吸边的效果;


import android.animation.ObjectAnimator;
import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
import android.widget.ImageView;
import android.widget.Toast;import androidx.annotation.Nullable;public class DragFloatActionButton extends ImageView {private int parentHeight;private int parentWidth;Handler handler = new Handler();Runnable runnable = new Runnable() {@Overridepublic void run() {setAlpha(0.3f);}};private int lastX;private int lastY;private ViewGroup parent;public DragFloatActionButton(Context context) {super(context);}public DragFloatActionButton(Context context,  AttributeSet attrs) {super(context, attrs);}public DragFloatActionButton(Context context,  AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}private int downX;private int downY;private long downTime;@Overridepublic boolean onTouchEvent(MotionEvent event) {int rawX = (int) event.getRawX();int rawY = (int) event.getRawY();switch (event.getAction() & MotionEvent.ACTION_MASK) {case MotionEvent.ACTION_DOWN:this.setAlpha(0.9f);getParent().requestDisallowInterceptTouchEvent(true);lastX = rawX;lastY = rawY;downX = rawX;downY = rawY;downTime = System.currentTimeMillis();if (getParent() != null) {parent = (ViewGroup) getParent();parentHeight = parent.getHeight();parentWidth = parent.getWidth();}break;case MotionEvent.ACTION_MOVE:if (parentHeight <= 0.2 || parentWidth <= 0.2) {break;}this.setAlpha(0.9f);int dx = rawX - lastX;int dy = rawY - lastY;//这里修复一些华为手机无法触发点击事件int distance = (int) Math.sqrt(dx * dx + dy * dy);if (distance == 0) {break;}float x = getX() + dx;float y = getY() + dy;//检测是否到达边缘 左上右下x = x < 0 ? 0 : x + getWidth() > parentWidth  ? parentWidth - getWidth() : x;y = y < 0 ? 0 : y + getHeight() > parentHeight ? parentHeight - getHeight() : y;setX(x);setY(y);lastX = rawX;lastY = rawY;Log.i("ACTION_MOVE", "getX=" + getX() + ";getY=" + getY() + ";parentWidth=" + parentWidth+ ";parentHeight=" + parentHeight);break;case MotionEvent.ACTION_UP:moveHide(rawX);if(onClickListener != null&& Math.abs(downX - rawX) < 10&& Math.abs(downY - rawY) < 10&& System.currentTimeMillis() - downTime < 1000){Log.i("ACTION_UP", "触发点击事件 ");onClickListener.onClick(this);}break;}return true;}OnClickListener onClickListener;@Overridepublic void setOnClickListener(@Nullable OnClickListener l) {onClickListener = l;}private void moveHide(int rawX) {if (rawX >= parentWidth / 2) {//靠右吸附animate().setInterpolator(new DecelerateInterpolator()).setDuration(500).xBy(parentWidth - getWidth() - getX()).start();myRunable();} else {//靠左吸附ObjectAnimator oa = ObjectAnimator.ofFloat(this, "x", getX(), 0);oa.setInterpolator(new DecelerateInterpolator());oa.setDuration(500);oa.start();myRunable();}}private void myRunable() {handler.removeCallbacks(runnable);handler.postDelayed(runnable, 2000);}

实现方法二:自定义ViewGroup

使用ViewDragHelper实现:

ViewDragHelper is a utility class for writing custom ViewGroups. It offers a number of useful operations and state tracking for allowing a user to drag and reposition views within their parent ViewGroup.


import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.RelativeLayout;import androidx.customview.widget.ViewDragHelper;public class DragViewGroup extends RelativeLayout {private ViewDragHelper mDragger;private View mDragView;public DragViewGroup(Context context, AttributeSet attrs) {super(context, attrs);this.setGravity(Gravity.CENTER);mDragger = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {@Overridepublic boolean tryCaptureView(View child, int pointerId) {return true;}@Overridepublic int clampViewPositionHorizontal(View child, int left, int dx) {final int leftBound = getPaddingLeft();final int rightBound = getWidth() - mDragView.getWidth();final int newLeft = Math.min(Math.max(left, leftBound), rightBound);return newLeft;}@Overridepublic int clampViewPositionVertical(View child, int top, int dy) {final int topBound = getPaddingTop();final int bottomBound = getHeight() - mDragView.getHeight();final int newTop = Math.min(Math.max(top, topBound), bottomBound);return newTop;}//手指释放的时候回调@Overridepublic void onViewReleased(View releasedChild, float xvel, float yvel) {Log.i("onViewReleased", "view: x :"+mDragView.getX() +"y:"+mDragView.getY()+"\nviewgroup: w: "+getWidth() + "h : "+getHeight());}});}@Overridepublic boolean onInterceptTouchEvent(MotionEvent event) {return mDragger.shouldInterceptTouchEvent(event);}@Overridepublic boolean onTouchEvent(MotionEvent event) {mDragger.processTouchEvent(event);return true;}@Overrideprotected void onFinishInflate() {super.onFinishInflate();mDragView = getChildAt(0);}
}

这篇关于Android 可拖拽的View,限制在父布局中随意拖拽;拖拽结束后可左右吸边;的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1043341

相关文章

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

前端原生js实现拖拽排课效果实例

《前端原生js实现拖拽排课效果实例》:本文主要介绍如何实现一个简单的课程表拖拽功能,通过HTML、CSS和JavaScript的配合,我们实现了课程项的拖拽、放置和显示功能,文中通过实例代码介绍的... 目录1. 效果展示2. 效果分析2.1 关键点2.2 实现方法3. 代码实现3.1 html部分3.2

如何利用Java获取当天的开始和结束时间

《如何利用Java获取当天的开始和结束时间》:本文主要介绍如何使用Java8的LocalDate和LocalDateTime类获取指定日期的开始和结束时间,展示了如何通过这些类进行日期和时间的处... 目录前言1. Java日期时间API概述2. 获取当天的开始和结束时间代码解析运行结果3. 总结前言在J

Android里面的Service种类以及启动方式

《Android里面的Service种类以及启动方式》Android中的Service分为前台服务和后台服务,前台服务需要亮身份牌并显示通知,后台服务则有启动方式选择,包括startService和b... 目录一句话总结:一、Service 的两种类型:1. 前台服务(必须亮身份牌)2. 后台服务(偷偷干

CSS弹性布局常用设置方式

《CSS弹性布局常用设置方式》文章总结了CSS布局与样式的常用属性和技巧,包括视口单位、弹性盒子布局、浮动元素、背景和边框样式、文本和阴影效果、溢出隐藏、定位以及背景渐变等,通过这些技巧,可以实现复杂... 一、单位元素vm 1vm 为视口的1%vh 视口高的1%vmin 参照长边vmax 参照长边re

CSS3中使用flex和grid实现等高元素布局的示例代码

《CSS3中使用flex和grid实现等高元素布局的示例代码》:本文主要介绍了使用CSS3中的Flexbox和Grid布局实现等高元素布局的方法,通过简单的两列实现、每行放置3列以及全部代码的展示,展示了这两种布局方式的实现细节和效果,详细内容请阅读本文,希望能对你有所帮助... 过往的实现方法是使用浮动加

Android kotlin语言实现删除文件的解决方案

《Androidkotlin语言实现删除文件的解决方案》:本文主要介绍Androidkotlin语言实现删除文件的解决方案,在项目开发过程中,尤其是需要跨平台协作的项目,那么删除用户指定的文件的... 目录一、前言二、适用环境三、模板内容1.权限申请2.Activity中的模板一、前言在项目开发过程中,尤

SpringBoot实现基于URL和IP的访问频率限制

《SpringBoot实现基于URL和IP的访问频率限制》在现代Web应用中,接口被恶意刷新或暴力请求是一种常见的攻击手段,为了保护系统资源,需要对接口的访问频率进行限制,下面我们就来看看如何使用... 目录1. 引言2. 项目依赖3. 配置 Redis4. 创建拦截器5. 注册拦截器6. 创建控制器8.

Android数据库Room的实际使用过程总结

《Android数据库Room的实际使用过程总结》这篇文章主要给大家介绍了关于Android数据库Room的实际使用过程,详细介绍了如何创建实体类、数据访问对象(DAO)和数据库抽象类,需要的朋友可以... 目录前言一、Room的基本使用1.项目配置2.创建实体类(Entity)3.创建数据访问对象(DAO

Linux限制ip访问的解决方案

《Linux限制ip访问的解决方案》为了修复安全扫描中发现的漏洞,我们需要对某些服务设置访问限制,具体来说,就是要确保只有指定的内部IP地址能够访问这些服务,所以本文给大家介绍了Linux限制ip访问... 目录背景:解决方案:使用Firewalld防火墙规则验证方法深度了解防火墙逻辑应用场景与扩展背景: