31

在这周的 Android Design in Action 节目中,Adam Koch 谈到了一款名为Etsy的应用程序,该应用程序具有非常酷的模糊效果,当导航抽屉被拉出时,它会应用于主布局。

有谁知道 Etsy 背后的开发人员可能是如何实现这一点的?

在这里观看:http: //youtu.be/GjUxEddmjFw?t= 22m48s

在此处输入图像描述 在此处输入图像描述

4

2 回答 2

67

这有几个部分:

1. 创建模糊位图:

当抽屉第一次打开时,我们从抽屉后面的内容视图创建一个缩小的位图(缩小使模糊速度更快)。然后,我们在可用的情况下(甚至更快)使用 RenderScript 将模糊应用于缩小的图像。为此,您应该阅读已经提到的博客http://nicolaspomepuy.fr/?p=18并查看 GlassActionBar 项目以获取参考代码https://github.com/ManuelPeinado/GlassActionBar

注意: RenderScript 现在可以在支持库中使用……但不能使用 Gradle 构建(目前)。ScriptIntrinsicBlur在某些设备上也存在问题,尤其是 Nexus 10 - 请参阅Roman Nurik 的解释

2. 显示和动画模糊:

我们的导航抽屉布局包含位于内容顶部的隐藏 ImageView。

<FrameLayout
    android:id="@+id/nav_content_frame"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

<!-- our blur image -->
<ImageView
    android:id="@+id/blur_image"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scaleType="centerCrop"
    android:visibility="gone" />

在活动 onCreate() 中,您需要获取对此 ImageView 的引用并设置自定义抽屉侦听器:

mBlurImage = (ImageView) findViewById(R.id.blur_image);
mDrawerLayout = (DrawerLayout) findViewById(R.id.nav_drawer_layout);

mDrawerToggle = new EtsyNavActionBarDrawerToggle(
            this, 
            mDrawerLayout,
            R.drawable.ic_drawer, 
            R.string.nav_drawer_open, 
            R.string.nav_drawer_closed);

mDrawerLayout.setDrawerListener(mDrawerToggle);

我们的抽屉有自定义的稀松布颜色(即覆盖颜色)而不是默认的透明黑色。这也隐藏了模糊图像位于缩小图像上的事实。

mDrawerLayout.setScrimColor(getResources().getColor(R.color.background_main_v2_glass));

设置、清除和动画模糊图像的抽屉侦听器:

private class EtsyNavActionBarDrawerToggle extends ActionBarDrawerToggle {

    public EtsyNavActionBarDrawerToggle(Activity activity, DrawerLayout drawerLayout, 
            int drawerImageRes, int openDrawerContentDescRes, int closeDrawerContentDescRes) {
        super(activity, drawerLayout, drawerImageRes, openDrawerContentDescRes, closeDrawerContentDescRes);
    }

    @Override
    public void onDrawerSlide(final View drawerView, final float slideOffset) {
        super.onDrawerSlide(drawerView, slideOffset);
        if (slideOffset > 0.0f) {
            setBlurAlpha(slideOffset);
        }
        else {
            clearBlurImage();
        }
    }

    @Override
    public void onDrawerClosed(View view) {
        clearBlurImage();
    }

}

private void setBlurAlpha(float slideOffset) {
    if (mBlurImage.getVisibility() != View.VISIBLE) {
        setBlurImage();
    }
    ViewHelper.setAlpha(mBlurImage, slideOffset);
}

public void setBlurImage() {
    mBlurImage.setImageBitmap(null);
    mBlurImage.setVisibility(View.VISIBLE);
    Bitmap downScaled = ... // do the downscaling
    Bitmap blurred = ... // apply the blur
    mBlurImage.setImageBitmap(blurred);
}

public void clearBlurImage() {
    mBlurImage.setVisibility(View.GONE);
    mBlurImage.setImageBitmap(null);
}

最后,ViewHelper 来自NineOldAndroids,因此我们可以在蜂窝之前设置Alpha()。

于 2013-12-03T22:28:56.317 回答
4

看看这个博客http://nicolaspomepuy.fr/?p=18

基本上,您从原始图像生成模糊图像。我猜在这种情况下,原始的是使用getDrawingCache()方法生成的,请务必先调用setDrawingCacheEnabled()

于 2013-11-28T19:03:44.547 回答