在这周的 Android Design in Action 节目中,Adam Koch 谈到了一款名为Etsy的应用程序,该应用程序具有非常酷的模糊效果,当导航抽屉被拉出时,它会应用于主布局。
有谁知道 Etsy 背后的开发人员可能是如何实现这一点的?
在这里观看:http: //youtu.be/GjUxEddmjFw?t= 22m48s
在这周的 Android Design in Action 节目中,Adam Koch 谈到了一款名为Etsy的应用程序,该应用程序具有非常酷的模糊效果,当导航抽屉被拉出时,它会应用于主布局。
有谁知道 Etsy 背后的开发人员可能是如何实现这一点的?
在这里观看:http: //youtu.be/GjUxEddmjFw?t= 22m48s
这有几个部分:
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()。
看看这个博客http://nicolaspomepuy.fr/?p=18
基本上,您从原始图像生成模糊图像。我猜在这种情况下,原始的是使用getDrawingCache()
方法生成的,请务必先调用setDrawingCacheEnabled()
。