Zackratos / UltimateBarX

Make Android transparent statusbar and navigationbar easy.
Apache License 2.0
1.56k stars 166 forks source link

虚拟按键开启关闭导致底部导航栏显示问题 #36

Open MissBin opened 3 years ago

MissBin commented 3 years ago

手机开启虚拟按键底部正常显示 关闭虚拟按键底部还是有虚拟按键的高度 1624960502767

h4091 commented 3 years ago

你需要修改activity_root_view_parent的padding,可以参考下面的代码 NavigationBarHelper.java

package com.h4091.utils;

import android.app.Activity;
import android.content.Context;
import android.os.Build;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.graphics.Insets;
import androidx.core.view.OnApplyWindowInsetsListener;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

public class NavigationBarHelper {

    public static void setNavigationBarListener(@NonNull Activity activity,
        @Nullable NavigationStateListener listener) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
            Context context = activity.getApplicationContext();
            ViewCompat.setOnApplyWindowInsetsListener(activity.getWindow().getDecorView(),
                new OnApplyWindowInsetsListener() {
                    @Override
                    public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {
                        /** 虚拟导航栏或虚拟导航线高度(使用AndroidAutoSize会使该值发生变化) */
                        int height = AndroidUtil.getNavigationBarHeight(context);
                        boolean isShowing = false;
                        Insets temp = null;
                        if (insets != null) {
                            temp = Insets.of(
                                insets.getSystemWindowInsetLeft(),
                                insets.getSystemWindowInsetTop(),
                                insets.getSystemWindowInsetRight(),
                                insets.getSystemWindowInsetBottom()
                            );
                            // or
//                            Insets statusInsets = insets.getInsets(WindowInsetsCompat.Type.statusBars());
//                            Insets navInsets = insets.getInsets(WindowInsetsCompat.Type.navigationBars());
                            isShowing = height - temp.bottom >= 0;
                        }
                        if (listener != null) {
                            listener.onStateChanged(temp, isShowing);
                        }
                        return ViewCompat.onApplyWindowInsets(v, insets);
                    }
                });
        }
    }

    /**
     * 获取虚拟导航栏或虚拟导航线高度
     */
    public static int getNavigationBarHeight(@NonNull Context context) {
        Resources resources = context.getApplicationContext().getResources();
        int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
        return resources.getDimensionPixelSize(resourceId);
    }

    public interface NavigationStateListener {
        /**
         *
         * @param insets
         * @param isNavShowing 是否显示虚拟导航栏或虚拟导航线
         */
        void onStateChanged(Insets insets, boolean isNavShowing);
    }
}

BaseActivity.java

package com.h4091.base.view;

import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;

import androidx.annotation.ColorRes;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.Insets;

import com.h4091.R;
import com.h4091.BuildConfig;
import com.h4091.utils.NavigationBarHelper;
import com.zackratos.ultimatebarx.ultimatebarx.UltimateBarX;

import me.jessyan.autosize.internal.CustomAdapt;

public abstract class BaseActivity extends AppCompatActivity implements CustomAdapt {

    protected boolean isShowNavigationBar;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.setStatusBar();
        this.setNavigationBar();
    }

    @Override
    public boolean isBaseOnWidth() {
        return false;
    }

    @Override
    public float getSizeInDp() {
        // 使用AndroidManifest中声明的设计图尺寸
        return 667;
    }

    /**
     * 设置状态栏
     */
    protected void setStatusBar() {
        UltimateBarX.with(this)
            .fitWindow(isFitStatusBar())
            .colorRes(getStatusBarColor())
            .light(isLight())
            .applyStatusBar();
    }

    /**
     * 是否侵入状态栏,默认true
     * @return true:不侵入,false:侵入
     */
    protected boolean isFitStatusBar() {
        return true;
    }

    /**
     * 状态栏颜色,默认R.color.white
     */
    @ColorRes
    protected int getStatusBarColor() {
        return R.color.white;
    }

    /**
     * 是否light模式,默认true
     * @return true: light模式
     */
    protected boolean isLight() {
        return true;
    }

    @ColorRes
    protected int getNavigationBarColor() {
        return R.color.blue;
    }

    public boolean isShowNavigationBar() {
        return isShowNavigationBar;
    }

    /**
     * 设置导航栏
     */
    protected void setNavigationBar() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            getWindow().setNavigationBarColor(ContextCompat.getColor(this, getNavigationBarColor()));
        }
        NavigationBarHelper.setNavigationBarListener(this, new NavigationBarHelper.NavigationStateListener() {
            @Override
            public void onStateChanged(Insets insets, boolean isNavShowing) {
                isShowNavigationBar = isNavShowing;
                getWindow().getDecorView()
                    .findViewWithTag("activity_root_view_parent")
                    .setPadding(insets.left,
                        isFitStatusBar() ? insets.top : 0,
                        insets.right,
                        insets.bottom);
            }
        });
    }
}

最后要说的是:

getSystemWindowInsetLeft()

方法已经被标记为deprecated,你也可以使用

Insets statusInsets = insets.getInsets(WindowInsetsCompat.Type.statusBars());
Insets navInsets = insets.getInsets(WindowInsetsCompat.Type.navigationBars());

这两个来实现,具体取决于你。

lihuiqiang123 commented 3 years ago

我在realme手机也遇到类似问题,可以先获取Navigation的默认配置,然后设置fitWindow = false ,然后覆盖默认配置,在配置StateBar,可以解决底部导航白条的问题。代码如下:

val config = UltimateBarX.getNavigationBarConfig(this).fitWindow(false)
UltimateBarX.get(this).config(config).applyNavigationBar()
UltimateBarX.with(this)
   .light(true)
   .applyStatusBar()
Zackratos commented 3 years ago

你是在当前 Activity 打开的状态下直接关闭导航栏吗

Zackratos commented 2 years ago

如果你只需要设置状态栏而不需要设置导航栏的话,更新到 0.8.0 版本,使用 statusBarOnly 方法替换 statusBar 方法可以彻底解决这个问题 @h4091 @MissBin @lihuiqiang123