android 背景透明模糊效果怎么做的,將展開Android狀態欄的背景設置為透明模糊效果…

  • Post author:
  • Post category:其他


在android 4.4 版本中狀態欄是在一個apk中(SystemUI.apk),查看layout/gemini_status_bar_expanded.xml源文件

xmlns:android=”http://schemas.android.com/apk/res/android”

xmlns:systemui=”http://schemas.android.com/apk/res/com.android.systemui”

android:id=”@+id/notification_panel”

android:layout_width=”0dp”

android:layout_height=”wrap_content”

android:background=”@drawable/notification_panel_bg”

android:paddingTop=”@dimen/notification_panel_padding_top”

android:layout_marginStart=”@dimen/notification_panel_margin_left”

>

android:id=”@+id/handle”

android:layout_width=”match_parent”

android:layout_height=”@dimen/close_handle_height”

android:background=”@drawable/status_bar_close”

android:visibility=”invisible”

/>

layout=”@layout/gemini_carrier_label”

android:layout_height=”@dimen/carrier_label_height”

android:layout_width=”match_parent”

android:layout_marginBottom=”@dimen/close_handle_height”

android:layout_gravity=”bottom”

/>

android:layout_width=”match_parent”

android:layout_height=”wrap_content”

android:layout_marginBottom=”@dimen/close_handle_underlap”

android:orientation=”vertical”

android:animateLayoutChanges=”false”

>

android:layout_width=”match_parent”

android:layout_height=”@dimen/notification_panel_header_height”

/>

android:id=”@+id/toolBarSwitchPanel”

android:layout_width=”match_parent”

android:layout_height=”103dip”

android:background=”@drawable/notification_header_bg”>

android:layout_width=”match_parent”

android:layout_height=”wrap_content”

>

android:layout=”@layout/flip_settings”

android:layout_width=”match_parent”

android:layout_height=”wrap_content”

/>

android:id=”@+id/scroll”

android:layout_width=”match_parent”

android:layout_height=”wrap_content”

android:fadingEdge=”none”

android:overScrollMode=”ifContentScrolls”

>

android:id=”@+id/latestItems”

android:layout_width=”match_parent”

android:layout_height=”wrap_content”

systemui:rowHeight=”@dimen/notification_row_min_height”

/>

可知我們只要設置NotificationPanelView的背景即可,而這個NotificationPanelView在PhoneStatusBar.java文件中的makeStatusBarView方法中初始化。現在采用的方法是將屏幕截屏后將獲取到的Bitmap模糊化作為NotificationPanelView背景。當用戶點擊最上面的狀態欄時就會觸發事件,而我們獲取到這個事件,並在這時截取屏幕。仔細看代碼可以得到用戶在點擊上方狀態欄時就會觸發在PhoneStatusBarView.java中的onTouchEvent方法添加如下代碼,其中考慮到橫豎屏轉化的問題得調用getResources().getConfiguration().orientation 判斷是橫屏還是豎屏。

if (event.getAction() == MotionEvent.ACTION_DOWN) {

BitmapDrawable mBitmapDrawable;

if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){

mBitmapDrawable = new BitmapDrawable(getResources(), darkBitmap(fastBlur(shot())));

}else{

mBitmapDrawable = new BitmapDrawable(getResources(), darkBitmap(fastBlur(rotateBitmap(shot()))));

}

mBitmapDrawable.setTileModeXY(TileMode.REPEAT , TileMode.REPEAT);

mBar.mNotificationPanel.setBackground(mBitmapDrawable);

}

需要的截屏類,和截屏后處理的代碼如下:

public static boolean leftOrRightLandscape = true;

private Bitmap shot() {

DisplayMetrics dm = getResources().getDisplayMetrics();

int width , height;

if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){

width = dm.widthPixels;

height = dm.heightPixels;

}else{

width = dm.heightPixels;

height = dm.widthPixels;

}

Bitmap mBitmap = SurfaceControl.screenshot(width, height);

return mBitmap;

}

private Bitmap fastBlur(Bitmap bkg) {

float scaleFactor = 8;

float radius = 2;

Bitmap overlay = Bitmap.createBitmap(

(int) (bkg.getWidth() / scaleFactor),

(int) (bkg.getHeight() / scaleFactor),

Bitmap.Config.ARGB_8888);

Canvas canvas = new Canvas(overlay);

canvas.translate(0, 0);

canvas.scale(1 / scaleFactor, 1 / scaleFactor);

Paint paint = new Paint();

paint.setFlags(Paint.FILTER_BITMAP_FLAG);

canvas.drawBitmap(bkg, 0, 0, paint);

overlay = FastBlur.doBlur(overlay, (int) radius, true);

DisplayMetrics dm = getResources().getDisplayMetrics();

int width = bkg.getWidth();

int height = bkg.getHeight();

Bitmap mBitmap = overlay.createScaledBitmap(overlay, width, height, true);

return mBitmap;

}

private Bitmap darkBitmap(Bitmap srcBitmap){

int imgHeight, imgWidth;

imgHeight = srcBitmap.getHeight();

imgWidth = srcBitmap.getWidth();

Bitmap dstBitmap = Bitmap.createBitmap(imgWidth, imgHeight, Config.ARGB_8888);

Bitmap bmp = Bitmap.createBitmap(imgWidth, imgHeight,

Config.ARGB_8888);

float contrast = (float) (30 / 100.0);

ColorMatrix cMatrix = new ColorMatrix();

cMatrix.set(new float[] { contrast, 0, 0, 0, 0, 0,

contrast, 0, 0, 0,

0, 0, contrast, 0, 0, 0, 0, 0, 1, 0 });

Paint paint = new Paint();

paint.setColorFilter(new ColorMatrixColorFilter(cMatrix));

Canvas canvas = new Canvas(bmp);

canvas.drawBitmap(srcBitmap, 0, 0, paint);

return bmp;

}

private  Bitmap rotateBitmap(Bitmap bmp){

Bitmap mbmp = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(),

Config.ARGB_8888);

Canvas canvas = new Canvas(mbmp);

canvas.drawBitmap(bmp, 0, 0, null);

Matrix matrix = new Matrix();

matrix.postScale(1f, 1f);

if(leftOrRightLandscape == true){

matrix.postRotate(90);

}else{

matrix.postRotate(-90);

}

Bitmap dstbmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(),matrix, true);

canvas.drawBitmap(dstbmp, 0, 0, null);

return dstbmp;

}

因為橫屏截取屏幕時,截取到的Bitmap會被旋轉,這里需要考慮到將獲取到的Bitmap轉換方向,此處還必須的考慮是左旋還是右旋到的橫屏,轉屏的方向不一樣的話,那么得到的Bitmap也不一樣。在SystemUIService.java中添加如下代碼:

private OrientationEventListener mOrientationListener;

private boolean mScreenProtrait = true;

private boolean mCurrentOrient = false;

private final void startOrientationChangeListener() {

mOrientationListener = new OrientationEventListener(this) {

@Override

public void onOrientationChanged(int rotation) {

if ((rotation >= 0) && (rotation <= 180)) {// portrait

mCurrentOrient = true;

if (mCurrentOrient != mScreenProtrait) {

mScreenProtrait = mCurrentOrient;

PhoneStatusBarView.leftOrRightLandscape = true;

}

} else if ((rotation > 180) && (rotation < 360)) {// landscape

mCurrentOrient = false;

if (mCurrentOrient != mScreenProtrait) {

mScreenProtrait = mCurrentOrient;

PhoneStatusBarView.leftOrRightLandscape = false;

}

}

}

};

mOrientationListener.enable();

}

並在onCreate方法中添加startOrientationChangeListener();

這里是調用的android.view.OrientationEventListener這個監聽屏幕轉換方向的類,獲取到屏幕的轉換的度數之后就可以判斷是否左旋還是右旋,並將布爾數值賦給PhoneStatusBarView類中的屬性,用戶在點擊狀態欄就會將Bitmap旋轉為合適的度數,具體代碼看上面。

此處還得注意的一個地方是,當用戶將狀態欄展開后再轉化屏幕方向就會出現一個問題,因為背景圖還是以前的圖,而如果又重新截屏的話那截取到的是含有展開狀態欄的。所以必須的在這種情況下屏幕方向轉換時,將展開的狀態欄退回。可以將PhoneStatusBar的onConfigurationChanged方法中添加animateCollapsePanels();

附:效果圖如下:

d2920dde4c50a6c4dea14b1efba661c0.jpe