Размытие в стиле iOS для Android
Можно наткнуться на большое количество (одинаковых) рецептов размытия картинки в Android. Авторы предлагают размыть её заранее и смешивать в нужных пропорциях с оригиналом. Это классно, но меня интересовало размытие элементов интерфейса. Может, я хочу создать панельку с размытым фоном, под которой будет список, таблица или любой другой компонент.
Решено размывать в реальном времени с использованием RenderScript.
Компонент BlurredLayout, наследник FrameLayout
Много кода позаимствовано из ответов на StackOverflow: переопределение dispatchDraw, Android Blur Guide 2014
private void blurRect(Rect rect, float radius, Canvas canvas) {
Bitmap blurred = Bitmap.createBitmap(mBitmap, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top);
Allocation input = Allocation.createFromBitmap(mRenderScript, blurred);
Allocation output = Allocation.createTyped(mRenderScript, input.getType());
ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(mRenderScript, Element.U8_4(mRenderScript));
script.setRadius(radius);
script.setInput(input);
script.forEach(output); // FIXME: the most expensive command
output.copyTo(blurred);
canvas.drawBitmap(blurred, rect.left, rect.top, BITMAP_PAINT);
blurred.recycle();
}
Строка с комментарием — это такое чудесное место, где происходит отправка картинки на видеокарту и ожидание результата. Ускорять, увы, нечего :'(
Чтобы создать области размытия, нужно непосредственно внутри BlurredLayout разместить любые View, у которых tag="blur region".
<net.aquadc.widgets.BlurredLayout android:id="@+id/blurred"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<View
android:layout_width="match_parent"
android:layout_height="64dp"
android:background="#66000000"
android:tag="blur region" />
<View
android:layout_width="match_parent"
android:layout_height="64dp"
android:layout_gravity="bottom"
android:background="#22000000"
android:tag="blur region" />
</net.aquadc.widgets.BlurredLayout>
Аппаратное ускорение должно быть отключено, иначе происходит неведомая хрень. У меня на четырёхлетнем телефоне с Android 4.0.3 тормозит совсем чуть-чуть.