ViewDragLogic.java package com.cnsunrun.user.mode;import android.animation.ObjectAnimator;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import android.view.ViewParent;import android.view.animation.De
package com.cnsunrun.user.mode; import android.animation.ObjectAnimator; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; import android.view.animation.DecelerateInterpolator; /** * 控件拖动逻辑处理 * Created by WQ on 2017/10/23. */ public class ViewDragLogic implements View.OnTouchListener{ private View targetView; public ViewDragLogic(final View targetView) { this.targetView=targetView; this.targetView.setOnTouchListener(this); } private int parentHeight; private int parentWidth; private int lastX; private int lastY; private boolean isDrag; @Override public boolean onTouch(View v, MotionEvent event) { int rawX = (int) event.getRawX(); int rawY = (int) event.getRawY(); switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: targetView.setPressed(true); isDrag = false; ViewParent viewParent = targetView.getParent(); viewParent.requestDisallowInterceptTouchEvent(true); lastX = rawX; lastY = rawY; ViewGroup parent; parent = (ViewGroup) viewParent; parentHeight = parent.getHeight(); parentWidth = parent.getWidth(); break; case MotionEvent.ACTION_MOVE: if (parentHeight <= 0 || parentWidth == 0) { isDrag = false; break; } else { isDrag = true; } int dx = rawX - lastX; int dy = rawY - lastY; //这里修复一些华为手机无法触发点击事件 int distance = (int) Math.sqrt(dx * dx + dy * dy); if (distance == 0) { isDrag = false; break; } float x = targetView.getX() + dx; float y = targetView.getY() + dy; //检测是否到达边缘 左上右下 x = x < 0 ? 0 : x > parentWidth - targetView.getWidth() ? parentWidth - targetView.getWidth() : x; y = targetView.getY() < 0 ? 0 : targetView.getY() + targetView.getHeight() > parentHeight ? parentHeight - targetView.getHeight() : y; targetView.setX(x); targetView.setY(y); lastX = rawX; lastY = rawY; break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: if (!isNotDrag()) { //恢复按压效果 targetView.setPressed(false); if (rawX >= parentWidth / 2) { //靠右吸附 targetView.animate().setInterpolator(new DecelerateInterpolator()) .setDuration(500) .xBy(parentWidth - targetView.getWidth()-getRightMargin(targetView) - targetView.getX()) .start(); } else { //靠左吸附 ObjectAnimator oa = ObjectAnimator.ofFloat(targetView, "x", targetView.getX(), getLeftMargin(targetView)); oa.setInterpolator(new DecelerateInterpolator()); oa.setDuration(500); oa.start(); } } break; } //如果是拖拽则消s耗事件,否则正常传递即可。 return !isNotDrag() || targetView.onTouchEvent(event); } /** * 获取左右margin值 * @param view * @return */ int getLeftMargin(View view){ if(view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams){ return ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).leftMargin; } return 0; } int getRightMargin(View view){ if(view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams){ return ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).rightMargin; } return 0; } /** * 是否拖拽中 * @return */ public boolean isDraging(){ return isDrag; } private boolean isNotDrag() { if(targetView ==null)return true; return !isDrag ; } }