Fork me on GitHub

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

PhoneWindowManager.java

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

/** {@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

/*
* Listens for system-wide input gestures, firing callbacks when detected.
* @hide
*/
public class SystemGesturesPointerEventListener implements PointerEventListener {

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

这个Listener实现了一个接口:

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,看一下其对这个接口的具体实现:

@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就是

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最基本的操作。这里主要看一下从上往下滑动的事件是怎么计算的:

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方法,具体见注释。

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;
}
坚持原创技术分享,您的支持将鼓励我继续创作!