Loading packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml +8 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,14 @@ android:focusable="true" android:clickable="true" > <com.android.systemui.statusbar.NotificationBackgroundView android:id="@+id/backgroundNormal" android:layout_width="match_parent" android:layout_height="match_parent" /> <com.android.systemui.statusbar.NotificationBackgroundView android:id="@+id/backgroundDimmed" android:layout_width="match_parent" android:layout_height="match_parent" /> <TextView android:id="@+id/more_text" android:layout_width="match_parent" Loading packages/SystemUI/res/layout/status_bar_notification_row.xml +10 −0 Original line number Diff line number Diff line Loading @@ -6,6 +6,16 @@ android:clickable="true" > <com.android.systemui.statusbar.NotificationBackgroundView android:id="@+id/backgroundNormal" android:layout_width="match_parent" android:layout_height="match_parent" /> <com.android.systemui.statusbar.NotificationBackgroundView android:id="@+id/backgroundDimmed" android:layout_width="match_parent" android:layout_height="match_parent" /> <com.android.systemui.statusbar.NotificationContentView android:id="@+id/expanded" android:layout_width="match_parent" android:layout_height="wrap_content" /> Loading packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java +90 −117 Original line number Diff line number Diff line Loading @@ -19,18 +19,17 @@ package com.android.systemui.statusbar; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; import android.view.animation.PathInterpolator; import com.android.internal.R; import com.android.systemui.R; /** * Base class for both {@link ExpandableNotificationRow} and {@link NotificationOverflowContainer} Loading @@ -38,13 +37,19 @@ import com.android.internal.R; */ public abstract class ActivatableNotificationView extends ExpandableOutlineView { private static final long DOUBLETAP_TIMEOUT_MS = 1000; private static final long DOUBLETAP_TIMEOUT_MS = 1200; private static final int BACKGROUND_ANIMATION_LENGTH_MS = 220; private static final int ACTIVATE_ANIMATION_LENGTH = 220; private static final Interpolator ACTIVATE_INVERSE_INTERPOLATOR = new PathInterpolator(0.6f, 0, 0.5f, 1); private static final Interpolator ACTIVATE_INVERSE_ALPHA_INTERPOLATOR = new PathInterpolator(0, 0, 0.5f, 1); private boolean mDimmed; private int mBgResId = R.drawable.notification_quantum_bg; private int mDimmedBgResId = R.drawable.notification_quantum_bg_dim; private int mBgResId = com.android.internal.R.drawable.notification_quantum_bg; private int mDimmedBgResId = com.android.internal.R.drawable.notification_quantum_bg_dim; private int mBgTint = 0; private int mDimmedBgTint = 0; Loading @@ -61,18 +66,30 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView private OnActivatedListener mOnActivatedListener; protected Drawable mBackgroundNormal; protected Drawable mBackgroundDimmed; private ObjectAnimator mBackgroundAnimator; private Interpolator mLinearOutSlowInInterpolator; private Interpolator mFastOutSlowInInterpolator; private NotificationBackgroundView mBackgroundNormal; private NotificationBackgroundView mBackgroundDimmed; private ObjectAnimator mBackgroundAnimator; public ActivatableNotificationView(Context context, AttributeSet attrs) { super(context, attrs); mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); updateBackgroundResource(); setWillNotDraw(false); mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context, android.R.interpolator.fast_out_slow_in); mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context, android.R.interpolator.linear_out_slow_in); setClipChildren(false); setClipToPadding(false); } @Override protected void onFinishInflate() { super.onFinishInflate(); mBackgroundNormal = (NotificationBackgroundView) findViewById(R.id.backgroundNormal); mBackgroundDimmed = (NotificationBackgroundView) findViewById(R.id.backgroundDimmed); updateBackgroundResource(); } private final Runnable mTapTimeoutRunnable = new Runnable() { Loading @@ -82,42 +99,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView } }; @Override protected void onDraw(Canvas canvas) { draw(canvas, mBackgroundNormal); draw(canvas, mBackgroundDimmed); } private void draw(Canvas canvas, Drawable drawable) { if (drawable != null) { drawable.setBounds(0, mClipTopAmount, getWidth(), mActualHeight); drawable.draw(canvas); } } @Override protected boolean verifyDrawable(Drawable who) { return super.verifyDrawable(who) || who == mBackgroundNormal || who == mBackgroundDimmed; } @Override protected void drawableStateChanged() { drawableStateChanged(mBackgroundNormal); drawableStateChanged(mBackgroundDimmed); } private void drawableStateChanged(Drawable d) { if (d != null && d.isStateful()) { d.setState(getDrawableState()); } } @Override public void setOnClickListener(OnClickListener l) { super.setOnClickListener(l); } @Override public boolean onTouchEvent(MotionEvent event) { if (mDimmed) { Loading Loading @@ -146,10 +127,9 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView case MotionEvent.ACTION_UP: if (isWithinTouchSlop(event)) { if (!mActivated) { makeActive(event.getX(), event.getY()); makeActive(); postDelayed(mTapTimeoutRunnable, DOUBLETAP_TIMEOUT_MS); } else { makeInactive(); performClick(); } } else { Loading @@ -165,23 +145,58 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView return true; } private void makeActive(float x, float y) { mBackgroundDimmed.setHotspot(0, x, y); private void makeActive() { startActivateAnimation(false /* reverse */); mActivated = true; if (mOnActivatedListener != null) { mOnActivatedListener.onActivated(this); } } private void startActivateAnimation(boolean reverse) { int widthHalf = mBackgroundNormal.getWidth()/2; int heightHalf = mBackgroundNormal.getActualHeight()/2; float radius = (float) Math.sqrt(widthHalf*widthHalf + heightHalf*heightHalf); ValueAnimator animator = mBackgroundNormal.createRevealAnimator(widthHalf, heightHalf, 0, radius); mBackgroundNormal.setVisibility(View.VISIBLE); Interpolator interpolator; Interpolator alphaInterpolator; if (!reverse) { interpolator = mLinearOutSlowInInterpolator; alphaInterpolator = mLinearOutSlowInInterpolator; } else { interpolator = ACTIVATE_INVERSE_INTERPOLATOR; alphaInterpolator = ACTIVATE_INVERSE_ALPHA_INTERPOLATOR; } animator.setInterpolator(interpolator); animator.setDuration(ACTIVATE_ANIMATION_LENGTH); if (reverse) { mBackgroundNormal.setAlpha(1f); animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mBackgroundNormal.setVisibility(View.INVISIBLE); } }); animator.reverse(); } else { mBackgroundNormal.setAlpha(0.4f); animator.start(); } mBackgroundNormal.animate() .alpha(reverse ? 0f : 1f) .setInterpolator(alphaInterpolator) .setDuration(ACTIVATE_ANIMATION_LENGTH); } /** * Cancels the hotspot and makes the notification inactive. */ private void makeInactive() { if (mActivated) { // Make sure that we clear the hotspot from the center. if (mBackgroundDimmed != null) { mBackgroundDimmed.setHotspot(0, getWidth() / 2, getActualHeight() / 2); mBackgroundDimmed.removeHotspot(0); if (mDimmed) { startActivateAnimation(true /* reverse */); } mActivated = false; } Loading Loading @@ -227,16 +242,16 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView private void fadeBackgroundResource() { if (mDimmed) { setBackgroundDimmed(mDimmedBgResId, mDimmedBgTint); mBackgroundDimmed.setVisibility(View.VISIBLE); } else { setBackgroundNormal(mBgResId, mBgTint); mBackgroundNormal.setVisibility(View.VISIBLE); } int startAlpha = mDimmed ? 255 : 0; int endAlpha = mDimmed ? 0 : 255; float startAlpha = mDimmed ? 1f : 0; float endAlpha = mDimmed ? 0 : 1f; int duration = BACKGROUND_ANIMATION_LENGTH_MS; // Check whether there is already a background animation running. if (mBackgroundAnimator != null) { startAlpha = (Integer) mBackgroundAnimator.getAnimatedValue(); startAlpha = (Float) mBackgroundAnimator.getAnimatedValue(); duration = (int) mBackgroundAnimator.getCurrentPlayTime(); mBackgroundAnimator.removeAllListeners(); mBackgroundAnimator.cancel(); Loading @@ -247,16 +262,16 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView } mBackgroundNormal.setAlpha(startAlpha); mBackgroundAnimator = ObjectAnimator.ofInt(mBackgroundNormal, "alpha", startAlpha, endAlpha); ObjectAnimator.ofFloat(mBackgroundNormal, View.ALPHA, startAlpha, endAlpha); mBackgroundAnimator.setInterpolator(mFastOutSlowInInterpolator); mBackgroundAnimator.setDuration(duration); mBackgroundAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (mDimmed) { setBackgroundNormal(null); mBackgroundNormal.setVisibility(View.INVISIBLE); } else { setBackgroundDimmed(null); mBackgroundDimmed.setVisibility(View.INVISIBLE); } mBackgroundAnimator = null; } Loading @@ -266,59 +281,15 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView private void updateBackgroundResource() { if (mDimmed) { setBackgroundDimmed(mDimmedBgResId, mDimmedBgTint); mBackgroundDimmed.setAlpha(255); setBackgroundNormal(null); mBackgroundDimmed.setVisibility(View.VISIBLE); mBackgroundDimmed.setCustomBackground(mDimmedBgResId, mDimmedBgTint); mBackgroundNormal.setVisibility(View.INVISIBLE); } else { setBackgroundDimmed(null); setBackgroundNormal(mBgResId, mBgTint); mBackgroundNormal.setAlpha(255); } } /** * Sets a background drawable for the normal state. As we need to change our bounds * independently of layout, we need the notion of a background independently of the regular View * background.. */ private void setBackgroundNormal(Drawable backgroundNormal) { if (mBackgroundNormal != null) { mBackgroundNormal.setCallback(null); unscheduleDrawable(mBackgroundNormal); } mBackgroundNormal = backgroundNormal; if (mBackgroundNormal != null) { mBackgroundNormal.setCallback(this); } invalidate(); } private void setBackgroundDimmed(Drawable overlay) { if (mBackgroundDimmed != null) { mBackgroundDimmed.setCallback(null); unscheduleDrawable(mBackgroundDimmed); } mBackgroundDimmed = overlay; if (mBackgroundDimmed != null) { mBackgroundDimmed.setCallback(this); } invalidate(); } private void setBackgroundNormal(int drawableResId, int tintColor) { final Drawable d = getResources().getDrawable(drawableResId); if (tintColor != 0) { d.setColorFilter(tintColor, PorterDuff.Mode.SRC_ATOP); } setBackgroundNormal(d); } private void setBackgroundDimmed(int drawableResId, int tintColor) { final Drawable d = getResources().getDrawable(drawableResId); if (tintColor != 0) { d.setColorFilter(tintColor, PorterDuff.Mode.SRC_ATOP); mBackgroundDimmed.setVisibility(View.INVISIBLE); mBackgroundNormal.setVisibility(View.VISIBLE); mBackgroundNormal.setCustomBackground(mBgResId, mBgTint); mBackgroundNormal.setAlpha(1f); } setBackgroundDimmed(d); } @Override Loading @@ -330,14 +301,16 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView @Override public void setActualHeight(int actualHeight, boolean notifyListeners) { super.setActualHeight(actualHeight, notifyListeners); invalidate(); setPivotY(actualHeight / 2); mBackgroundNormal.setActualHeight(actualHeight); mBackgroundDimmed.setActualHeight(actualHeight); } @Override public void setClipTopAmount(int clipTopAmount) { super.setClipTopAmount(clipTopAmount); invalidate(); mBackgroundNormal.setClipTopAmount(clipTopAmount); mBackgroundDimmed.setClipTopAmount(clipTopAmount); } public void setOnActivatedListener(OnActivatedListener onActivatedListener) { Loading packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java 0 → 100644 +122 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.systemui.statusbar; import android.content.Context; import android.graphics.Canvas; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.View; /** * A view that can be used for both the dimmed and normal background of an notification. */ public class NotificationBackgroundView extends View { private Drawable mBackground; private int mClipTopAmount; private int mActualHeight; private boolean mActualHeightInitialized; public NotificationBackgroundView(Context context, AttributeSet attrs) { super(context, attrs); setWillNotDraw(false); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); if (!mActualHeightInitialized && mActualHeight == 0) { mActualHeight = getHeight(); } mActualHeightInitialized = true; } @Override protected void onDraw(Canvas canvas) { draw(canvas, mBackground); } private void draw(Canvas canvas, Drawable drawable) { if (drawable != null) { drawable.setBounds(0, mClipTopAmount, getWidth(), mActualHeight); drawable.draw(canvas); } } @Override protected boolean verifyDrawable(Drawable who) { return super.verifyDrawable(who) || who == mBackground; } @Override protected void drawableStateChanged() { drawableStateChanged(mBackground); } private void drawableStateChanged(Drawable d) { if (d != null && d.isStateful()) { d.setState(getDrawableState()); } } /** * Sets a background drawable. As we need to change our bounds independently of layout, we need * the notion of a background independently of the regular View background.. */ public void setCustomBackground(Drawable background) { if (mBackground != null) { mBackground.setCallback(null); unscheduleDrawable(mBackground); } mBackground = background; if (mBackground != null) { mBackground.setCallback(this); } invalidate(); } public void setCustomBackground(int drawableResId, int tintColor) { final Drawable d = getResources().getDrawable(drawableResId); if (tintColor != 0) { d.setColorFilter(tintColor, PorterDuff.Mode.SRC_ATOP); } setCustomBackground(d); } public void setActualHeight(int actualHeight) { mActualHeight = actualHeight; invalidate(); } public int getActualHeight() { return mActualHeight; } public void setClipTopAmount(int clipTopAmount) { mClipTopAmount = clipTopAmount; invalidate(); } @Override public boolean hasOverlappingRendering() { // Prevents this view from creating a layer when alpha is animating. return false; } } Loading
packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml +8 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,14 @@ android:focusable="true" android:clickable="true" > <com.android.systemui.statusbar.NotificationBackgroundView android:id="@+id/backgroundNormal" android:layout_width="match_parent" android:layout_height="match_parent" /> <com.android.systemui.statusbar.NotificationBackgroundView android:id="@+id/backgroundDimmed" android:layout_width="match_parent" android:layout_height="match_parent" /> <TextView android:id="@+id/more_text" android:layout_width="match_parent" Loading
packages/SystemUI/res/layout/status_bar_notification_row.xml +10 −0 Original line number Diff line number Diff line Loading @@ -6,6 +6,16 @@ android:clickable="true" > <com.android.systemui.statusbar.NotificationBackgroundView android:id="@+id/backgroundNormal" android:layout_width="match_parent" android:layout_height="match_parent" /> <com.android.systemui.statusbar.NotificationBackgroundView android:id="@+id/backgroundDimmed" android:layout_width="match_parent" android:layout_height="match_parent" /> <com.android.systemui.statusbar.NotificationContentView android:id="@+id/expanded" android:layout_width="match_parent" android:layout_height="wrap_content" /> Loading
packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java +90 −117 Original line number Diff line number Diff line Loading @@ -19,18 +19,17 @@ package com.android.systemui.statusbar; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; import android.view.animation.PathInterpolator; import com.android.internal.R; import com.android.systemui.R; /** * Base class for both {@link ExpandableNotificationRow} and {@link NotificationOverflowContainer} Loading @@ -38,13 +37,19 @@ import com.android.internal.R; */ public abstract class ActivatableNotificationView extends ExpandableOutlineView { private static final long DOUBLETAP_TIMEOUT_MS = 1000; private static final long DOUBLETAP_TIMEOUT_MS = 1200; private static final int BACKGROUND_ANIMATION_LENGTH_MS = 220; private static final int ACTIVATE_ANIMATION_LENGTH = 220; private static final Interpolator ACTIVATE_INVERSE_INTERPOLATOR = new PathInterpolator(0.6f, 0, 0.5f, 1); private static final Interpolator ACTIVATE_INVERSE_ALPHA_INTERPOLATOR = new PathInterpolator(0, 0, 0.5f, 1); private boolean mDimmed; private int mBgResId = R.drawable.notification_quantum_bg; private int mDimmedBgResId = R.drawable.notification_quantum_bg_dim; private int mBgResId = com.android.internal.R.drawable.notification_quantum_bg; private int mDimmedBgResId = com.android.internal.R.drawable.notification_quantum_bg_dim; private int mBgTint = 0; private int mDimmedBgTint = 0; Loading @@ -61,18 +66,30 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView private OnActivatedListener mOnActivatedListener; protected Drawable mBackgroundNormal; protected Drawable mBackgroundDimmed; private ObjectAnimator mBackgroundAnimator; private Interpolator mLinearOutSlowInInterpolator; private Interpolator mFastOutSlowInInterpolator; private NotificationBackgroundView mBackgroundNormal; private NotificationBackgroundView mBackgroundDimmed; private ObjectAnimator mBackgroundAnimator; public ActivatableNotificationView(Context context, AttributeSet attrs) { super(context, attrs); mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); updateBackgroundResource(); setWillNotDraw(false); mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context, android.R.interpolator.fast_out_slow_in); mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context, android.R.interpolator.linear_out_slow_in); setClipChildren(false); setClipToPadding(false); } @Override protected void onFinishInflate() { super.onFinishInflate(); mBackgroundNormal = (NotificationBackgroundView) findViewById(R.id.backgroundNormal); mBackgroundDimmed = (NotificationBackgroundView) findViewById(R.id.backgroundDimmed); updateBackgroundResource(); } private final Runnable mTapTimeoutRunnable = new Runnable() { Loading @@ -82,42 +99,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView } }; @Override protected void onDraw(Canvas canvas) { draw(canvas, mBackgroundNormal); draw(canvas, mBackgroundDimmed); } private void draw(Canvas canvas, Drawable drawable) { if (drawable != null) { drawable.setBounds(0, mClipTopAmount, getWidth(), mActualHeight); drawable.draw(canvas); } } @Override protected boolean verifyDrawable(Drawable who) { return super.verifyDrawable(who) || who == mBackgroundNormal || who == mBackgroundDimmed; } @Override protected void drawableStateChanged() { drawableStateChanged(mBackgroundNormal); drawableStateChanged(mBackgroundDimmed); } private void drawableStateChanged(Drawable d) { if (d != null && d.isStateful()) { d.setState(getDrawableState()); } } @Override public void setOnClickListener(OnClickListener l) { super.setOnClickListener(l); } @Override public boolean onTouchEvent(MotionEvent event) { if (mDimmed) { Loading Loading @@ -146,10 +127,9 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView case MotionEvent.ACTION_UP: if (isWithinTouchSlop(event)) { if (!mActivated) { makeActive(event.getX(), event.getY()); makeActive(); postDelayed(mTapTimeoutRunnable, DOUBLETAP_TIMEOUT_MS); } else { makeInactive(); performClick(); } } else { Loading @@ -165,23 +145,58 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView return true; } private void makeActive(float x, float y) { mBackgroundDimmed.setHotspot(0, x, y); private void makeActive() { startActivateAnimation(false /* reverse */); mActivated = true; if (mOnActivatedListener != null) { mOnActivatedListener.onActivated(this); } } private void startActivateAnimation(boolean reverse) { int widthHalf = mBackgroundNormal.getWidth()/2; int heightHalf = mBackgroundNormal.getActualHeight()/2; float radius = (float) Math.sqrt(widthHalf*widthHalf + heightHalf*heightHalf); ValueAnimator animator = mBackgroundNormal.createRevealAnimator(widthHalf, heightHalf, 0, radius); mBackgroundNormal.setVisibility(View.VISIBLE); Interpolator interpolator; Interpolator alphaInterpolator; if (!reverse) { interpolator = mLinearOutSlowInInterpolator; alphaInterpolator = mLinearOutSlowInInterpolator; } else { interpolator = ACTIVATE_INVERSE_INTERPOLATOR; alphaInterpolator = ACTIVATE_INVERSE_ALPHA_INTERPOLATOR; } animator.setInterpolator(interpolator); animator.setDuration(ACTIVATE_ANIMATION_LENGTH); if (reverse) { mBackgroundNormal.setAlpha(1f); animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mBackgroundNormal.setVisibility(View.INVISIBLE); } }); animator.reverse(); } else { mBackgroundNormal.setAlpha(0.4f); animator.start(); } mBackgroundNormal.animate() .alpha(reverse ? 0f : 1f) .setInterpolator(alphaInterpolator) .setDuration(ACTIVATE_ANIMATION_LENGTH); } /** * Cancels the hotspot and makes the notification inactive. */ private void makeInactive() { if (mActivated) { // Make sure that we clear the hotspot from the center. if (mBackgroundDimmed != null) { mBackgroundDimmed.setHotspot(0, getWidth() / 2, getActualHeight() / 2); mBackgroundDimmed.removeHotspot(0); if (mDimmed) { startActivateAnimation(true /* reverse */); } mActivated = false; } Loading Loading @@ -227,16 +242,16 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView private void fadeBackgroundResource() { if (mDimmed) { setBackgroundDimmed(mDimmedBgResId, mDimmedBgTint); mBackgroundDimmed.setVisibility(View.VISIBLE); } else { setBackgroundNormal(mBgResId, mBgTint); mBackgroundNormal.setVisibility(View.VISIBLE); } int startAlpha = mDimmed ? 255 : 0; int endAlpha = mDimmed ? 0 : 255; float startAlpha = mDimmed ? 1f : 0; float endAlpha = mDimmed ? 0 : 1f; int duration = BACKGROUND_ANIMATION_LENGTH_MS; // Check whether there is already a background animation running. if (mBackgroundAnimator != null) { startAlpha = (Integer) mBackgroundAnimator.getAnimatedValue(); startAlpha = (Float) mBackgroundAnimator.getAnimatedValue(); duration = (int) mBackgroundAnimator.getCurrentPlayTime(); mBackgroundAnimator.removeAllListeners(); mBackgroundAnimator.cancel(); Loading @@ -247,16 +262,16 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView } mBackgroundNormal.setAlpha(startAlpha); mBackgroundAnimator = ObjectAnimator.ofInt(mBackgroundNormal, "alpha", startAlpha, endAlpha); ObjectAnimator.ofFloat(mBackgroundNormal, View.ALPHA, startAlpha, endAlpha); mBackgroundAnimator.setInterpolator(mFastOutSlowInInterpolator); mBackgroundAnimator.setDuration(duration); mBackgroundAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (mDimmed) { setBackgroundNormal(null); mBackgroundNormal.setVisibility(View.INVISIBLE); } else { setBackgroundDimmed(null); mBackgroundDimmed.setVisibility(View.INVISIBLE); } mBackgroundAnimator = null; } Loading @@ -266,59 +281,15 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView private void updateBackgroundResource() { if (mDimmed) { setBackgroundDimmed(mDimmedBgResId, mDimmedBgTint); mBackgroundDimmed.setAlpha(255); setBackgroundNormal(null); mBackgroundDimmed.setVisibility(View.VISIBLE); mBackgroundDimmed.setCustomBackground(mDimmedBgResId, mDimmedBgTint); mBackgroundNormal.setVisibility(View.INVISIBLE); } else { setBackgroundDimmed(null); setBackgroundNormal(mBgResId, mBgTint); mBackgroundNormal.setAlpha(255); } } /** * Sets a background drawable for the normal state. As we need to change our bounds * independently of layout, we need the notion of a background independently of the regular View * background.. */ private void setBackgroundNormal(Drawable backgroundNormal) { if (mBackgroundNormal != null) { mBackgroundNormal.setCallback(null); unscheduleDrawable(mBackgroundNormal); } mBackgroundNormal = backgroundNormal; if (mBackgroundNormal != null) { mBackgroundNormal.setCallback(this); } invalidate(); } private void setBackgroundDimmed(Drawable overlay) { if (mBackgroundDimmed != null) { mBackgroundDimmed.setCallback(null); unscheduleDrawable(mBackgroundDimmed); } mBackgroundDimmed = overlay; if (mBackgroundDimmed != null) { mBackgroundDimmed.setCallback(this); } invalidate(); } private void setBackgroundNormal(int drawableResId, int tintColor) { final Drawable d = getResources().getDrawable(drawableResId); if (tintColor != 0) { d.setColorFilter(tintColor, PorterDuff.Mode.SRC_ATOP); } setBackgroundNormal(d); } private void setBackgroundDimmed(int drawableResId, int tintColor) { final Drawable d = getResources().getDrawable(drawableResId); if (tintColor != 0) { d.setColorFilter(tintColor, PorterDuff.Mode.SRC_ATOP); mBackgroundDimmed.setVisibility(View.INVISIBLE); mBackgroundNormal.setVisibility(View.VISIBLE); mBackgroundNormal.setCustomBackground(mBgResId, mBgTint); mBackgroundNormal.setAlpha(1f); } setBackgroundDimmed(d); } @Override Loading @@ -330,14 +301,16 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView @Override public void setActualHeight(int actualHeight, boolean notifyListeners) { super.setActualHeight(actualHeight, notifyListeners); invalidate(); setPivotY(actualHeight / 2); mBackgroundNormal.setActualHeight(actualHeight); mBackgroundDimmed.setActualHeight(actualHeight); } @Override public void setClipTopAmount(int clipTopAmount) { super.setClipTopAmount(clipTopAmount); invalidate(); mBackgroundNormal.setClipTopAmount(clipTopAmount); mBackgroundDimmed.setClipTopAmount(clipTopAmount); } public void setOnActivatedListener(OnActivatedListener onActivatedListener) { Loading
packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java 0 → 100644 +122 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.systemui.statusbar; import android.content.Context; import android.graphics.Canvas; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.View; /** * A view that can be used for both the dimmed and normal background of an notification. */ public class NotificationBackgroundView extends View { private Drawable mBackground; private int mClipTopAmount; private int mActualHeight; private boolean mActualHeightInitialized; public NotificationBackgroundView(Context context, AttributeSet attrs) { super(context, attrs); setWillNotDraw(false); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); if (!mActualHeightInitialized && mActualHeight == 0) { mActualHeight = getHeight(); } mActualHeightInitialized = true; } @Override protected void onDraw(Canvas canvas) { draw(canvas, mBackground); } private void draw(Canvas canvas, Drawable drawable) { if (drawable != null) { drawable.setBounds(0, mClipTopAmount, getWidth(), mActualHeight); drawable.draw(canvas); } } @Override protected boolean verifyDrawable(Drawable who) { return super.verifyDrawable(who) || who == mBackground; } @Override protected void drawableStateChanged() { drawableStateChanged(mBackground); } private void drawableStateChanged(Drawable d) { if (d != null && d.isStateful()) { d.setState(getDrawableState()); } } /** * Sets a background drawable. As we need to change our bounds independently of layout, we need * the notion of a background independently of the regular View background.. */ public void setCustomBackground(Drawable background) { if (mBackground != null) { mBackground.setCallback(null); unscheduleDrawable(mBackground); } mBackground = background; if (mBackground != null) { mBackground.setCallback(this); } invalidate(); } public void setCustomBackground(int drawableResId, int tintColor) { final Drawable d = getResources().getDrawable(drawableResId); if (tintColor != 0) { d.setColorFilter(tintColor, PorterDuff.Mode.SRC_ATOP); } setCustomBackground(d); } public void setActualHeight(int actualHeight) { mActualHeight = actualHeight; invalidate(); } public int getActualHeight() { return mActualHeight; } public void setClipTopAmount(int clipTopAmount) { mClipTopAmount = clipTopAmount; invalidate(); } @Override public boolean hasOverlappingRendering() { // Prevents this view from creating a layer when alpha is animating. return false; } }