写点什么

自定义 View:触摸反馈

用户头像
Changing Lin
关注
发布于: 刚刚
自定义View:触摸反馈

1.知识点

  • 概念模型

  • onTouchEvent:Implement this method to handle touch screen motion events.

  • getAction():包含 2 个信息,第几个手指的按下和抬起,触摸事件

  • getActionMasked():多点触摸开始支持,

2.原理

  • 点击如何实现?

  • 长按如何实现?


3.代码

public boolean onTouchEvent(MotionEvent event) {        final float x = event.getX();        final float y = event.getY(); //获取位置基本信息        final int viewFlags = mViewFlags;        final int action = event.getAction();
final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE; // CONTEXT_CLICKABLE鼠标右键、长按点击
if ((viewFlags & ENABLED_MASK) == DISABLED) { if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) { setPressed(false); } mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN; // A disabled view that is clickable still consumes the touch // events, it just doesn't respond to them. return clickable;// 阻拦触摸事件传递 } if (mTouchDelegate != null) { if (mTouchDelegate.onTouchEvent(event)) { return true; } }
if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {// api 26后加入 解释性提示 switch (action) { case MotionEvent.ACTION_UP: mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN; if ((viewFlags & TOOLTIP) == TOOLTIP) { handleTooltipUp(); } if (!clickable) { removeTapCallback(); removeLongPressCallback(); mInContextButtonPress = false; mHasPerformedLongPress = false; mIgnoreNextUpEvent = false; break; } boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0; if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) { // take focus if we don't have it already and we should in // touch mode. boolean focusTaken = false; if (isFocusable() && isFocusableInTouchMode() && !isFocused()) { focusTaken = requestFocus(); }
if (prepressed) { // The button is being released before we actually // showed it as pressed. Make it show the pressed // state now (before scheduling the click) to ensure // the user sees it. setPressed(true, x, y); }
if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) { // This is a tap, so remove the longpress check removeLongPressCallback();
// Only perform take click actions if we were in the pressed state if (!focusTaken) { // Use a Runnable and post this rather than calling // performClick directly. This lets other visual state // of the view update before click actions start. if (mPerformClick == null) { mPerformClick = new PerformClick(); } if (!post(mPerformClick)) { performClickInternal(); } } }
if (mUnsetPressedState == null) { mUnsetPressedState = new UnsetPressedState(); }
if (prepressed) { postDelayed(mUnsetPressedState, ViewConfiguration.getPressedStateDuration()); } else if (!post(mUnsetPressedState)) { // If the post failed, unpress right now mUnsetPressedState.run(); }
removeTapCallback(); } mIgnoreNextUpEvent = false; break;
case MotionEvent.ACTION_DOWN: if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) { // 是否触摸屏幕 mPrivateFlags3 |= PFLAG3_FINGER_DOWN; // 标记为手指按下 } mHasPerformedLongPress = false;
if (!clickable) { checkForLongClick( ViewConfiguration.getLongPressTimeout(), x, y, TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS); break; }
if (performButtonActionOnTouchDown(event)) { // 是否是鼠标右键触摸 break; }
// Walk up the hierarchy to determine if we're inside a scrolling container. boolean isInScrollingContainer = isInScrollingContainer();
// For views inside a scrolling container, delay the pressed feedback for // a short period in case this is a scroll. if (isInScrollingContainer) { mPrivateFlags |= PFLAG_PREPRESSED; if (mPendingCheckForTap == null) { mPendingCheckForTap = new CheckForTap(); } mPendingCheckForTap.x = event.getX(); mPendingCheckForTap.y = event.getY(); postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout()); } else { // Not inside a scrolling container, so show the feedback right away setPressed(true, x, y); checkForLongClick( ViewConfiguration.getLongPressTimeout(), x, y, TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS); } break;
case MotionEvent.ACTION_CANCEL: if (clickable) { setPressed(false); } removeTapCallback(); removeLongPressCallback(); mInContextButtonPress = false; mHasPerformedLongPress = false; mIgnoreNextUpEvent = false; mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN; break;
case MotionEvent.ACTION_MOVE: if (clickable) { drawableHotspotChanged(x, y); }
final int motionClassification = event.getClassification(); final boolean ambiguousGesture = motionClassification == MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE; int touchSlop = mTouchSlop; if (ambiguousGesture && hasPendingLongPressCallback()) { if (!pointInView(x, y, touchSlop)) { // The default action here is to cancel long press. But instead, we // just extend the timeout here, in case the classification // stays ambiguous. removeLongPressCallback(); long delay = (long) (ViewConfiguration.getLongPressTimeout() * mAmbiguousGestureMultiplier); // Subtract the time already spent delay -= event.getEventTime() - event.getDownTime(); checkForLongClick( delay, x, y, TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS); } touchSlop *= mAmbiguousGestureMultiplier; }
// Be lenient about moving outside of buttons if (!pointInView(x, y, touchSlop)) { // Outside button // Remove any future long press/tap checks removeTapCallback(); removeLongPressCallback(); if ((mPrivateFlags & PFLAG_PRESSED) != 0) { setPressed(false); } mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN; }
final boolean deepPress = motionClassification == MotionEvent.CLASSIFICATION_DEEP_PRESS; if (deepPress && hasPendingLongPressCallback()) { // process the long click action immediately removeLongPressCallback(); checkForLongClick( 0 /* send immediately */, x, y, TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS); }
break; }
return true; }
return false; }
复制代码


发布于: 刚刚阅读数: 2
用户头像

Changing Lin

关注

获得机遇的手段远超于固有常规之上~ 2020.04.29 加入

我能做的,就是调整好自己的精神状态,以最佳的面貌去面对那些未曾经历过得事情,对生活充满热情和希望。

评论

发布
暂无评论
自定义View:触摸反馈