返回

HostStatusLayout解决Android导航栏适配问题

Android

HostStatusLayout解决Android导航栏适配问题

作为Android开发者,我们经常会遇到导航栏适配的问题。尤其是在Android 10及以上版本中,由于手势导航的引入,导航栏的显示和隐藏变得更加复杂。

我们可能认为大部分应用只需要使用状态栏,就可以使用系统去管理导航栏,却忽略了手动管理导航栏带来的好处。

事实上,手动管理导航栏可以避免许多常见的坑,包括背景设置的坑,判断导航栏是否存在、手动设置导航栏隐藏和显示的坑,以及获取导航栏高度的坑。

HostStatusLayout是一种处理Android导航栏适配的简单有效的方法。它是一个自定义ViewGroup,可以将状态栏和导航栏作为它的子视图,从而统一管理状态栏和导航栏。

HostStatusLayout的使用非常简单。首先,我们需要在布局文件中添加HostStatusLayout,然后将状态栏和导航栏作为它的子视图。接下来,我们需要在HostStatusLayout中实现onMeasure()和onLayout()方法,以正确地测量和布局状态栏和导航栏。

public class HostStatusLayout extends ViewGroup {

    private View mStatusBar;
    private View mNavigationBar;

    public HostStatusLayout(Context context) {
        super(context);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);

        int statusBarHeight = getStatusBarHeight();
        int navigationBarHeight = getNavigationBarHeight();

        mStatusBar.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
                MeasureSpec.makeMeasureSpec(statusBarHeight, MeasureSpec.EXACTLY));
        mNavigationBar.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
                MeasureSpec.makeMeasureSpec(navigationBarHeight, MeasureSpec.EXACTLY));

        setMeasuredDimension(width, height);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int statusBarHeight = getStatusBarHeight();
        int navigationBarHeight = getNavigationBarHeight();

        mStatusBar.layout(0, 0, mStatusBar.getMeasuredWidth(), statusBarHeight);
        mNavigationBar.layout(0, b - navigationBarHeight, mNavigationBar.getMeasuredWidth(), b);
    }

    private int getStatusBarHeight() {
        int statusBarHeight = 0;
        int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            statusBarHeight = getResources().getDimensionPixelSize(resourceId);
        }
        return statusBarHeight;
    }

    private int getNavigationBarHeight() {
        int navigationBarHeight = 0;
        int resourceId = getResources().getIdentifier("navigation_bar_height", "dimen", "android");
        if (resourceId > 0) {
            navigationBarHeight = getResources().getDimensionPixelSize(resourceId);
        }
        return navigationBarHeight;
    }
}

最后,我们需要在Activity的onWindowFocusChanged()方法中设置HostStatusLayout的fitsSystemWindows属性为false。

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    if (hasFocus) {
        mHostStatusLayout.setFitsSystemWindows(false);
    }
}

通过这种方式,我们可以使用HostStatusLayout来统一管理状态栏和导航栏,从而解决Android导航栏适配的问题。