美文网首页Android开发
浅析Android 9.0导航栏的变化

浅析Android 9.0导航栏的变化

作者: Soetsu | 来源:发表于2018-10-30 19:43 被阅读0次

资源变化

在Android 8.0及以前,导航栏NavigationBarView上的每个KeyButton的图标资源几乎都是用的PNG图片,这类资源使用通常需要在不同分辨率的drawable-xxx目录下面都加入相应的文件,这就导致一些客制化需求的修改也变得比较费事。

矢量图在不同分辨率下经过放大或缩小后,图片的质量都不会下降,使用矢量图替代PNG资源可以降低应用内存的占用。在9.0之前的版本,Google已经在逐步使用Vector矢量图来替换PNG资源,比如导航栏上最右边的切换输入法的按钮,在8.0版本上已经改为了矢量图,而到了9.0版本上导航栏的所有按钮资源都已经被替换成矢量图。

<!-- back按钮的Vector资源 -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="28dp"
    android:height="28dp"
    android:viewportWidth="28"
    android:viewportHeight="28">

    <path
        android:fillColor="?attr/singleToneColor"
        android:pathData="M6.49,14.86c-0.66-0.39-0.66-1.34,0-1.73l6.02-3.53l5.89-3.46C19.11,5.73,20,6.26,20,7.1V14v6.9 c0,0.84-0.89,1.37-1.6,0.95l-5.89-3.46L6.49,14.86z" />
</vector>

黑白色按钮

其实这一点的变化并不大,之前已经提到在8.0版本上已经有图标开始使用矢量图了,所以后续9.0上也是用同样的做法修改的。

我们知道Android 8.0上谷歌引入了一个新的flag:View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,应用可以通过使用这个flag来轻松切换导航栏上的按钮的颜色(黑 - 白):SystemUI上负责显示按钮的是一类KeyButtonDrawable,这个类继承自LayerDrawable,它会把drawable资源层叠显示,我们设置的白色与黑色的drawable会被一个在上一个在下的放在这个容器中,当需要切换颜色时,KeyButtonDrawable会通过分别设置两边的alpha透明度的方式来实现。

8.08.1版本上,NavigationBarView需要传入两个drawable资源,一个黑色的一个白色的:

    private void updateIcons(Context ctx, Configuration oldConfig, Configuration newConfig) {
        ...
        if (oldConfig.densityDpi != newConfig.densityDpi
                || oldConfig.getLayoutDirection() != newConfig.getLayoutDirection()) {
            mBackIcon = getDrawable(ctx, R.drawable.ic_sysbar_back, R.drawable.ic_sysbar_back_dark);
            ...
            mHomeDefaultIcon = getDrawable(ctx,
                    R.drawable.ic_sysbar_home, R.drawable.ic_sysbar_home_dark);
            mRecentIcon = getDrawable(ctx,
                    R.drawable.ic_sysbar_recent, R.drawable.ic_sysbar_recent_dark);
            ...
        }
    }

而在9.0上由于这些Vector的fillColor用的是attr值,之后可根据不同attr下获得相应的Context来设置不同的color,所以只需要传入一个xml的drawable资源即可:

    private void updateIcons(Context ctx, Configuration oldConfig, Configuration newConfig) {
        int dualToneDarkTheme = Utils.getThemeAttr(ctx, R.attr.darkIconTheme);
        int dualToneLightTheme = Utils.getThemeAttr(ctx, R.attr.lightIconTheme);
        Context lightContext = new ContextThemeWrapper(ctx, dualToneLightTheme);
        Context darkContext = new ContextThemeWrapper(ctx, dualToneDarkTheme);
        ...
        if (oldConfig.densityDpi != newConfig.densityDpi
                || oldConfig.getLayoutDirection() != newConfig.getLayoutDirection()) {
            mBackIcon = getBackDrawable(lightContext, darkContext);
            mRecentIcon = getDrawable(lightContext, darkContext, R.drawable.ic_sysbar_recent);
            ...
        }
    }

    private KeyButtonDrawable getDrawable(Context lightContext, Context darkContext,
            @DrawableRes int icon, boolean hasShadow) {
        return KeyButtonDrawable.create(lightContext, lightContext.getDrawable(icon),
                darkContext.getDrawable(icon), hasShadow);
    }

并且在使用了矢量图后,9.0也不再需要保留箭头朝下的back按钮图标资源(软键盘弹出后back键会变成箭头朝下),KeyButtonDrawable内部已经实现了用于图标旋转的方法:定义rotateDegrees值后调用invalidateSelf(),然后在draw()方法里根据rotateDegrees来旋转Canvas。

屏幕旋转

在绝大部分时候 —— 尤其是躺在床上的时候,为了避免屏幕突然被旋转,我们可能都会将屏幕自动旋转功能关闭。毕竟,我们并非时时都需要横屏观看内容。

但一旦需要让屏幕旋转时,我们又得手动在快捷设置中打开这个开关,长此以往,实在有些麻烦。

面对这种情况,Android 9.0 提供了一个更有「灵性」的解决方案:在屏幕旋转方向锁定的情况下,系统依然会检测你的设备方向;这时当你将手机横过来之后,屏幕内导航栏区域就会出现一个「自动旋转」开关,点击就能打开并旋转屏幕内容:


自动旋转按钮与其他常见按钮不太一样,它是AnimatedVectorDrawable,这是一个动态的矢量图,其xml资源文件需要使用animated-vector标签,并在里面定义一系列动画效果,就是上图gif里演示的小手机旋转的动画。关于AnimatedVectorDrawable,有兴趣的同学可以自行搜索了解一下。
    public void setRotateSuggestionButtonState(final boolean visible, final boolean force) {
        if (mNavigationBarView == null) return;

        // At any point the the button can become invisible because an a11y service became active.
        // Similarly, a call to make the button visible may be rejected because an a11y service is
        // active. Must account for this.

        ButtonDispatcher rotBtn = mNavigationBarView.getRotateSuggestionButton();
        final boolean currentlyVisible = mNavigationBarView.isRotateButtonVisible();

        // Rerun a show animation to indicate change but don't rerun a hide animation
        if (!visible && !currentlyVisible) return;

        View view = rotBtn.getCurrentView();
        if (view == null) return;

        KeyButtonDrawable kbd = rotBtn.getImageDrawable();
        if (kbd == null) return;

        // The KBD and AVD is recreated every new valid suggestion because of style changes.
        AnimatedVectorDrawable animIcon = null;
        if (kbd.getDrawable(0) instanceof AnimatedVectorDrawable) {
            animIcon = (AnimatedVectorDrawable) kbd.getDrawable(0);
        }

        // Handle the visibility change and animation
        if (visible) { // Appear and change (cannot force)
            // Stop and clear any currently running hide animations
            if (mRotateHideAnimator != null && mRotateHideAnimator.isRunning()) {
                mRotateHideAnimator.cancel();
            }
            mRotateHideAnimator = null;

            // Reset the alpha if any has changed due to hide animation
            view.setAlpha(1f);

            // Run the rotate icon's animation if it has one
            if (animIcon != null) {
                animIcon.reset();
                animIcon.start();
            }
            ...
        }

    }

布局变化

Android 9.0 导航栏上最Cool的变化,自然是新的导航手势及“药丸”按钮。

导航手势
由于新增了一种导航手势,自然NavigationBarInflaterView加载的布局也多了一种。
8.0的加载默认布局:
    protected String getDefaultLayout() {
        return mContext.getString(R.string.config_navBarLayout);
    }

9.0的加载默认布局:

    protected String getDefaultLayout() {
        final int defaultResource = mOverviewProxyService.shouldShowSwipeUpUI()
                ? R.string.config_navBarLayoutQuickstep
                : R.string.config_navBarLayout;
        return mContext.getString(defaultResource);
    }

当使用了Quickstep的布局时,导航栏就会变成这种效果:




关于9.0上的手势的使用方法,可移步至以下文章:
https://baijiahao.baidu.com/s?id=1600087701707774194&wfr=spider&for=pc

相关文章

网友评论

    本文标题:浅析Android 9.0导航栏的变化

    本文链接:https://www.haomeiwen.com/subject/vnbktqtx.html