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中Dialog的使用详解

《Android中Dialog的使用详解》Dialog(对话框)是Android中常用的UI组件,用于临时显示重要信息或获取用户输入,本文给大家介绍Android中Dialog的使用,感兴趣的朋友一起... 目录android中Dialog的使用详解1. 基本Dialog类型1.1 AlertDialog(

浅谈mysql的sql_mode可能会限制你的查询

《浅谈mysql的sql_mode可能会限制你的查询》本文主要介绍了浅谈mysql的sql_mode可能会限制你的查询,这个问题主要说明的是,我们写的sql查询语句违背了聚合函数groupby的规则... 目录场景:问题描述原因分析:解决方案:第一种:修改后,只有当前生效,若是mysql服务重启,就会失效;

Android Kotlin 高阶函数详解及其在协程中的应用小结

《AndroidKotlin高阶函数详解及其在协程中的应用小结》高阶函数是Kotlin中的一个重要特性,它能够将函数作为一等公民(First-ClassCitizen),使得代码更加简洁、灵活和可... 目录1. 引言2. 什么是高阶函数?3. 高阶函数的基础用法3.1 传递函数作为参数3.2 Lambda

Android自定义Scrollbar的两种实现方式

《Android自定义Scrollbar的两种实现方式》本文介绍两种实现自定义滚动条的方法,分别通过ItemDecoration方案和独立View方案实现滚动条定制化,文章通过代码示例讲解的非常详细,... 目录方案一:ItemDecoration实现(推荐用于RecyclerView)实现原理完整代码实现

Android App安装列表获取方法(实践方案)

《AndroidApp安装列表获取方法(实践方案)》文章介绍了Android11及以上版本获取应用列表的方案调整,包括权限配置、白名单配置和action配置三种方式,并提供了相应的Java和Kotl... 目录前言实现方案         方案概述一、 androidManifest 三种配置方式

Android WebView无法加载H5页面的常见问题和解决方法

《AndroidWebView无法加载H5页面的常见问题和解决方法》AndroidWebView是一种视图组件,使得Android应用能够显示网页内容,它基于Chromium,具备现代浏览器的许多功... 目录1. WebView 简介2. 常见问题3. 网络权限设置4. 启用 JavaScript5. D

Android如何获取当前CPU频率和占用率

《Android如何获取当前CPU频率和占用率》最近在优化App的性能,需要获取当前CPU视频频率和占用率,所以本文小编就来和大家总结一下如何在Android中获取当前CPU频率和占用率吧... 最近在优化 App 的性能,需要获取当前 CPU视频频率和占用率,通过查询资料,大致思路如下:目前没有标准的

Android开发中gradle下载缓慢的问题级解决方法

《Android开发中gradle下载缓慢的问题级解决方法》本文介绍了解决Android开发中Gradle下载缓慢问题的几种方法,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、网络环境优化二、Gradle版本与配置优化三、其他优化措施针对android开发中Gradle下载缓慢的问

CSS3 最强二维布局系统之Grid 网格布局

《CSS3最强二维布局系统之Grid网格布局》CS3的Grid网格布局是目前最强的二维布局系统,可以同时对列和行进行处理,将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局,本文介... 深入学习 css3 目前最强大的布局系统 Grid 网格布局Grid 网格布局的基本认识Grid 网

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

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