在项目中要点击一个按钮弹出一个对话框但背景得是当前界面的模糊图像,和对话框。其间遇到了一些困难,获取的背景图片不能和原来的窗口重合,看起来窗口下移了一段距离等,为了方便以后回顾 ,特意记下来:
1、获取当前窗口的截图:
public static Bitmap getScreenBitmap(Activity activity) { // View view2 = activity.getWindow().getDecorView().findViewById(android.R.id.content);//这是获得内容的view View view2 = activity.getWindow().getDecorView();//这是获取整个窗口的view,包括状态栏,标题栏。但是状态栏上是空的。这里获得图像的高宽就是手机屏幕的高宽 Bitmap bitmap = Bitmap.createBitmap(view2.getWidth(), view2.getHeight(), Bitmap.Config.ARGB_8888); //利用bitmap生成画布 Canvas canvas = new Canvas(bitmap); //把view中的内容绘制在画布上 view2.draw(canvas); return bitmap; }
获取手机屏幕的时候,有2个方式,第一个view2是获取的content的view的截图,因此不含状态栏和标题栏;第二个view是包含整个屏幕的,包含状态栏但没有图标。
2、获取状态栏的高度。
方法1:
int statusBarHeight1 = -1; //获取status_bar_height资源的ID int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); if (resourceId > 0) { //根据资源ID获取响应的尺寸值 statusBarHeight1 = getResources().getDimensionPixelSize(resourceId); }
方法2:
Rect rectangle= new Rect(); getWindow().getDecorView().getWindowVisibleDisplayFrame(rectangle); statusBarHeight1 = rectangle.top;
3、获取标题栏的高度
标题栏的高度可以通过1中讲到的获取content view的方式,利用view.getTop()获得标题栏高度。
4、当acitivity有标题栏时候添加popupWindow时候需要注意的2点(当activity没有标题栏的时候我们可以直接获取content的截图,直接模糊不需要设置偏移量):
(1)、当我们利用PopupWindow的构造函数来添加view的时候,当view偏移到屏幕边缘时就不会再偏移了,因此很多时候偏移量设定移除屏幕外了是无法做到的,因此需要在view的内部就将偏移量定义好。
PopupWindow popupWindow = new PopupWindow(relativeLayout,bitmap.getWidth(),bitmap.getHeight());
popupWindow.showAtLocation(button, Gravity.LEFT|Gravity.TOP , 0 , 0 );
(2)、为了让模糊后的图像与原窗口图像重合,要设定好图片的偏移量。
通过上面讲到的方式获取状态栏的高度,然后可以定义一个view放在relativeLayout中,让其背景为模糊后的图片,然后添加我们的点击选项。
下面是有状态栏时候添加背景图片的代码:(blurmap是图片模糊方法,返回模糊图像。)
Rect rectangle= new Rect(); getWindow().getDecorView().getWindowVisibleDisplayFrame(rectangle); int statusBarHeight1 = rectangle.top; Bitmap bitmap = GSBitmap.getScreenBitmap(this); bitmap = blurBitmap(this,bitmap,25); View view1 = new View(this); view1.setBackground(new BitmapDrawable(getResources() , bitmap)); RelativeLayout relativeLayout = new RelativeLayout(this); RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(bitmap.getWidth(),bitmap.getHeight()); layoutParams.topMargin = -statusBarHeight1; view1.setLayoutParams(layoutParams); relativeLayout.addView(view1); PopupWindow popupWindow = new PopupWindow(relativeLayout,bitmap.getWidth(),bitmap.getHeight()); popupWindow.showAtLocation(button, Gravity.LEFT|Gravity.TOP , 0 , 0 );
5、当没有状态栏的时候,j获取bitmap的时候直接获取content 的view图像,然后直接将rootview的背景设置为模糊图像即可:
Bitmap bitmap = GSBitmap.getScreenBitmap(this); bitmap = blurBitmap(this,bitmap,25); View rootView = new RelativeLayout(this); rootView.setBackground(new BitmapDrawable(getResources() ,bitmap)); PopupWindow popupWindow = new PopupWindow(rootView,bitmap.getWidth(),bitmap.getHeight()); popupWindow.showAtLocation(button, Gravity.LEFT|Gravity.TOP , 0 , 0 );
模糊图像大多都是采用的高斯模糊算法,有些博客中提到为了加快速度我们在获取截图后,先进性缩小处理:(因为图像缩小也费时间和资源,本人觉得没有必要)
Bitmap bitmap = GSBitmap.getScreenBitmap(this); Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap,bitmap.getWidth()/3,bitmap.getHeight()/3,false); scaledBitmap = blurBitmap(this,scaledBitmap,5); View rootView = new RelativeLayout(this); rootView.setBackground(new BitmapDrawable(getResources() ,scaledBitmap)); PopupWindow popupWindow = new PopupWindow(rootView,bitmap.getWidth(),bitmap.getHeight()); popupWindow.showAtLocation(button, Gravity.LEFT|Gravity.TOP , 0 , 0 );
6、模糊算法,这是系统里的算法,效率比我自己写的高斯算法效率高一点,这里直接贴出:
/** * android系统的模糊方法 * @param bitmap 要模糊的图片 * @param radius 模糊等级 >=0 && <=25 */ public static Bitmap blurBitmap(Context context, Bitmap bitmap, int radius) { if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1){ //Let's create an empty bitmap with the same size of the bitmap we want to blur Bitmap outBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); //Instantiate a new Renderscript RenderScript rs = RenderScript.create(context); //Create an Intrinsic Blur Script using the Renderscript ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); //Create the Allocations (in/out) with the Renderscript and the in/out bitmaps Allocation allIn = Allocation.createFromBitmap(rs, bitmap); Allocation allOut = Allocation.createFromBitmap(rs, outBitmap); //Set the radius of the blur blurScript.setRadius(radius); //Perform the Renderscript blurScript.setInput(allIn); blurScript.forEach(allOut); //Copy the final bitmap created by the out Allocation to the outBitmap allOut.copyTo(outBitmap); //recycle the original bitmap bitmap.recycle(); //After finishing everything, we destroy the Renderscript. rs.destroy(); return outBitmap; }else{ return bitmap; } }