Detecting when system buttons are visible while using 'immersive mode'

后端 未结 4 601
谎友^
谎友^ 2020-12-28 08:39

I\'m currently using immersive mode (API 19) for one of my Activities as follows:

getWindow().getDecorView()
            .setSystemUiVisibility(
                     


        
相关标签:
4条回答
  • 2020-12-28 09:11

    I have found a solution that suits me even though it's not perfect. I set the UI visiblity to View.SYSTEM_UI_FLAG_IMMERSIVE instead of View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY and when I receive the onSystemUiVisibilityChange callback, I delay a message to an Handler to reset the UI Visibility. Here is the code :

    private static final int FULL_SREEN_MSG = 10;
    private static final long TIME_BEFORE_HIDE_UI = 2 * DateUtils.SECOND_IN_MILLIS;
    
    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == FULL_SREEN_MSG) {
                setFullscreen();
            }
        }
    };
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setFullscreen();
        getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(this);
    }
    
    private void setFullscreen() {
        getWindow().getDecorView().setSystemUiVisibility(
                View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                        | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                        | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
                        | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
                        | View.SYSTEM_UI_FLAG_IMMERSIVE);
    }
    
    @Override
    public void onSystemUiVisibilityChange(int visibility) {
        if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
            mHandler.sendEmptyMessageDelayed(FULL_SREEN_MSG, TIME_BEFORE_HIDE_UI);
        }
    }
    
    0 讨论(0)
  • 2020-12-28 09:12

    From Android Developers video, when you're in immersive sticky mode, the app isn't notified.

    Immersive sticky mode starts at 6:56 and around 7:25 Roman Nurik tells that the listener won't be triggered.

    This is the video: http://youtu.be/cBi8fjv90E4?t=6m56s

    0 讨论(0)
  • 2020-12-28 09:12

    UPDATED ANSWER:

    Set an OnSystemUiVisibilityChangeListener, force immersive mode when visibility is 0 (rather than 6).

    if(android.os.Build.VERSION.SDK_INT >= 19) {
            getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() {
                @Override
                public void onSystemUiVisibilityChange(int visibility) {
                    if(visibility == 0) {
                        getWindow().getDecorView().setSystemUiVisibility(
                                View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                                | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                                | View.SYSTEM_UI_FLAG_FULLSCREEN
                                | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
                    }
                }
            });
        }
    

    OLD, NASTY ANSWER:

    this is nasty, but it is a solution IFF you were showing an ActionBar:

    • add an OnGlobalLayoutListener to the ViewTreeObserver of 'action_bar_container'.
    • in the OnGlobalLayoutListener implementation, check if 'action_bar_container' visibility if GONE or not.
    • when it moved from GONE to !GONE (and assuming you were in immersive mode) then force immersive mode again via the setSystemUiVisibility method.

    if(android.os.Build.VERSION.SDK_INT >= 19) {
            int actionBarContainerId = Resources.getSystem().getIdentifier("action_bar_container", "id", "android");
            ((ViewGroup)findViewById(actionBarContainerId)).getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    int actionBarContainerId = Resources.getSystem().getIdentifier("action_bar_container", "id", "android");
                    ViewGroup actionBarContainer = (ViewGroup) findViewById(actionBarContainerId);
                    if(actionBarContainer.getVisibility() == View.GONE) {
                        if(DEBUG) Log.d(TAG, "...PROBABLY IN IMMERSIVE MODE AND ALL IS GOOD!..");
                    } else {
                        if(DEBUG) Log.d(TAG, "...PROBABLY NO LONGER IN IMMERSIVE MODE, HEY..");
                        getWindow().getDecorView().setSystemUiVisibility(
                                View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                                | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                                | View.SYSTEM_UI_FLAG_FULLSCREEN
                                | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
                    }
    
                }
            });
        }
    
    0 讨论(0)
  • 2020-12-28 09:28

    In 4.4, the app will not receive any indication when the transient system bars are revealed or auto-hidden (under IMMERSIVE_STICKY), either via the OnSystemUiVisibilityChangeListener or other means.

    You can listen for edge swipes similar to the system gesture listener as a guess, but this is not part of the public api, it may change in future releases and differ across devices.

    I'm curious what you want to do when the transient system bars are shown/hidden.

    0 讨论(0)
提交回复
热议问题