前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[Android][Framework]系统手势和状态栏

[Android][Framework]系统手势和状态栏

作者头像
wOw
发布2018-09-18 14:57:15
2.6K0
发布2018-09-18 14:57:15
举报
文章被收录于专栏:wOw的Android小站wOw的Android小站

PhoneWindowManager.java

PhoneWindowManager在init的时候会监听系统手势:

代码语言:javascript
复制
/** {@inheritDoc} */
@Override
public void init(Context context, IWindowManager windowManager,
                 WindowManagerFuncs windowManagerFuncs) {
...
// monitor for system gestures
mSystemGestures = new SystemGesturesPointerEventListener(context,
new SystemGesturesPointerEventListener.Callbacks() {
    @Override
    public void onSwipeFromTop() {
        if (mStatusBar != null) {
            requestTransientBars(mStatusBar);
        }
    }
    @Override
    public void onSwipeFromBottom() {
        if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_BOTTOM) {
            requestTransientBars(mNavigationBar);
        }
    }
    @Override
    public void onSwipeFromRight() {
        if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_RIGHT) {
            requestTransientBars(mNavigationBar);
        }
    }
    @Override
    public void onSwipeFromLeft() {
        if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_LEFT) {
            requestTransientBars(mNavigationBar);
        }
    }
    @Override
    public void onFling(int duration) {
        if (mPowerManagerInternal != null) {
            mPowerManagerInternal.powerHint(
                    PowerManagerInternal.POWER_HINT_INTERACTION, duration);
        }
    }
    @Override
    public void onDebug() {
        // no-op
    }
    @Override
    public void onDown() {
        mOrientationListener.onTouchStart();
    }
    @Override
    public void onUpOrCancel() {
        mOrientationListener.onTouchEnd();
    }
    @Override
    public void onMouseHoverAtTop() {
        mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
        Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
        msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS;
        mHandler.sendMessageDelayed(msg, 500);
    }
    @Override
    public void onMouseHoverAtBottom() {
        mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
        Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
        msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION;
        mHandler.sendMessageDelayed(msg, 500);
    }
    @Override
    public void onMouseLeaveFromEdge() {
        mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
    }
});
    ...
}

监听使用的是SystemGesturesPointerEventListener

代码语言:javascript
复制
/*
 * Listens for system-wide input gestures, firing callbacks when detected.
 * @hide
 */
public class SystemGesturesPointerEventListener implements PointerEventListener {

由注释可见,这个Listener监听系统级别的输入手势,由回调触发处理。

这个Listener实现了一个接口:

代码语言:javascript
复制
public interface PointerEventListener {
    /**
     * 1. onPointerEvent will be called on the service.UiThread.
     * 2. motionEvent will be recycled after onPointerEvent returns so if it is needed later a
     * copy() must be made and the copy must be recycled.
     **/
    public void onPointerEvent(MotionEvent motionEvent);
}

这个接口位于WindowManagerPolicy,是一个比较关键的接口。

回到Listener,看一下其对这个接口的具体实现:

代码语言:javascript
复制
@Override
public void onPointerEvent(MotionEvent event) {
    if (mGestureDetector != null && event.isTouchEvent()) {
        mGestureDetector.onTouchEvent(event);
    }
    switch (event.getActionMasked()) {
        case MotionEvent.ACTION_DOWN:
            mSwipeFireable = true;
            mDebugFireable = true;
            mDownPointers = 0;
            captureDown(event, 0);
            if (mMouseHoveringAtEdge) {
                mMouseHoveringAtEdge = false;
                mCallbacks.onMouseLeaveFromEdge();
            }
            mCallbacks.onDown();
            break;
        case MotionEvent.ACTION_POINTER_DOWN:
            captureDown(event, event.getActionIndex());
            if (mDebugFireable) {
                mDebugFireable = event.getPointerCount() < 5;
                if (!mDebugFireable) {
                    if (DEBUG) Slog.d(TAG, "Firing debug");
                    mCallbacks.onDebug();
                }
            }
            break;
        case MotionEvent.ACTION_MOVE:
            if (mSwipeFireable) {
                final int swipe = detectSwipe(event);
                mSwipeFireable = swipe == SWIPE_NONE;
                if (swipe == SWIPE_FROM_TOP) {
                    if (DEBUG) Slog.d(TAG, "Firing onSwipeFromTop");
                    mCallbacks.onSwipeFromTop();
                } else if (swipe == SWIPE_FROM_BOTTOM) {
                    if (DEBUG) Slog.d(TAG, "Firing onSwipeFromBottom");
                    mCallbacks.onSwipeFromBottom();
                } else if (swipe == SWIPE_FROM_RIGHT) {
                    if (DEBUG) Slog.d(TAG, "Firing onSwipeFromRight");
                    mCallbacks.onSwipeFromRight();
                } else if (swipe == SWIPE_FROM_LEFT) {
                    if (DEBUG) Slog.d(TAG, "Firing onSwipeFromLeft");
                    mCallbacks.onSwipeFromLeft();
                }
            }
            break;
        case MotionEvent.ACTION_HOVER_MOVE:
            if (event.isFromSource(InputDevice.SOURCE_MOUSE)) {
                if (!mMouseHoveringAtEdge && event.getY() == 0) {
                    mCallbacks.onMouseHoverAtTop();
                    mMouseHoveringAtEdge = true;
                } else if (!mMouseHoveringAtEdge && event.getY() >= screenHeight - 1) {
                    mCallbacks.onMouseHoverAtBottom();
                    mMouseHoveringAtEdge = true;
                } else if (mMouseHoveringAtEdge
                        && (event.getY() > 0 && event.getY() < screenHeight - 1)) {
                    mCallbacks.onMouseLeaveFromEdge();
                    mMouseHoveringAtEdge = false;
                }
            }
            break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            mSwipeFireable = false;
            mDebugFireable = false;
            mCallbacks.onUpOrCancel();
            break;
        default:
            if (DEBUG) Slog.d(TAG, "Ignoring " + event);
    }
}

其中mCallbacks就是

代码语言:javascript
复制
interface Callbacks {
    void onSwipeFromTop();
    void onSwipeFromBottom();
    void onSwipeFromRight();
    void onSwipeFromLeft();
    void onFling(int durationMs);
    void onDown();
    void onUpOrCancel();
    void onMouseHoverAtTop();
    void onMouseHoverAtBottom();
    void onMouseLeaveFromEdge();
    void onDebug();
}

即定义好的10种手势。

里面switch语句处理的操作也是MotionEvent最基本的操作。这里主要看一下从上往下滑动的事件是怎么计算的:

代码语言:javascript
复制
case MotionEvent.ACTION_MOVE:
    if (mSwipeFireable) {
        final int swipe = detectSwipe(event);
        mSwipeFireable = swipe == SWIPE_NONE;
        if (swipe == SWIPE_FROM_TOP) {
            if (DEBUG) Slog.d(TAG, "Firing onSwipeFromTop");
            mCallbacks.onSwipeFromTop();
  1. 在MotionEvent.ACTION_DOWN的时候,将mSwipeFireable置为true
  2. 通过detectSwipe()方法计算滑动方向
  3. 确定SWIPE_FROM_TOP事件,调用对应回调

来看看detectSwipe方法,具体见注释。

代码语言:javascript
复制
private int detectSwipe(MotionEvent move) {
    // 返回此event中历史的点数
    final int historySize = move.getHistorySize();
    final int pointerCount = move.getPointerCount();
    for (int p = 0; p < pointerCount; p++) {
        final int pointerId = move.getPointerId(p);
        final int i = findIndex(pointerId);
        if (i != UNTRACKED_POINTER) {
            for (int h = 0; h < historySize; h++) {
                // 两次事件的间隔
                final long time = move.getHistoricalEventTime(h);
                final float x = move.getHistoricalX(p, h);
                final float y = move.getHistoricalY(p,  h);
                final int swipe = detectSwipe(i, time, x, y);
                if (swipe != SWIPE_NONE) {
                    return swipe;
                }
            }
            final int swipe = detectSwipe(i, move.getEventTime(), move.getX(p), move.getY(p));
            if (swipe != SWIPE_NONE) {
                return swipe;
            }
        }
    }
    return SWIPE_NONE;
}

private int detectSwipe(int i, long time, float x, float y) {
    final float fromX = mDownX[i];
    final float fromY = mDownY[i];
    final long elapsed = time - mDownTime[i];
    if (DEBUG) Slog.d(TAG, "pointer " + mDownPointerId[i]
            + " moved (" + fromX + "->" + x + "," + fromY + "->" + y + ") in " + elapsed);
    if (fromY <= mSwipeStartThreshold/*status_bar_height 意味着从status_bar范围内开始*/
            && y > fromY + mSwipeDistanceThreshold/*status_bar_height 划出status_bar范围*/
            && elapsed < SWIPE_TIMEOUT_MS/*500ms*/) {
        return SWIPE_FROM_TOP;
    }
    if (fromY >= screenHeight - mSwipeStartThreshold
            && y < fromY - mSwipeDistanceThreshold
            && elapsed < SWIPE_TIMEOUT_MS) {
        return SWIPE_FROM_BOTTOM;
    }
    if (fromX >= screenWidth - mSwipeStartThreshold
            && x < fromX - mSwipeDistanceThreshold
            && elapsed < SWIPE_TIMEOUT_MS) {
        return SWIPE_FROM_RIGHT;
    }
    if (fromX <= mSwipeStartThreshold
            && x > fromX + mSwipeDistanceThreshold
            && elapsed < SWIPE_TIMEOUT_MS) {
        return SWIPE_FROM_LEFT;
    }
    return SWIPE_NONE;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-07-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档