/*
* Copyright (C) 2014 Charalampakis Basilis - Blur ActionBarDrawerToggle
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.marshalchen.common.uimodule.BlurNavigationDrawer;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.widget.DrawerLayout;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.widget.ImageView;
import android.widget.RelativeLayout;
public class BlurActionBarDrawerToggle extends ActionBarDrawerToggle {
private Context context;
/**
* the layout that we take snapshot
*/
private DrawerLayout mDrawerLayout;
/**
* an imageview to display the blurred snapshot/bitmap
*/
private ImageView mBlurredImageView;
/**
* Blur radius used for the background.
*/
private int mBlurRadius = DEFAULT_BLUR_RADIUS;
/**
* Default Blur Radius
*/
public static int DEFAULT_BLUR_RADIUS = 5;
/**
* Down scale factor to reduce blurring time and memory allocation.
*/
private float mDownScaleFactor = DEFAULT_DOWNSCALEFACTOR;
/**
* Default Down Scale Factor
*/
public static float DEFAULT_DOWNSCALEFACTOR = 5.0f;
/**
* Render flag
* <p/>
* If true we must render
* if false, we have already blurred the background
*/
private boolean prepareToRender = true;
/**
* flag for "fake" sliding detection
*/
private boolean isOpening = false;
public BlurActionBarDrawerToggle(Activity activity, DrawerLayout drawerLayout,
int drawerImageRes, int openDrawerContentDescRes,
int closeDrawerContentDescRes) {
super(activity, drawerLayout, drawerImageRes, openDrawerContentDescRes, closeDrawerContentDescRes);
this.context = activity.getBaseContext();
this.mDrawerLayout = drawerLayout;
init();
}
/**
* We make a fake ImageView with width and height MATCH_PARENT.
* This ImageView will host the blurred snapshot/bitmap.
*/
private void init() {
mBlurredImageView = new ImageView(context);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
mBlurredImageView.setLayoutParams(params);
mBlurredImageView.setClickable(false);
mBlurredImageView.setVisibility(View.GONE);
mBlurredImageView.setScaleType(ImageView.ScaleType.FIT_XY);
mDrawerLayout.post(new Runnable() {
@Override
public void run() {
// Add the ImageViewiew not in the last position.
// Otherwise, it will be shown in NavigationDrawer
mDrawerLayout.addView(mBlurredImageView, 1);
}
});
}
@Override
public void onDrawerSlide(final View drawerView, final float slideOffset) {
super.onDrawerSlide(drawerView, slideOffset);
//must check this for "fake" sliding..
if (slideOffset == 0.f)
isOpening = false;
else
isOpening = true;
render();
setAlpha(mBlurredImageView, slideOffset, 100);
}
@Override
public void onDrawerClosed(View view) {
prepareToRender = true;
mBlurredImageView.setVisibility(View.GONE);
}
@Override
public void onDrawerStateChanged(int newState) {
super.onDrawerStateChanged(newState);
// "fake" sliding detection
if (newState == DrawerLayout.STATE_IDLE
&& !isOpening) {
handleRecycle();
}
}
/**
* Snapshots the specified layout and scale it using scaleBitmap() function
* then we blur the scaled bitmap with the preferred blur radius.
* Finally, we post it to our fake {@link android.widget.ImageView}.
*/
private void render() {
if (prepareToRender) {
prepareToRender = false;
Bitmap bitmap = loadBitmapFromView(mDrawerLayout);
bitmap = scaleBitmap(bitmap);
bitmap = Blur.fastblur(context, bitmap, mBlurRadius, false);
mBlurredImageView.setVisibility(View.VISIBLE);
mBlurredImageView.setImageBitmap(bitmap);
}
}
public void setRadius(int radius) {
mBlurRadius = radius < 1 ? 1 : radius;
}
public void setDownScaleFactor(float downScaleFactor) {
mDownScaleFactor = downScaleFactor < 1 ? 1 : downScaleFactor;
}
private void setAlpha(View view, float alpha, long durationMillis) {
if (Build.VERSION.SDK_INT < 11) {
final AlphaAnimation animation = new AlphaAnimation(alpha, alpha);
animation.setDuration(durationMillis);
animation.setFillAfter(true);
view.startAnimation(animation);
} else {
view.setAlpha(alpha);
}
}
private Bitmap loadBitmapFromView(View mView) {
Bitmap b = Bitmap.createBitmap(
mView.getWidth(),
mView.getHeight(),
Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
// With the following, screen blinks
//v.layout(0, 0, v.getLayoutParams().width, v.getLayoutParams().height);
mView.draw(c);
return b;
}
private Bitmap scaleBitmap(Bitmap myBitmap) {
int width = (int) (myBitmap.getWidth() / mDownScaleFactor);
int height = (int) (myBitmap.getHeight() / mDownScaleFactor);
return Bitmap.createScaledBitmap(myBitmap, width, height, false);
}
private void handleRecycle() {
Drawable drawable = mBlurredImageView.getDrawable();
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bitmapDrawable = ((BitmapDrawable) drawable);
Bitmap bitmap = bitmapDrawable.getBitmap();
if (bitmap != null)
bitmap.recycle();
mBlurredImageView.setImageBitmap(null);
}
prepareToRender = true;
}
}