package com.sd.lib.switchbutton.gesture; import android.content.Context; import android.os.Build; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewParent; import java.util.LinkedList; import java.util.List; /** * 触摸事件处理帮助类<br> */ public class FTouchHelper { private float mCurrentX; private float mCurrentY; private float mLastX; private float mLastY; private float mDownX; private float mDownY; /** * 处理触摸事件 * * @param event */ public void processTouchEvent(MotionEvent event) { mLastX = mCurrentX; mLastY = mCurrentY; mCurrentX = event.getRawX(); mCurrentY = event.getRawY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mDownX = mCurrentX; mDownY = mCurrentY; break; default: break; } } public float getCurrentX() { return mCurrentX; } public float getCurrentY() { return mCurrentY; } public float getLastX() { return mLastX; } public float getLastY() { return mLastY; } public float getDownX() { return mDownX; } public float getDownY() { return mDownY; } //---------- Delta Start ---------- /** * 返回当前事件和上一次事件之间的x轴方向增量 * * @return */ public float getDeltaX() { return mCurrentX - mLastX; } /** * 返回当前事件和上一次事件之间的y轴方向增量 */ public float getDeltaY() { return mCurrentY - mLastY; } /** * 返回当前事件和{@link MotionEvent#ACTION_DOWN}事件之间的x轴方向增量 * * @return */ public float getDeltaXFromDown() { return mCurrentX - mDownX; } /** * 返回当前事件和{@link MotionEvent#ACTION_DOWN}事件之间的y轴方向增量 * * @return */ public float getDeltaYFromDown() { return mCurrentY - mDownY; } //---------- Delta End ---------- //---------- Degree Start ---------- /** * 返回当前事件和上一次事件之间的x轴方向夹角 * * @return */ public double getDegreeX() { final float dx = getDeltaX(); if (dx == 0) return 0; final float dy = getDeltaY(); final float angle = Math.abs(dy) / Math.abs(dx); return Math.toDegrees(Math.atan(angle)); } /** * 返回当前事件和上一次事件之间的y轴方向夹角 * * @return */ public double getDegreeY() { final float dy = getDeltaY(); if (dy == 0) return 0; final float dx = getDeltaX(); final float angle = Math.abs(dx) / Math.abs(dy); return Math.toDegrees(Math.atan(angle)); } /** * 返回当前事件和{@link MotionEvent#ACTION_DOWN}事件之间的x轴方向夹角 * * @return */ public double getDegreeXFromDown() { final float dx = getDeltaXFromDown(); if (dx == 0) return 0; final float dy = getDeltaYFromDown(); final float angle = Math.abs(dy) / Math.abs(dx); return Math.toDegrees(Math.atan(angle)); } /** * 返回当前事件和{@link MotionEvent#ACTION_DOWN}事件之间的y轴方向夹角 * * @return */ public double getDegreeYFromDown() { final float dy = getDeltaYFromDown(); if (dy == 0) return 0; final float dx = getDeltaXFromDown(); final float angle = Math.abs(dx) / Math.abs(dy); return Math.toDegrees(Math.atan(angle)); } //---------- Degree End ---------- /** * 是否是点击事件 * * @param event * @param context * @return */ public boolean isClick(MotionEvent event, Context context) { if (event.getAction() == MotionEvent.ACTION_UP) { final long clickTimeout = ViewConfiguration.getPressedStateDuration() + ViewConfiguration.getTapTimeout(); final int touchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); final long duration = event.getEventTime() - event.getDownTime(); final int dx = (int) getDeltaXFromDown(); final int dy = (int) getDeltaYFromDown(); if (duration < clickTimeout && dx < touchSlop && dy < touchSlop) return true; } return false; } //----------static method start---------- /** * 返回合理的增量 * * @param current 当前值 * @param min 最小值 * @param max 最大值 * @param delta 增量 * @return */ public static int getLegalDelta(int current, int min, int max, int delta) { if (delta == 0) return 0; final int future = current + delta; if (future < min) { delta += (min - future); } else if (future > max) { delta += (max - future); } return delta; } /** * 是否请求当前view的父view不要拦截事件 * * @param view * @param disallowIntercept true-请求父view不要拦截,false-父view可以拦截 */ public static void requestDisallowInterceptTouchEvent(View view, boolean disallowIntercept) { final ViewParent parent = view.getParent(); if (parent != null) parent.requestDisallowInterceptTouchEvent(disallowIntercept); } /** * view是否处于某个坐标点下面,相对父布局的坐标 * * @param view * @param x * @param y * @return */ public static boolean isViewUnder(View view, int x, int y) { return x >= view.getLeft() && x < view.getRight() && y >= view.getTop() && y < view.getBottom(); } /** * view是否处于某个坐标点下面,相对屏幕的坐标 * * @param view * @param x * @param y * @return */ public static boolean isViewUnderScreen(View view, int x, int y) { final int[] location = new int[2]; view.getLocationOnScreen(location); return x >= location[0] && x < location[0] + view.getWidth() && y >= location[1] && y < location[1] + view.getHeight(); } /** * 找到parent中处于指定坐标下的child * * @param parent * @param x * @param y * @return */ public static List<View> findChildrenUnder(ViewGroup parent, int x, int y) { final List<View> list = new LinkedList<>(); final int count = parent.getChildCount(); for (int i = count - 1; i >= 0; i--) { final View child = parent.getChildAt(i); if (isViewUnder(child, x, y)) list.add(child); } return list; } /** * 找到parent中处于指定坐标下最顶部的child(Z值最大,最后面添加) * * @param parent * @param x * @param y * @return */ public static View findTopChildUnder(ViewGroup parent, int x, int y) { if (Build.VERSION.SDK_INT < 21) return parent.getChildAt(parent.getChildCount() - 1); final List<View> list = findChildrenUnder(parent, x, y); if (list.isEmpty()) return null; View target = list.remove(0); for (View item : list) { if (item.getZ() > target.getZ()) target = item; } return target; } /** * view是否已经滚动到最左边 * * @param view * @return */ public static boolean isScrollToLeft(View view) { return !view.canScrollHorizontally(-1); } /** * view是否已经滚动到最顶部 * * @param view * @return */ public static boolean isScrollToTop(View view) { return !view.canScrollVertically(-1); } /** * view是否已经滚动到最右边 * * @param view * @return */ public static boolean isScrollToRight(View view) { return !view.canScrollHorizontally(1); } /** * view是否已经滚动到最底部 * * @param view * @return */ public static boolean isScrollToBottom(View view) { return !view.canScrollVertically(1); } //----------static method end---------- }