模糊导航抽屉的背景

时间:2014-02-17 22:53:34

标签: android blur navigation-drawer

如何在导航抽屉上创建实时模糊,因此当您拉出抽屉时,列表的背景是显示在其后面的片段的模糊背景?

我看过,但主要发现BitMap模糊,没有任何现实。

1 个答案:

答案 0 :(得分:13)

该过程涉及以下阶段:

  1. 获取整个抽屉布局的快照。
  2. 将其裁剪为菜单的确切大小。
  3. 相当多缩小(8倍是非常好的)。
  4. 模糊那个图像。
  5. 拥有一个自定义视图,可以显示菜单显示位置后面的部分图像。
  6. 当您滑动时,抽屉会显示该图像的大部分内容。
  7. 这是一个代码示例(全部在BlurActionBarDrawerToggle和BlurAndDimView中完成):

    public class BlurActionBarDrawerToggle extends ActionBarDrawerToggle {
    
        private static final int DOWNSAMPLING = 8;
    
        private final DrawerLayout drawerLayout;
        private final BlurAndDimView blurrer;
        private Bitmap drawerSnapshot;
        private final ColorDrawable imageBackgroundDrawable;
    
        public BlurActionBarDrawerToggle(Activity activity, DrawerLayout drawerLayout, int drawerImageRes, int openDrawerContentDescRes, int closeDrawerContentDescRes, BlurAndDimView blurrer) {
            super(activity, drawerLayout, drawerImageRes, openDrawerContentDescRes, closeDrawerContentDescRes);
    
            //this should be roughly the same color as your window background
            imageBackgroundDrawable = new ColorDrawable(activity.getResources().getColor(R.color.dark_blue_2));
            this.drawerLayout = drawerLayout;
            this.blurrer = blurrer;
        }
    
        @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 (!blurrer.hasImage()) {
                setBlurImage();
            }
            blurrer.handleScroll(slideOffset);
        }
    
        public void setBlurImage() {
            blurrer.setVisibility(View.VISIBLE);
            drawerSnapshot = drawViewToBitmap(drawerSnapshot, drawerLayout, DOWNSAMPLING, imageBackgroundDrawable);
            blurrer.setImage(drawerSnapshot, DOWNSAMPLING);
        }
    
        public void clearBlurImage() {
            blurrer.clearImage();
            blurrer.setVisibility(View.INVISIBLE);
        }
    
        private Bitmap drawViewToBitmap(Bitmap dest, View view, int downSampling, Drawable background) {
            float scale = 1f / downSampling;
            int viewWidth = view.getWidth();
            int viewHeight = view.getHeight();
            int bmpWidth = (int) (viewWidth * scale);
            int bmpHeight = (int) (viewHeight * scale);
            if (dest == null || dest.getWidth() != bmpWidth || dest.getHeight() != bmpHeight) {
                dest = Bitmap.createBitmap(bmpWidth, bmpHeight, Bitmap.Config.ARGB_8888);
            }
            Canvas c = new Canvas(dest);
            background.setBounds(new Rect(0, 0, viewWidth, viewHeight));
            background.draw(c);
            if (downSampling > 1) {
                c.scale(scale, scale);
            }
    
            view.draw(c);
            view.layout(0, 0, viewWidth, viewHeight);
            return dest;
        }
    }
    

    BlurAndDim视图模糊菜单下方的部分,并使其余部分变暗(您可以调整数字以获得您想要的确切效果):

    public class BlurAndDimView extends View {
    
        private static final int BLUR_RADIUS = 4;
        private static final int BLUE_ALPHA = 178;
        private static final int MAX_DIM_ALPHA = 127;
        private Paint bitmapPaint;
        private Paint dimPaint;
        private Paint blueSemiTransparentPaint;
        private int menuWidth;
        private int titleHeight;
    
        private Bitmap image;
        private Rect rectDst;
        private Rect rectSrc;
        private int downSampling;
        private Rect rectRest;
    
        public BlurAndDimView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            postConstruct();
        }
    
        public BlurAndDimView(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
            postConstruct();
        }
    
        public BlurAndDimView(Context context) {
            this(context, null);
            postConstruct();
        }
    
        private void postConstruct() {
            bitmapPaint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
            dimPaint = new Paint();
            blueSemiTransparentPaint = new Paint();
            //You might want to also have a semitransparent overlay over your blurred image, since you can't control what's behind your menu.
            blueSemiTransparentPaint.setColor(getResources().getColor(R.color.dark_blue));
            blueSemiTransparentPaint.setAlpha(BLUE_ALPHA);
            menuWidth = getResources().getDimensionPixelSize(R.dimen.browse_menu_width);
        }
    }
    
        @Override
        protected void onDraw(Canvas canvas) {
            if (image != null) {
                canvas.drawBitmap(image, rectSrc, rectDst, bitmapPaint);
                canvas.drawRect(rectDst, blueSemiTransparentPaint);
                canvas.drawRect(rectRest, dimPaint);
            }
        }
    
        public void handleScroll(float xOffset) {
            if(image != null) {
                rectSrc.right = (int) (image.getWidth() * xOffset);
                rectDst.right = rectSrc.right * downSampling;
                rectRest.left = rectDst.right;
                dimPaint.setAlpha((int) (xOffset * MAX_DIM_ALPHA));
                invalidate();
            }
        }
    
        public void setImage(Bitmap bmp, int downSampling) {
            Bitmap cropped = Bitmap.createBitmap(bmp, 0, 0, menuWidth / downSampling, getHeight() / downSampling);
            this.image = Blur.blur(getContext(), cropped, BLUR_RADIUS);
            rectSrc = new Rect(0, 0, bmp.getWidth(), bmp.getHeight());
            rectDst = new Rect(0, 0, menuWidth, getHeight());
            rectRest = new Rect(menuWidth, 0, getWidth(), getHeight());
            this.downSampling = downSampling;
            invalidate();
        }
    
        public boolean hasImage() {
            return image != null;
        }
    
        public void clearImage() {
            image = null;
        }
    }
    

    对于良好的模糊算法(尽可能使用Renderscript),您可以使用this

    布局将是这样的:

    <android.support.v4.widget.DrawerLayout
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    
        <android.support.v4.widget.ViewPager
            android:id="@+id/pager"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    
        <com.bla.bla.BlurAndDimView
            android:id="@+id/blurrer"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginTop="?android:attr/actionBarSize"
            android:visibility="invisible" />
    
        <ListView
            android:id="@+id/menu_list"
            android:layout_width="@dimen/browse_menu_width"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:choiceMode="singleChoice" />
    </android.support.v4.widget.DrawerLayout>