
status_bar_expanded.xml布局中
NotificationPanelViewController.java类
private static final int BLUR_START = 200;
private static final int BLUR_END = 700;
/**
* 高斯模糊背景
*/
private ImageView mBlurView;
createTouchHandler()方法中
public boolean onTouch(View v, MotionEvent event) {
if (mBlockTouches || (mQsFullyExpanded && mQs != null
&& mQs.disallowPanelTouches())) {
return false;
}
// Do not allow panel expansion if bouncer is scrimmed, otherwise user would be able
// to pull down QS or expand the shade.
if (mStatusBar.isBouncerShowingScrimmed()) {
return false;
}
// Make sure the next touch won't the blocked after the current ends.
if (event.getAction() == MotionEvent.ACTION_UP
|| event.getAction() == MotionEvent.ACTION_CANCEL) {
mBlockingExpansionForCurrentTouch = false;
}
// When touch focus transfer happens, ACTION_DOWN->ACTION_UP may happen immediately
// without any ACTION_MOVE event.
// In such case, simply expand the panel instead of being stuck at the bottom bar.
if (mLastEventSynthesizedDown && event.getAction() == MotionEvent.ACTION_UP) {
expand(true /* animate */);
}
initDownStates(event);
if (!mIsExpanding && !shouldQuickSettingsIntercept(mDownX, mDownY, 0)
&& mPulseExpansionHandler.onTouchEvent(event)) {
// We're expanding all the other ones shouldn't get this anymore
return true;
}
if (mListenForHeadsUp && !mHeadsUpTouchHelper.isTrackingHeadsUp()
&& mHeadsUpTouchHelper.onInterceptTouchEvent(event)) {
mMetricsLogger.count(COUNTER_PANEL_OPEN_PEEK, 1);
}
boolean handled = false;
if ((!mIsExpanding || mHintAnimationRunning) && !mQsExpanded
&& mBarState != StatusBarState.SHADE && !mDozing) {
handled |= mAffordanceHelper.onTouchEvent(event);
}
if (mOnlyAffordanceInThisMotion) {
return true;
}
handled |= mHeadsUpTouchHelper.onTouchEvent(event);
if (!mHeadsUpTouchHelper.isTrackingHeadsUp() && handleQsTouch(event)) {
return true;
}
if (event.getActionMasked() == MotionEvent.ACTION_DOWN && isFullyCollapsed()) {
mMetricsLogger.count(COUNTER_PANEL_OPEN, 1);
updateVerticalPanelPosition(event.getX());
handled = true;
}
//添加背景高斯模糊 begin
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (!mPanelExpanded) {
setBlurBackground();
}
break;
case MotionEvent.ACTION_MOVE:
if (y <= BLUR_END) {
float alpha = (y - BLUR_START) / (BLUR_END - BLUR_START);
if (alpha < 0) {
alpha = 0;
}
mBlurView.setAlpha(alpha);
}
break;
case MotionEvent.ACTION_UP:
float a = mBlurView.getAlpha();
startAlphaAnimation(a, 1.0f);
break;
}
// 添加背景高斯模糊 end
handled |= super.onTouch(v, event);
return !mDozing || mPulsing || handled;
}
private void startAlphaAnimation(float start, float end) {
ValueAnimator va = ValueAnimator.ofFloat(start, end);
va.setDuration((long) (Math.abs(end - start) * 500));
va.start();
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float alpha = (float) animation.getAnimatedValue();
mBlurView.setAlpha(alpha);
}
});
}
private void setBlurBackground() {
Bitmap bitmap = ScreenShotUtil.takeScreenShot(mView.getContext());
if (bitmap == null) {
Log.d(TAG, "setBlurBackground bitmap == null");
return;
}
Bitmap cutBitmap = ScreenShotUtil.convertHardWareBitmap(bitmap);
Bitmap blurBitmap = BlurUtil.blur(mView.getContext(), cutBitmap, BlurUtil.BLUR_RADIUS_MAX);
BitmapUtils.recycleImageView(mBlurView);
mBlurView.setImageBitmap(blurBitmap);
}
private class StatusBarStateListener implements StateListener {
@Override
public void onStateChanged(int statusBarState) {
boolean goingToFullShade = mStatusBarStateController.goingToFullShade();
boolean keyguardFadingAway = mKeyguardStateController.isKeyguardFadingAway();
int oldState = mBarState;
boolean keyguardShowing = statusBarState == StatusBarState.KEYGUARD;
setKeyguardStatusViewVisibility(statusBarState, keyguardFadingAway, goingToFullShade);
setKeyguardBottomAreaVisibility(statusBarState, goingToFullShade);
mBarState = statusBarState;
mKeyguardShowing = keyguardShowing;
if (oldState == StatusBarState.KEYGUARD && (goingToFullShade
|| statusBarState == StatusBarState.SHADE_LOCKED)) {
animateKeyguardStatusBarOut();
long
delay =
mBarState == StatusBarState.SHADE_LOCKED ? 0
: mKeyguardStateController.calculateGoingToFullShadeDelay();
mQs.animateHeaderSlidingIn(delay);
} else if (oldState == StatusBarState.SHADE_LOCKED
&& statusBarState == StatusBarState.KEYGUARD) {
animateKeyguardStatusBarIn(StackStateAnimator.ANIMATION_DURATION_STANDARD);
mNotificationStackScroller.resetScrollPosition();
// Only animate header if the header is visible. If not, it will partially
// animate out
// the top of QS
if (!mQsExpanded) {
mQs.animateHeaderSlidingOut();
}
} else {
mKeyguardStatusBar.setAlpha(1f);
mKeyguardStatusBar.setVisibility(keyguardShowing ? View.VISIBLE : View.INVISIBLE);
if (keyguardShowing && oldState != mBarState) {
if (mQs != null) {
mQs.hideImmediately();
}
}
}
updateKeyguardStatusBarForHeadsUp();
if (keyguardShowing) {
updateDozingVisibilities(false /* animate */);
}
// THe update needs to happen after the headerSlide in above, otherwise the translation
// would reset
updateQSPulseExpansion();
maybeAnimateBottomAreaAlpha();
resetHorizontalPanelPosition();
updateQsState();
// 根据是否锁屏展示高斯模糊背景
updateBlurVisibility(keyguardShowing);
}
/**
* 根据是否锁屏展示高斯模糊背景
* @param keyguardShowing
*/
private void updateBlurVisibility(boolean keyguardShowing){
if (keyguardShowing) {
mBlurView.setVisibility(View.GONE);
BitmapUtils.recycleImageView(mBlurView);
}else {
mBlurView.setVisibility(View.VISIBLE);
}
}
工具类:
public class BitmapUtils {
/**
* 回收ImageView
* @param view
*/
public static void recycleImageView(View view) {
if (view == null) return;
if (view instanceof ImageView) {
Drawable drawable = ((ImageView) view).getDrawable();
if (drawable instanceof BitmapDrawable) {
Bitmap bmp = ((BitmapDrawable) drawable).getBitmap();
if (bmp != null && !bmp.isRecycled()) {
((ImageView) view).setImageBitmap(null);
bmp.recycle();
bmp = null;
}
}
}
}
}
public class BlurUtil {
private static final float BITMAP_SCALE = 0.4f;
private static final int BLUR_RADIUS = 7;
/**
* 高斯模糊半径,0-25区间,越大越模糊
*/
public static final int BLUR_RADIUS_MAX = 25;
public static Bitmap blur(Context context, Bitmap bitmap) {
return blur(context, bitmap, BITMAP_SCALE, BLUR_RADIUS);
}
public static Bitmap blur(Context context, Bitmap bitmap, float bitmap_scale) {
return blur(context, bitmap, bitmap_scale, BLUR_RADIUS);
}
public static Bitmap blur(Context context, Bitmap bitmap, int blur_radius) {
return blur(context, bitmap, BITMAP_SCALE, blur_radius);
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public static Bitmap blur(Context context, Bitmap bitmap, float bitmap_scale, int blur_radius) {
Bitmap inputBitmap = Bitmap.createScaledBitmap(bitmap, Math.round(bitmap.getWidth() * bitmap_scale),
Math.round(bitmap.getHeight() * bitmap_scale), false);
Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap);
RenderScript rs = RenderScript.create(context);
ScriptIntrinsicBlur theIntrinsic = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap);
Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap);
theIntrinsic.setRadius(blur_radius);
theIntrinsic.setInput(tmpIn);
theIntrinsic.forEach(tmpOut);
tmpOut.copyTo(outputBitmap);
rs.destroy();
bitmap.recycle();
return outputBitmap;
}
}
public class ScreenShotUtil {
/**
* 获取截屏图片
* @param context
* @return
*/
public static Bitmap takeScreenShot(Context context) {
Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
DisplayMetrics displayMetrics = new DisplayMetrics();
display.getRealMetrics(displayMetrics);
final float[] dims = {displayMetrics.widthPixels, displayMetrics.heightPixels};
Rect crop = new Rect(0, 0, displayMetrics.widthPixels, displayMetrics.heightPixels);
int rot = display.getRotation();
int width = crop.width();
int height = crop.height();
Bitmap bitmap = SurfaceControl.screenshot(crop, width, height, rot);
if (bitmap != null) {
return bitmap;
}
bitmap = SurfaceControl.screenshot(crop, height, width, rot);
Matrix matrix = new Matrix();
matrix.setRotate(-90);
if (bitmap == null) {
return null;
}
Bitmap newBM = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
bitmap.recycle();
return newBM;
}
public static Bitmap convertHardWareBitmap(Bitmap src) {
if (src.getConfig() != Bitmap.Config.HARDWARE) {
//return Bitmap.createBitmap(src, 0, 0, src.getWidth(), src.getHeight());
return src;
}
final int w = src.getWidth();
final int h = src.getHeight();
// For hardware bitmaps, use the Picture API to directly create a software bitmap
Picture picture = new Picture();
Canvas canvas = picture.beginRecording(w, h);
canvas.drawBitmap(src, 0, 0, null);
picture.endRecording();
return Bitmap.createBitmap(picture, w, h, Bitmap.Config.ARGB_8888);
}
}欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)