android 为什么使用WindowInsetsControllerCompat#setAppearanceLightStatusBars()无法以编程方式设置windowLightStatusBar

pprl5pva  于 2023-02-02  发布在  Android
关注(0)|答案(3)|浏览(269)

我试图创建一个启动器应用程序,但我有问题时,试图改变API 30编程windowLightStatusBar和相同的代码工作完美的罚款below,我希望如果有人能帮我:)
下面是完整的类源代码:

public final class AppDrawer extends BottomSheetBehavior.BottomSheetCallback implements OnApplyWindowInsetsListener {

    private static boolean ALREADY_CREATED = false;

    private AppCompatActivity activity;
    private boolean dragging = false;
    private float radius;
    private int left, right, height, peekOver, oldState;
    private Rect displayRect = new Rect();
    private DisplayMetrics displayMetrics = new DisplayMetrics();
    private Insets navigationBarInsets = Insets.of(0, 0, 0, 0), cutoutInsets = navigationBarInsets;
    private WindowInsetsControllerCompat windowInsetsController;
    private Configuration oldConfiguration;
    private CardView cardView;
    private FrameLayout frameLayout;
    private BottomSheetBehavior<FrameLayout> bottomSheetBehavior;

    public AppDrawer(AppCompatActivity activity){
        if(ALREADY_CREATED) throw new IllegalArgumentException("The appDrawer object cannot be created more than once, clear the existing one from the memory first.");
        this.activity = activity;
        ALREADY_CREATED = true;
    }

    public void destroy(){
        activity = null;
        radius = 0.0f;
        left = right = height = peekOver = oldState = 0;
        displayRect = null;
        displayMetrics = null;
        navigationBarInsets = cutoutInsets = navigationBarInsets = null;
        windowInsetsController = null;
        oldConfiguration = null;
        cardView = null;
        frameLayout = null;
        bottomSheetBehavior = null;
        ALREADY_CREATED = false;
    }
    // WindowInsetControllerCompat is created and set from the activity that created this class
    public void setWindowInsetsController(@NonNull WindowInsetsControllerCompat windowInsetsController) { this.windowInsetsController = windowInsetsController; }

    public void initViews(View contentView){

        oldConfiguration = activity.getResources().getConfiguration();
        cardView = activity.findViewById(R.id.app_drawer_card_view);
        frameLayout = activity.findViewById(R.id.app_drawer_container);
        bottomSheetBehavior = BottomSheetBehavior.from(frameLayout);

        bottomSheetBehavior.addBottomSheetCallback(this);

        ViewCompat.setOnApplyWindowInsetsListener(contentView, this);

        updateVars();
    }

    @Override
    public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {
        if(dragging) return insets;
        cutoutInsets = insets.getInsets(WindowInsetsCompat.Type.displayCutout());
        navigationBarInsets = insets.getInsets(WindowInsetsCompat.Type.navigationBars());
        updateVars();
        if(bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_COLLAPSED) frameLayout.setPadding(left + navigationBarInsets.left, 0, right + navigationBarInsets.right, 0);
        return insets;
    }

    public void setConfiguration(Configuration configuration) { this.oldConfiguration = configuration; }

    private void updateWindowInsetsBars(int state){
        // here is the one i used
        if (state != BottomSheetBehavior.STATE_COLLAPSED && (oldConfiguration.uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_NO) {
            windowInsetsController.setAppearanceLightNavigationBars(true);
            windowInsetsController.setAppearanceLightStatusBars(true);
        } else {
            windowInsetsController.setAppearanceLightNavigationBars(false);
            windowInsetsController.setAppearanceLightStatusBars(false);
        }

        // here is the one of @Zain answer
        if (state != BottomSheetBehavior.STATE_COLLAPSED && (oldConfiguration.uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_NO) {
            new WindowInsetsControllerCompat(activity.getWindow(), activity.getWindow().getDecorView()).setAppearanceLightStatusBars(true);
            new WindowInsetsControllerCompat(activity.getWindow(), activity.getWindow().getDecorView()).setAppearanceLightNavigationBars(true);
        } else {
            new WindowInsetsControllerCompat(activity.getWindow(), activity.getWindow().getDecorView()).setAppearanceLightStatusBars(false);
            new WindowInsetsControllerCompat(activity.getWindow(), activity.getWindow().getDecorView()).setAppearanceLightNavigationBars(false);
        }

    }

    private void updateCardViewState(float slideOffset){
        float a = 1.f - slideOffset;
        cardView.setRadius(radius * a);
        frameLayout.setPadding((int) ((left + navigationBarInsets.left) * a) , 0, (int) ((right + navigationBarInsets.right) * a), 0);
        FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) cardView.getLayoutParams();
        layoutParams.height = (int) ((displayRect.height() + navigationBarInsets.bottom + cutoutInsets.top + cutoutInsets.bottom) * slideOffset + height * a);
        Log.d("AppDrawer", "card height: " + layoutParams.height + ", screen height: " + displayRect.height());
        //cardView.setAlpha(Math.min(slideOffset * 1.1f, 1.0f));
        cardView.setLayoutParams(layoutParams);
    }

    private void updateDisplayMetrics(){
        WindowManager windowManager = this.activity.getWindowManager();
        windowManager.getDefaultDisplay().getMetrics(displayMetrics);
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R){
            displayRect.set(windowManager.getCurrentWindowMetrics().getBounds());
            displayRect.bottom -= navigationBarInsets.bottom + cutoutInsets.top + cutoutInsets.bottom;
            displayRect.right -= navigationBarInsets.right + cutoutInsets.left + cutoutInsets.right;
        } else {
            displayRect.top = 0;
            displayRect.bottom = displayMetrics.heightPixels;
            displayRect.left = 0;
            displayRect.right = displayMetrics.widthPixels;
        }
    }

    private void updateVars(){
        updateDisplayMetrics();
        peekOver = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10f, displayMetrics);
        radius = radius == 0 ? cardView.getRadius() : radius;
        left = left == 0 ? frameLayout.getPaddingLeft() : left;
        right = right == 0 ? frameLayout.getPaddingRight() : right;
        height = height == 0 ? cardView.getLayoutParams().height : height;
        bottomSheetBehavior.setPeekHeight(height + navigationBarInsets.bottom + peekOver);
        if(oldState != 0) updateCardViewState(oldState == BottomSheetBehavior.STATE_COLLAPSED ? 0.0f : 1.0f);
    }

    @Override
    public void onStateChanged(@NonNull View bottomSheet, int newState) {
        dragging = newState == BottomSheetBehavior.STATE_DRAGGING;
        updateWindowInsetsBars(newState);
        oldState = newState;
    }

    @Override
    public void onSlide(@NonNull View bottomSheet, float slideOffset) { updateCardViewState(slideOffset); }
}

在API 30上,您可以看到navigationbar是白色的,而statusbar仍然是黑色的,即使两者都设置为false,但它根本不影响statusbar
Screenshot-1 on API 30
Screenshot-2 on API 30
但在API 29(低于API 29也能很好地工作)上,它们都很好地进行了更改。
Screenshot-1 on API 29
Screenshot-2 on API 29

pdsfdshx

pdsfdshx1#

这是一个平台错误。https://issuetracker.google.com/issues/180881870
要解决此问题,您只需将androidx.core:core-ktx更新为1.8.0-alpha03或更高版本。
详情请参考API变更https://developer.android.com/jetpack/androidx/releases/core#1.8.0-alpha03

fhity93d

fhity93d2#

    • 我找到了解决方案:**

在测试了一些不同的东西之后,我找到了导致这个问题的原因。

/* make system bars transparent */
private void setup(){
    Window window = getWindow();

    window.requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY);

    window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
    window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);

    WindowCompat.setDecorFitsSystemWindows(window, false);
    WindowInsetsControllerCompat windowInsetsController = new WindowInsetsControllerCompat(window, window.getDecorView());

    windowInsetsController.show(WindowInsetsCompat.Type.statusBars() | WindowInsetsCompat.Type.navigationBars() | WindowInsetsCompat.Type.systemBars());

    appDrawer.setWindowInsetsController(windowInsetsController);

}

当Activity调用onCreate()方法时,setup()方法会使状态栏/导航栏透明,除了一件事之外,一切都很好,我没有设置window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);,状态栏的变化也很好。

/* make system bars transparent */
private void setup(){
    Window window = getWindow();

    window.requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY);

    // Adding it fix the problem.
    window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);

    window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
    window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);

    WindowCompat.setDecorFitsSystemWindows(window, false);
    WindowInsetsControllerCompat windowInsetsController = new WindowInsetsControllerCompat(window, window.getDecorView());

    windowInsetsController.show(WindowInsetsCompat.Type.statusBars() | WindowInsetsCompat.Type.navigationBars() | WindowInsetsCompat.Type.systemBars());

    appDrawer.setWindowInsetsController(windowInsetsController);

}

希望有人会发现这个有用,而不是像我一样犯愚蠢的错误😅

    • 更新日期:**

我发现了真正导致问题的原因,是它补充说:

<item name="android:windowLightStatusBar">true</item>

到themes.xml文件使得设置statusbar为光编程不工作,我不知道是什么使导致的问题,但现在我知道了,我不必使用window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);,因为它是在API 30和更高版本的弃用,如@Zain指出。

oxosxuxt

oxosxuxt3#

对我来说,这是因为:

<item name="android:statusBarColor">@color/transparent</item>

这是阻止我作出改变,以状态栏文本颜色编程!删除后,我可以改变状态栏文本颜色编程再次!我希望这是有用的人!

相关问题