How do I maintain the Immersive Mode in Spinner?
Asked Answered
I

2

6

I use immersive-sticky mode to hide the navigation bar and action bar:

@TargetApi(19)
private void setImmersiveMode() {
    if (Build.VERSION.SDK_INT >= 19) {
        View decorView = getWindow().getDecorView();
        int uiOptions = getImmersiveUiOptions(decorView);
        decorView.setSystemUiVisibility(uiOptions);
        ActionBar actionBar = getActionBar();
        if (null!=actionBar) {
            actionBar.hide();
        }
    }
}

When a Spinner is touched, the navigationBar is shown and immersive mode is disabled.

This solution works for Dialogs:

dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
dialog.show();
dialog.getWindow().getDecorView().setSystemUiVisibility(
context.getWindow().getDecorView().getSystemUiVisibility());
dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);

But Spinner doesn't have show() method that I could overwrite.

How can I prevent System UI from showing when a Spinner is touched?

Edit: this question is about keeping the Navigation Bar hidden (BackButton, HomeButton and RecentTasksButton). I'm already using FLAG_FULLSCREEN

getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);   
Ineffective answered 28/3, 2018 at 12:4 Comment(1)
Possible duplicate of setSystemUIVsibility full screen disables when using SpinnerIndonesian
E
7

I know this is super late, but I finally found a solution to this here:

Just call this on your spinner before using it:

import android.widget.PopupWindow
import android.widget.Spinner

fun Spinner.avoidDropdownFocus() {
    try {
        val isAppCompat = this is androidx.appcompat.widget.AppCompatSpinner
        val spinnerClass = if (isAppCompat) androidx.appcompat.widget.AppCompatSpinner::class.java else Spinner::class.java
        val popupWindowClass = if (isAppCompat) androidx.appcompat.widget.ListPopupWindow::class.java else android.widget.ListPopupWindow::class.java

        val listPopup = spinnerClass
                .getDeclaredField("mPopup")
                .apply { isAccessible = true }
                .get(this)
        if (popupWindowClass.isInstance(listPopup)) {
            val popup = popupWindowClass
                    .getDeclaredField("mPopup")
                    .apply { isAccessible = true }
                    .get(listPopup)
            if (popup is PopupWindow) {
                popup.isFocusable = false
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}
Engulf answered 29/2, 2020 at 7:2 Comment(0)
W
1

For everyone who, like me, will start rewriting solution pasted by @Quinn from Kotlin to Java and later they will find out that on the linked git repo is the solution in Java also, I am pasting it here:

import android.widget.ListPopupWindow;
import android.widget.PopupWindow;
import android.widget.Spinner;

public static void avoidSpinnerDropdownFocus(Spinner spinner) {
    try {
        Field listPopupField = Spinner.class.getDeclaredField("mPopup");
        listPopupField.setAccessible(true);
        Object listPopup = listPopupField.get(spinner);
        if (listPopup instanceof ListPopupWindow) {
            Field popupField = ListPopupWindow.class.getDeclaredField("mPopup");
            popupField.setAccessible(true);
            Object popup = popupField.get((ListPopupWindow) listPopup);
            if (popup instanceof PopupWindow) {
                ((PopupWindow) popup).setFocusable(false);
            }
        }
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}
Wardroom answered 5/3, 2020 at 8:29 Comment(3)
Haha, sorry about that!Engulf
No problem :) Thank you for your answer.Wardroom
I had a problem with this on Android 9 which was related to using androidx.appcompat:appcompat version 1.0.2. Upgrading to 1.2.0 avoided the problem and made this workaround work again.Detribalize

© 2022 - 2024 — McMap. All rights reserved.