Android支持点击的TouchView(可拖动视图)
需求:
1、一个可以拖动的view;
2、该view可以通过setOnClickListener设置点击监听。
解决思路:
可拖动视图就必须重写onTouch事件,但是重写onTouch事件,点击事件肯定会被过滤。所以,需要我们自己再处理一下,把符合条件的onTouch事件转化成点击事件。
需求和解决思路都出来了,那代码就很好实现了,我们先来看一下效果图。
上最主要的代码:(一会还有DEMO)
package com.milo.widget; import android.content.Context; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.Button; /** * 支持点击事件的可拖动视图 * The view can touch and support click event * * @author Milo * Email:[email protected] * @version 2018/4/20 */ public class TouchView extends View { private static final String TAG = "TouchView"; /** * 记录X轴最后位置 */ int lastX = 0; /** * 记录Y轴最后位置 */ int lastY = 0; /** * 记录Action_Down - X轴位置 */ int downX = 0; /** * 记录Action_Down - Y轴位置 */ int downY = 0; /** * 记录Action_Down 时间 */ long lastDownInMills; final int DEFAULT_LIMITLEFT = 0; final int DEFAULT_LIMITTOP = 0; int limitLeft; int limitTop; int limitRight; int limitBottom; int screenWidth; int screenHeight; private OnClickListener l; public TouchView(Context context) { super(context); } public TouchView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); DisplayMetrics metrics = context.getResources().getDisplayMetrics(); screenWidth = metrics.widthPixels; screenHeight = metrics.heightPixels; setLimitAuto(); } public TouchView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } /** * 自适应边界 */ private void setLimitAuto() { setLimitAuto(null); } /** * 根据parentView自适应边界 * * @param parentView */ public void setLimitAuto(ViewGroup parentView) { if (parentView == null) { this.limitLeft = DEFAULT_LIMITLEFT; this.limitTop = DEFAULT_LIMITTOP; this.limitRight = screenWidth; this.limitBottom = screenHeight; } else { this.limitLeft = parentView.getLeft(); this.limitTop = parentView.getTop(); this.limitRight = parentView.getRight(); this.limitBottom = parentView.getBottom(); } } /** * 设定自定义边界 * * @param limitLeft * @param limitTop * @param limitRight * @param limitBottom */ public void setLimitParams(int limitLeft, int limitTop, int limitRight, int limitBottom) { this.limitLeft = limitLeft; this.limitTop = limitTop; this.limitRight = limitRight; this.limitBottom = limitBottom; } @Override public void setOnClickListener(@Nullable OnClickListener l) { this.l = l; } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: //TODO 按下瞬间记录所有信息 lastDownInMills = System.currentTimeMillis(); lastX = (int) event.getRawX(); lastY = (int) event.getRawY(); downX = (int) event.getRawX(); downY = (int) event.getRawY(); break; case MotionEvent.ACTION_MOVE: //TODO 计算相对位置 int dx = (int) event.getRawX() - lastX; int dy = (int) event.getRawY() - lastY; int left = getLeft() + dx; int top = getTop() + dy; int right = getRight() + dx; int bottom = getBottom() + dy; //TODO 限制边界 if (left < limitLeft) { left = limitLeft; right = left + getWidth(); } if (top < limitTop) { top = limitTop; bottom = top + getHeight(); } if (right > limitRight) { right = limitRight; left = limitRight - getWidth(); } if (bottom > limitBottom) { bottom = limitBottom; top = limitBottom - getHeight(); } //TODO 更新view的位置 layout(left, top, right, bottom); lastX = (int) event.getRawX(); lastY = (int) event.getRawY(); break; case MotionEvent.ACTION_UP: dx = (int) event.getRawX() - downX; dy = (int) event.getRawY() - downY; if (dx + dy == 0 && System.currentTimeMillis() - lastDownInMills < 500) { //TODO x + y移动距离小于2px 且 触碰时间小于500ms 触发点击事件 if (l != null) { l.onClick(this); } } break; } return true; } }
源码下载地址(如果没有积分的,可以直接邮件[email protected]向我要):
https://download.****.net/download/yanjunhui2011/10365148
顺便吐槽一下CDSN近期的改动,设置密码复杂度要求过高,微信登录无法绑定已有账号。我这篇博文就是刚在微信那个账号下登录的,结果写完一看,咋就只有一篇呢?
还有下载,以前免积分的,全部默认3积分,且无法修改,我个人积分够用,我不希望那些需要我资源的用户因为积分无法下载,这严重违背了开源精神。
我觉得****再长久这么玩下去,就是在自掘坟墓。
国内这种平台还有很多,此文不过,必跳简书。