【Launcher小知识点】home按键监听

    在Android中我们没法通过onKeyEvent监听到home按键监听事件,而Launcher中当我们进入到all apps页面候点击home按键则需要返回到Workspace中,这又是如何做到的呢。有以下三种方式。其中前两者其它应用也可参照使用,第三种只对Launcher管用。

监听广播

    在我们每次点击Home按键时系统会发出action为Intent.ACTION_CLOSE_SYSTEM_DIALOGS的广播,用于关闭系统Dialog,此广播可以来监听Home按键。而我们的Launcher也是这样做的。在Launcher的onCreate中:

        //home按键广播
        IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
        registerReceiver(mCloseSystemDialogsReceiver, filter);

    此广播监听的接收者时CloseSystemDialogsIntentReceiver。可以看到,在onReceive中它关闭了系统Dalog和panel。

private class CloseSystemDialogsIntentReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            closeSystemDialogs();
            Log.i("Launcher","closeSystemDialogs");
        }
    }

onUserLeaveHint方法

    在Activity中的onUserLeaveHint方法会在用户主动点击home按键时回调,此方法在onPause之前被调用,当然如果应用时被动进入后台,比如有用户来电导致当前页面因来电页面打开而进入后台,则onUserLeaveHint不会被调用。在Launcher中我们可以看见此方法被重写。

/**
     * 此方法当用户点击home键或者menu键离开launcher应用时调用
     */
    protected void onUserLeaveHint() {
        super.onUserLeaveHint();
        sPausedFromUserAction = true;
        Log.i(TAG,"onUserLeaveHint");
    }
导航栏home按键触发intent

    当我们点击SysytemUI中的导航栏(NavigationBar)中的home按钮(KeyButtonView)时其最终会调用到PhoneWindowManager中的startDockOrHome中,在此方法中会启动符合HomeIntent的页面(其实就是Launcher页面)。

 mHomeIntent =  new Intent(Intent.ACTION_MAIN, null);
        mHomeIntent.addCategory(Intent.CATEGORY_HOME);
        mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);

    在我们的Launcher中也在onNewIntent中对此intent进行了处理。

@Override
    protected void onNewIntent(Intent intent) {
        Log.i("Launcher","onNewIntent");
        long startTime = 0;
        if (DEBUG_RESUME_TIME) {
            startTime = System.currentTimeMillis();
        }
        super.onNewIntent(intent);

        // Close the menu
        if (Intent.ACTION_MAIN.equals(intent.getAction())) {
            // also will cancel mWaitingForResult.
            closeSystemDialogs();

            final boolean alreadyOnHome =
                    ((intent.getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT)
                        != Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);

            Runnable processIntent = new Runnable() {
                public void run() {
                    if (mWorkspace == null) {
                        // Can be cases where mWorkspace is null, this prevents a NPE
                        return;
                    }
                    Folder openFolder = mWorkspace.getOpenFolder();
                    // In all these cases, only animate if we're already on home
                    mWorkspace.exitWidgetResizeMode();
                    if (alreadyOnHome && mState == State.WORKSPACE && !mWorkspace.isTouchActive() &&
                            openFolder == null) {
                        mWorkspace.moveToDefaultScreen(true);
                    }

                    closeFolder();
                    exitSpringLoadedDragMode();

                    // If we are already on home, then just animate back to the workspace,
                    // otherwise, just wait until onResume to set the state back to Workspace
                    if (alreadyOnHome) {
                        showWorkspace(true);
                    } else {
                        mOnResumeState = State.WORKSPACE;
                    }

                    final View v = getWindow().peekDecorView();
                    if (v != null && v.getWindowToken() != null) {
                        InputMethodManager imm = (InputMethodManager)getSystemService(
                                INPUT_METHOD_SERVICE);
                        imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
                    }

                    // Reset AllApps to its initial state
                    if (!alreadyOnHome && mAppsCustomizeTabHost != null) {
                        mAppsCustomizeTabHost.reset();
                    }
                }
            };

            if (alreadyOnHome && !mWorkspace.hasWindowFocus()) {
                // Delay processing of the intent to allow the status bar animation to finish
                // first in order to avoid janky animations.
                mWorkspace.postDelayed(processIntent, 350);
            } else {
                // Process the intent immediately.
                processIntent.run();
            }

        }
        if (DEBUG_RESUME_TIME) {
            Log.d(TAG, "Time spent in onNewIntent: " + (System.currentTimeMillis() - startTime));
        }
    }


你可能感兴趣的:(安卓,Launcher源码阅读)