android 可拖拽控件,安卓实现任意控件view可拖拽,并监听拖拽和点击事件,可自动拉回屏幕边缘...
因为项目中有需要实现控件可任意拖拽的需求,所以简单写了个自定义OnTouchListener,以作抛砖引玉,欢迎大家提议反馈。
完整实现类如下,代码中有详细注释: 用户可以决定是否开启自动拖拽边缘功能,可以监听控件的拖拽和点击事件
public class OnDragTouchListener implements View.OnTouchListener {
private int mScreenWidth, mScreenHeight;//屏幕宽高
private float mOriginalX, mOriginalY;//手指按下时的初始位置
private float mDistanceX, mDistanceY;//记录手指与view的左上角的距离
private int left, top, right, bottom;
private OnDraggableClickListener mListener;
private boolean hasAutoPullToBorder;//标记是否开启自动拉到边缘功能
public OnDragTouchListener() {
}
public OnDragTouchListener(boolean isAutoPullToBorder) {
hasAutoPullToBorder = isAutoPullToBorder;
}
@Override
public boolean onTouch(final View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mScreenWidth = v.getResources().getDisplayMetrics().widthPixels;
mScreenHeight = v.getResources().getDisplayMetrics().heightPixels;
mOriginalX = event.getRawX();
mOriginalY = event.getRawY();
mDistanceX = event.getRawX() - v.getLeft();
mDistanceY = event.getRawY() - v.getTop();
break;
case MotionEvent.ACTION_MOVE:
left = (int) (event.getRawX() - mDistanceX);
top = (int) (event.getRawY() - mDistanceY);
right = left + v.getWidth();
bottom = top + v.getHeight();
if (left < 0) {
left = 0;
right = left + v.getWidth();
}
if (top < 0) {
top = 0;
bottom = top + v.getHeight();
}
if (right > mScreenWidth) {
right = mScreenWidth;
left = right - v.getWidth();
}
if (bottom > mScreenHeight) {
bottom = mScreenHeight;
top = bottom - v.getHeight();
}
v.layout(left, top, right, bottom);
break;
case MotionEvent.ACTION_UP:
//在拖动过按钮后,如果其他view刷新导致重绘,会让按钮重回原点,所以需要更改布局参数
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
startAutoPull(v, lp);
//如果移动距离过小,则判定为点击
if (Math.abs(event.getRawX() - mOriginalX) <
ScreenUtils.getPxFromDp(v.getResources(), 5) &&
Math.abs(event.getRawY() - mOriginalY) <
ScreenUtils.getPxFromDp(v.getResources(), 5)) {
if (mListener != null) {
mListener.onClick(v);
}
}
//消除警告
v.performClick();
break;
}
return true;
}
public OnDraggableClickListener getOnDraggableClickListener() {
return mListener;
}
public void setOnDraggableClickListener(OnDraggableClickListener listener) {
mListener = listener;
}
public boolean isHasAutoPullToBorder() {
return hasAutoPullToBorder;
}
public void setHasAutoPullToBorder(boolean hasAutoPullToBorder) {
this.hasAutoPullToBorder = hasAutoPullToBorder;
}
/**
* 开启自动拖拽
*
* @param v 拉动控件
* @param lp 控件布局参数
*/
private void startAutoPull(final View v, final ViewGroup.MarginLayoutParams lp) {
if (!hasAutoPullToBorder) {
v.layout(left, top, right, bottom);
lp.setMargins(left, top, 0, 0);
v.setLayoutParams(lp);
if (mListener != null) {
mListener.onDragged(v, left, top);
}
return;
}
//当用户拖拽完后,让控件根据远近距离回到最近的边缘
float end = 0;
if ((left + v.getWidth() / 2) >= mScreenWidth / 2) {
end = mScreenWidth - v.getWidth();
}
ValueAnimator animator = ValueAnimator.ofFloat(left, end);
animator.setInterpolator(new DecelerateInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int leftMargin = (int) ((float) animation.getAnimatedValue());
v.layout(leftMargin, top, right, bottom);
lp.setMargins(leftMargin, top, 0, 0);
v.setLayoutParams(lp);
}
});
final float finalEnd = end;
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
if (mListener != null) {
mListener.onDragged(v, (int) finalEnd, top);
}
}
});
animator.setDuration(400);
animator.start();
}
/**
* 控件拖拽监听器
*/
public interface OnDraggableClickListener {
/**
* 当控件拖拽完后回调
*
* @param v 拖拽控件
* @param left 控件左边距
* @param top 控件右边距
*/
void onDragged(View v, int left, int top);
/**
* 当可拖拽控件被点击时回调
*
* @param v 拖拽控件
*/
void onClick(View v);
}
}
后期有时间会做更多优化和扩展功能,如果有什么更好的方式或建议,欢迎大家反馈。
android 可拖拽控件,安卓实现任意控件view可拖拽,并监听拖拽和点击事件,可自动拉回屏幕边缘...相关推荐
- android列表项点击事件,Android 开发 tips(2):监听 Listview 列表项点击事件
Android 开发 tips(2):监听 Listview 列表项点击事件 (这篇和上篇本来是应该一起写的,但是太过冗长,附链接:[SimpleAdapter 在 Listview 中的应用] ht ...
- Android按back后执行过程,安卓app测试获取接口返回数据,然后处理数据,放在一个button点击事件里面 执行顺序有问题?无法获取数据?...
private JSONArray jsonArray; btn1.setOnClickListener(new View.OnClickListener() { @Override public v ...
- 安卓APP在运行时对全局进行网络状态监听的实现
转载自:https://blog.51cto.com/wangjinchan/4752142 感谢博主:一粒程序米 分享 一.前言 怎么对APP进行全局的网络监听呢?仿照微信的无网状态下弹出的提示,应 ...
- 安卓传感器全解:注册、注销传感器、监听传感器,距离传感器、方向传感器、陀螺仪、加速计、磁场、气压传感器
全栈工程师开发手册 (作者:栾鹏) 安卓教程全解 安卓传感器全解:注册.注销传感器.监听传感器.距离传感器.方向传感器.陀螺仪.加速计.磁场.气压传感器. 注册.注销.监听传感器 1.自定义传感器监听 ...
- jquery实现上下左右键盘监听_基于 jQuery 实现键盘事件监听控件
最近项目里要做一个画板,需要对键盘事件进行监听,来进行诸如撤回.重做.移动.缩放等操作,因此顺手实现了一个键盘事件监听控件,期间略有收获,整理出来,希望对大家有所帮助,更希望能获得高手的指点. 1. ...
- 百度地图,开启marker点拖拽,并监听拖拽后的坐标位置
有的网站可能让用户自己移动marker点选择位置 这个时候 需要就来了 开启marker点的拖拽还是很简单的哈 其实开启拖拽的也是 BMapGL 版本的地图 这点要记住哈 var mar ...
- Android移动开发之【通往安卓的神奇之旅】Senior VIew高级组件与onClickListener()再探索
文章目录 1 setonClickListener() 2 button的OnClickListener的三种实现方法 3 VideoView 1 setonClickListener() setOn ...
- android 监听安装来源_Flutter插件开发之APK自动安装
点击上方的终端研发部,右上角选择"设为星标" 每日早9点半,技术文章准时送上 公众号后台回复"学习",获取作者独家秘制精品资料 往期文章 记五月的一个Andro ...
- Android viewpager 嵌套 viewpager滑动 点击事件冲突解决方案
为了解决这个问题.可以自定义viewpager,然后在里面监听首饰,自定义点击事件 package com.hpuvoice.view;import android.content.Context; ...
- 详细讲解安卓截屏监听操作
需求 项目中有时会遇到监听用户截屏操作的需求,应用场景也比较丰富. eg. 1: 某个隐私页面禁止截屏,当发现用户截屏后,删除该截屏文件: eg. 2: 当用户截屏时,可能是需要进行分享,意见反馈等操 ...
最新文章
- 利用 Java dump 进行 JVM 故障诊断
- 服务器重启后启动Docker命令
- 大数据的说法 正确的是_前端测试题:(解析)用于播放音频文件的正确HTML5元素是?...
- JAVA数组扁平化整合_JS数组扁平化(flat)方法总结详解
- mysql 日期和时间类型
- oracle10g中获得可更新的(修改、增加等) ResultSet
- 灰色关联分析_R语言使用灰色关联分析(Grey Relation Analysis,GRA)中国经济社会发展指标...
- git如何查看和切换账号
- win10wifi多了数字_win10系统电脑查看wifi密码是多少的方法
- CVPR 2018:阿里提出新零样本学习方法,有效解决偏置问题
- Windows7系统无损分区的教程
- PMP知识点总结-自由时差与总时差
- 【JVM】17、垃圾回收器
- Windows Installer服务总是自动关闭导致无法安装在win10上安装英伟达显卡驱动的解决方案...
- 【光纤专题】单模光纤和多模光纤有哪些不同之处?《建议收藏》
- 小众软件android,应用专题 - 这些小众软件,满足你文艺不甘寂寞的心|微信安卓版7.0内测来啦 - Android 应用 - 生活 - 【最美应用】...
- 公安大数据应用之情报分析与关联挖掘
- 微信群里的这几类人,真让人想打他
- c语言编程怎么样,C语言怎么样,好学吗?
- 英语之境(chapter two)