2014-02-17 2 views
5

Как я могу создать живое размытие в навигационном ящике, поэтому, когда вы вытаскиваете ящик, фон списка размывается фон фрагмента, отображаемого за ним?Размытие фона навигационного ящика

Я посмотрел, но в основном нашел размытие BitMap, и ничего, что является живым.

+0

Вы действительно хотите, чтобы размыть фон, а не просто сделать его полупрозрачным? Blur - это дорогостоящая операция, и сделать это на лету без трюков, возможно, слишком дорого! – LukaCiko

+1

Не могли бы вы просто создать прозрачное изображение .png с некоторым пятном на нем? А затем установите фон ящика равным этому? – Phoenix

+0

Вы не можете использовать размытие .png, потому что для создания размытия ему нужно изображение для образца, а затем размытие – SquiresSquire

ответ

11

Процесс включает в себя следующие этапы:

  1. Получить снимок всего макета ящика.
  2. Обрезать его до нужного размера вашего меню.
  3. Вниз это совсем немного (коэффициент 8 довольно хорош).
  4. Размытие этого изображения.
  5. У вас есть пользовательский вид, который отображает часть изображения прямо за местом вашего меню.
  6. Когда вы выдвигаете ящик, вы видите большую часть этого изображения.

Вот пример кода (все это делается в 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> 
+0

Помните, что в зависимости от того, насколько вы уменьшаете или уменьшаете изображение, это может занять дольше 40-50 мс на некоторых устройствах , Но, если вы придерживаетесь числа, которое я дал, вы можете использовать это в большинстве случаев без каких-либо проблем. –

+0

Я попробовал этот. но не смог показать ящик. как я могу использовать его (открыть ящик) из MainActivity? – Ajay

+0

Где вы получили «Blur.blur», можете ли вы указать библиотеку, которую используете или класс? спасибо – Cjames

Смежные вопросы