避免在Android上冷启动

原文链接 :Avoiding cold starts on Android
原文作者 : Saúl Molinero
译文出自 : http://blog.csdn.net/zhulove86
译者 : Tony Zhu

在过去几周,在android开发者社区中看一些关于冷启动(clod start)、闪屏(splash screen)、启动界面的动画。在本文中,我将阐明这些动画是否有必要,如何使用以及如何更好提供极致的用户体验。

本文中提到的代码和示例,可以在GitHub上获取。

Splash Screen,lunch screen和cold start

柯尔特(Colt McAnlis,在谷歌开发人员倡导者)通过在Cyril Morrier分享了主题文章,再次展开关于Splash/Lanuce screen在Android系统上使用的讨论。其中除其他事项外,讨论了为什么应该避免使用在Android上使用Splash Screen,声称这会伤害了用户体验,增加应用的大小等。

在我看来,用户应该尽快的看到应用的内容。但不可避免的,当用户启动一个应用程序时,Android会创建一个新的进程。在应用加载中,显示一个由应用theme构建的黑/白屏,或是第一个Activity的theme。

当我们应用非常复杂,并且我们重写了很多被用于初始化分析,报错等功能的对象,应用启动的负载就会变的很大。

这里写图片描述
Airbnb在应用初始化中显示白屏。

对于用户黑屏并不是最好的选择。如果我们的应用加载的时间很慢,我们应该使用一个占位,用实际内容简单的填充;或另一方面,如果我们的开发工作是复杂的,我们可以显示应用的logo,以增强品牌效应。

这里写图片描述
AliExpress 在初始化中显示其logo

你的新伙伴, windowBackground

如之前讨论,在进程加载状态时由WindowManager显示的窗口被设置为application主题。具体在android:windowBackground中值。参考lan Lake的文章,如果我们通过使用设定 <layer-list>这个属性,main activity的背景色之上在最中心显示一个bitmap,我们可以获得如下的效果:

这里写图片描述

<?xml version="1.0" encoding="utf-8"?>
<layer-list 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:opacity="opaque">

    <item android:drawable="@color/grey"/>
    <item>
        <bitmap
            android:gravity="center"
            android:src="@drawable/img_pizza"/>
    </item>
</layer-list>

我们必须牢记以避免出现问题,<layer-list>应该是不透明的,android:opacity=”opaque”。并且在layout中该activity的父activity背景色也应该被一种颜色填充,如果没有的话,<layer-list> 在启动时所展示的将被保留在你的activity中。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@color/grey"
    >

    <android.support.v7.widget.Toolbar
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?colorPrimary"
        android:elevation="4dp"
        />
</LinearLayout>

改变应用引导(onboarding)样式

利用窗口背景色,我们可以丰富用户体验的效果。如果我们的应用复杂,并且要展示一个类似登录或者选择的不透明界面,我们采用位图相同的定位点(anchor point)和动画实现,可以达到非常好的效果。

这里写图片描述
这个动画,转变一个ImageView,其中包含了相同的<layer-list>的资源 。

ViewCompat.animate(logoImageView)
    .translationY(-250)
    .setStartDelay(STARTUP_DELAY)
    .setDuration(ANIM_ITEM_DURATION).setInterpolator(
         new DecelerateInterpolator(1.2f)).start();

这个ImageView略高于屏幕的中心,这可以通过状态栏的影响,离 top 边缘12dp,正好是状态栏一半的高度。

<ImageView
    android:id="@+id/img_logo"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:layout_marginTop="12dp"
    android:src="@drawable/img_face"
    tools:visibility="gone"
    />

改变占位的样式

通过<layer-list> 我们可以创建一个占位的UI,在该UI中显示main activity的内容。举例,我们可以利用<layer-list> 模拟一个工具栏。

这里写图片描述

<?xml version="1.0" encoding="utf-8"?>
<layer-list
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:opacity="opaque"
    >
    <item>
        <shape>
            <solid android:color="@color/grey"/>
        </shape>
    </item>

    <item
        android:height="180dp"
        android:gravity="top">
        <shape android:shape="rectangle">
            <solid android:color="?colorPrimary"/>
        </shape>
    </item>
</layer-list>

在这种情况下,第二个<item> 模拟工具栏来显示实际的内容,甚至我们可以设置相同的高度(略小于状态栏的宽度),并且在工具栏上使用一些好的动画,可以给用户提供较好的用户体验。

这里写图片描述

private void collapseToolbar() {
    int toolBarHeight;
    TypedValue tv = new TypedValue();
    getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true);
    toolBarHeight = TypedValue.complexToDimensionPixelSize(
        tv.data, getResources().getDisplayMetrics());

    ValueAnimator valueHeightAnimator = ValueAnimator
        .ofInt(mContentViewHeight, toolBarHeight);

    valueHeightAnimator.addUpdateListener(
        new ValueAnimator.AnimatorUpdateListener() {

        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            ViewGroup.LayoutParams lp = mToolbar.getLayoutParams();
            lp.height = (Integer) animation.getAnimatedValue();
            mToolbar.setLayoutParams(lp);
        }
    });

    valueHeightAnimator.start();
    valueHeightAnimator.addListener(
        new AnimatorListenerAdapter() {

        @Override
        public void onAnimationEnd(Animator animation) {
            super.onAnimationEnd(animation);

            // Fire recycler animator
            mAdapter.addAll(ModelItem.getFakeItems());

            // Animate fab
            ViewCompat.animate(mFab).setStartDelay(600)
                .setDuration(400).scaleY(1).scaleX(1).start();

        }
    });
}

相关资料:
onboarding-examples - Github
Uber onboarding
Use cold start time effectively with a branded launch theme - Ian Lake
Splash Screens Are Evil, Don’t Use Them! - Cyril Mottier
Launch screens - Material Design Spec
Launch screens - MaterialDoc, Gonzalo Toledano


由于时间仓促、翻译水平有限,其中有许多不足之处在所难免,敬请批评指正。

猜你喜欢

转载自blog.csdn.net/zhulove86/article/details/52573417