需求任意app中依次点击屏幕四个角返回Launcher。
主要目标是要捕获全局Touch事件,思路是可以在View.java中dispatchTouchEvent或者参考系统手势实现。鉴于在View中操作容易误触进入其他界面,最后参考系统手势实现。
framework中有一个专门用来监听系统手势的监听器SystemGesturesPointerEventListener.java
直接在这里实现,主要业务在onPointerEvent方法中实现。
先写检测手势触摸的逻辑
java
private void checkFourCornersClick(MotionEvent event) {
float x = event.getX();
float y = event.getY();
if (screenWidth == 0 || screenHeight == 0) {
return;
}
//四角位置定位,这部分可以根据自己的需要定义,触摸点的位置,顺序,大小等
int corner = getCornerPosition(x, y);
if (corner != -1) {
if (DEBUG) Slog.d(TAG_CORNERS, "Corner clicked: " + corner + " at (" + x + ", " + y + ")");
//四角touch顺序判断
if (isExpectedNextCorner(corner)) {
mClickedCorners.add(corner);//手势符合后添加到集合
Slog.i(TAG_CORNERS, "Correct corner order, progress: " + mClickedCorners.size() + "/4");
resetCornerTimeout();//这里需要判断触摸超时业务
//四角全部touch后执行下一步任务
if (mClickedCorners.size() == 4) {
Slog.i(TAG_CORNERS, "All four corners clicked! Triggering action.");
performFourCornersAction();
}
} else {
Slog.w(TAG_CORNERS, "Wrong corner order. Expected: " + CORRECT_ORDER[mClickedCorners.size()]
+ ", got: " + corner + ". Reset.");
resetCornerClick();//未按流程触摸,重置手势集合
}
}
}
四角定位和顺序判断,mCornerSize随意,这里直接写的50
java
private int getCornerPosition(float x, float y) {
if (x <= mCornerSize && y <= mCornerSize) {
return 1;//返回值方便顺序判断
}
if (x <= mCornerSize && y >= screenHeight - mCornerSize) {
return 2;
}
if (x >= screenWidth - mCornerSize && y <= mCornerSize) {
return 3;
}
if (x >= screenWidth - mCornerSize && y >= screenHeight - mCornerSize) {
return 4;
}
return -1;
}
private boolean isExpectedNextCorner(int corner) {
if (mClickedCorners.size() >= CORRECT_ORDER.length) {
return false;
}
int nextExpected = CORRECT_ORDER[mClickedCorners.size()];
return corner == nextExpected;
}
执行手势完成后的任务
java
private void performFourCornersAction() {
resetCornerClick();
try {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addCategory(Intent.CATEGORY_HOME);
mContext.startActivity(intent);
} catch (Exception e) {
Slog.e(TAG_CORNERS, "Failed to start activity", e);
}
Slog.i(TAG_CORNERS, "Four corners gesture action completed");
}
onPointerEvent检测手势
java
@Override
public void onPointerEvent(MotionEvent event) {
if (mGestureDetector != null && event.isTouchEvent()) {
mGestureDetector.onTouchEvent(event);
}
//mh@预留手势开关{
if (mEnableFourCornersGestures && event.getAction() == MotionEvent.ACTION_DOWN) {
checkFourCornersClick(event);
}
//mh@}
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
mSwipeFireable = true;
mDebugFireable = true;
mDownPointers = 0;
captureDown(event, 0);
if (mMouseHoveringAtLeft) {
mMouseHoveringAtLeft = false;
...
写一个init方法,主要初始化开关和触摸点的大小
java
private void initFourCornersGesture() {
//触摸超时handler
mCornerTimeoutRunnable = new Runnable() {
@Override
public void run() {
resetCornerClick();
if (DEBUG) Slog.d(TAG_CORNERS, "Four corners gesture timeout, reset");
}
};
//自定义ContentObserver,监听开关变化
mSettingsObserver = new SettingsObserver(mHandler);
mSettingsObserver.observe();
updateFourCornersEnabled();
updateCornerSize();
Slog.i(TAG_CORNERS, "Four corners gesture initialized, enabled: " + mEnableFourCornersGestures
+ ", corner size: " + mCornerSize + "px");
}
private void updateFourCornersEnabled() {
try {
mEnableFourCornersGestures = Settings.Global.getInt(mContext.getContentResolver(),
SETTINGS_KEY_FOUR_CORNERS, 0) == 1;
} catch (Exception e) {
Slog.e(TAG_CORNERS, "Failed to read settings, using default", e);
mEnableFourCornersGestures = true;
}
}
//触摸超时,重置计时器
private void resetCornerTimeout() {
mHandler.removeCallbacks(mCornerTimeoutRunnable);
mHandler.postDelayed(mCornerTimeoutRunnable, CORNER_CLICK_TIMEOUT_MS);
}
//重置手势集合
private void resetCornerClick() {
mClickedCorners.clear();
mHandler.removeCallbacks(mCornerTimeoutRunnable);
if (DEBUG) Slog.d(TAG_CORNERS, "Corner click state reset");
}
private class SettingsObserver extends ContentObserver {
SettingsObserver(Handler handler) {
super(handler);
}
void observe() {
Uri uri = Settings.Global.getUriFor(SETTINGS_KEY_FOUR_CORNERS);
mContext.getContentResolver().registerContentObserver(uri, false, this);
if (DEBUG) Slog.d(TAG_CORNERS, "Settings observer registered for: " + uri);
}
@Override
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
if (uri == null || SETTINGS_KEY_FOUR_CORNERS.equals(uri.getLastPathSegment())) {
updateFourCornersEnabled();
Slog.i(TAG_CORNERS, "Four corners gesture setting changed to: " + mEnableFourCornersGestures);
if (!mEnableFourCornersGestures) {
resetCornerClick();
}
}
}
}
在构造方法中初始化
java
SystemGesturesPointerEventListener(Context context, Handler handler, Callbacks callbacks) {
mContext = checkNull("context", context);
mHandler = handler;
mCallbacks = checkNull("callbacks", callbacks);
onConfigurationChanged();
initFourCornersGesture();//mh@
}
最后在设置--开发者选项中实现一个开关控制
参考: