summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml6
-rw-r--r--packages/SystemUI/res/layout/status_bar_notification_row.xml5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/FakeShadowView.java84
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java85
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java31
8 files changed, 238 insertions, 6 deletions
diff --git a/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
index f699fce27043..7df6bc695555 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
@@ -22,6 +22,7 @@
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"
@@ -65,4 +66,9 @@
/>
</com.android.keyguard.AlphaOptimizedLinearLayout>
+ <com.android.systemui.statusbar.notification.FakeShadowView
+ android:id="@+id/fake_shadow"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
</com.android.systemui.statusbar.NotificationOverflowContainer>
diff --git a/packages/SystemUI/res/layout/status_bar_notification_row.xml b/packages/SystemUI/res/layout/status_bar_notification_row.xml
index c4c45bb0be22..e456984c5f36 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_row.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_row.xml
@@ -76,4 +76,9 @@
android:layout_height="wrap_content"
/>
+ <com.android.systemui.statusbar.notification.FakeShadowView
+ android:id="@+id/fake_shadow"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
</com.android.systemui.statusbar.ExpandableNotificationRow>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index 315c5092922c..effe581ac9ca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -35,6 +35,7 @@ import android.view.animation.PathInterpolator;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.statusbar.notification.FakeShadowView;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
/**
@@ -155,6 +156,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
}
};
private float mShadowAlpha = 1.0f;
+ private FakeShadowView mFakeShadow;
public ActivatableNotificationView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -180,6 +182,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
protected void onFinishInflate() {
super.onFinishInflate();
mBackgroundNormal = (NotificationBackgroundView) findViewById(R.id.backgroundNormal);
+ mFakeShadow = (FakeShadowView) findViewById(R.id.fake_shadow);
mBackgroundDimmed = (NotificationBackgroundView) findViewById(R.id.backgroundDimmed);
mBackgroundNormal.setCustomBackground(R.drawable.notification_material_bg);
mBackgroundDimmed.setCustomBackground(R.drawable.notification_material_bg_dim);
@@ -852,6 +855,14 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
}
}
+ @Override
+ public void setFakeShadowIntensity(float shadowIntensity, float outlineAlpha, int shadowYEnd,
+ int outlineTranslation) {
+ mFakeShadow.setFakeShadowTranslationZ(shadowIntensity * (getTranslationZ()
+ + FakeShadowView.SHADOW_SIBLING_TRESHOLD), outlineAlpha, shadowYEnd,
+ outlineTranslation);
+ }
+
public interface OnActivatedListener {
void onActivated(ActivatableNotificationView view);
void onActivationReset(ActivatableNotificationView view);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
index 782a38cc4023..f98e87d4848c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
@@ -70,6 +70,11 @@ public abstract class ExpandableOutlineView extends ExpandableView {
}
}
+ @Override
+ public float getOutlineAlpha() {
+ return mOutlineAlpha;
+ }
+
protected void setOutlineRect(RectF rect) {
if (rect != null) {
setOutlineRect(rect.left, rect.top, rect.right, rect.bottom);
@@ -80,6 +85,11 @@ public abstract class ExpandableOutlineView extends ExpandableView {
}
}
+ @Override
+ public int getOutlineTranslation() {
+ return mCustomOutline ? mOutlineRect.left : 0;
+ }
+
protected void setOutlineRect(float left, float top, float right, float bottom) {
setOutlineRect(true, left, top, right, bottom);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 3176e2e1851a..c9e1cff9c865 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -399,6 +399,18 @@ public abstract class ExpandableView extends FrameLayout {
return false;
}
+ public void setFakeShadowIntensity(float shadowIntensity, float outlineAlpha, int shadowYEnd,
+ int outlineTranslation) {
+ }
+
+ public float getOutlineAlpha() {
+ return 0.0f;
+ }
+
+ public int getOutlineTranslation() {
+ return 0;
+ }
+
/**
* A listener notifying when {@link #getActualHeight} changes.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/FakeShadowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/FakeShadowView.java
new file mode 100644
index 000000000000..32c26ba8ba13
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/FakeShadowView.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 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.notification;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.Outline;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewOutlineProvider;
+import android.widget.LinearLayout;
+
+import com.android.systemui.statusbar.AlphaOptimizedFrameLayout;
+
+/**
+ * A view used to cast a shadow of a certain size on another view
+ */
+public class FakeShadowView extends AlphaOptimizedFrameLayout {
+ public static final float SHADOW_SIBLING_TRESHOLD = 0.1f;
+
+ private View mFakeShadow;
+ private float mOutlineAlpha;
+
+ public FakeShadowView(Context context) {
+ this(context, null);
+ }
+
+ public FakeShadowView(Context context, @Nullable AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public FakeShadowView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public FakeShadowView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ mFakeShadow = new View(context);
+ mFakeShadow.setVisibility(INVISIBLE);
+ mFakeShadow.setLayoutParams(new LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ (int) (48 * getResources().getDisplayMetrics().density)));
+ mFakeShadow.setOutlineProvider(new ViewOutlineProvider() {
+ @Override
+ public void getOutline(View view, Outline outline) {
+ outline.setRect(0, 0, getWidth(), mFakeShadow.getHeight());
+ outline.setAlpha(mOutlineAlpha);
+ }
+ });
+ addView(mFakeShadow);
+ }
+
+ public void setFakeShadowTranslationZ(float fakeShadowTranslationZ, float outlineAlpha,
+ int shadowYEnd, int outlineTranslation) {
+ if (fakeShadowTranslationZ == 0.0f) {
+ mFakeShadow.setVisibility(INVISIBLE);
+ } else {
+ mFakeShadow.setVisibility(VISIBLE);
+ mFakeShadow.setTranslationZ(fakeShadowTranslationZ);
+ mFakeShadow.setTranslationX(outlineTranslation);
+ mFakeShadow.setTranslationY(shadowYEnd - mFakeShadow.getHeight());
+ if (outlineAlpha != mOutlineAlpha) {
+ mOutlineAlpha = outlineAlpha;
+ mFakeShadow.invalidateOutline();
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 8f9a2243bad3..fe06c3affa12 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -63,6 +63,7 @@ import com.android.systemui.statusbar.NotificationSettingsIconRow;
import com.android.systemui.statusbar.NotificationSettingsIconRow.SettingsIconRowListener;
import com.android.systemui.statusbar.StackScrollerDecorView;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.FakeShadowView;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
import com.android.systemui.statusbar.phone.ScrimController;
@@ -70,6 +71,8 @@ import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.ScrollAdapter;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.HashSet;
/**
@@ -93,7 +96,7 @@ public class NotificationStackScrollLayout extends ViewGroup
private static final int INVALID_POINTER = -1;
private ExpandHelper mExpandHelper;
- private SwipeHelper mSwipeHelper;
+ private NotificationSwipeHelper mSwipeHelper;
private boolean mSwipingInProgress;
private int mCurrentStackHeight = Integer.MAX_VALUE;
private final Paint mBackgroundPaint = new Paint();
@@ -277,6 +280,7 @@ public class NotificationStackScrollLayout extends ViewGroup
private int mBgColor;
private float mDimAmount;
private ValueAnimator mDimAnimator;
+ private ArrayList<ExpandableView> mTmpSortedChildren = new ArrayList<>();
private Animator.AnimatorListener mDimEndListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@@ -292,6 +296,31 @@ public class NotificationStackScrollLayout extends ViewGroup
}
};
private ViewGroup mQsContainer;
+ private boolean mContinuousShadowUpdate;
+ private ViewTreeObserver.OnPreDrawListener mShadowUpdater
+ = new ViewTreeObserver.OnPreDrawListener() {
+
+ @Override
+ public boolean onPreDraw() {
+ updateViewShadows();
+ return true;
+ }
+ };
+ private Comparator<ExpandableView> mViewPositionComparator = new Comparator<ExpandableView>() {
+ @Override
+ public int compare(ExpandableView view, ExpandableView otherView) {
+ float endY = view.getTranslationY() + view.getActualHeight();
+ float otherEndY = otherView.getTranslationY() + otherView.getActualHeight();
+ if (endY < otherEndY) {
+ return -1;
+ } else if (endY > otherEndY) {
+ return 1;
+ } else {
+ // The two notifications end at the same location
+ return 0;
+ }
+ }
+ };
public NotificationStackScrollLayout(Context context) {
this(context, null);
@@ -667,6 +696,7 @@ public class NotificationStackScrollLayout extends ViewGroup
}
mSwipedOutViews.add(v);
mAmbientState.onDragFinished(v);
+ updateContinuousShadowDrawing();
if (v instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) v;
if (row.isHeadsUp()) {
@@ -689,6 +719,7 @@ public class NotificationStackScrollLayout extends ViewGroup
@Override
public void onChildSnappedBack(View animView, float targetLeft) {
mAmbientState.onDragFinished(animView);
+ updateContinuousShadowDrawing();
if (!mDragAnimPendingChildren.contains(animView)) {
if (mAnimationsEnabled) {
mSnappedBackChildren.add(animView);
@@ -721,6 +752,7 @@ public class NotificationStackScrollLayout extends ViewGroup
mFalsingManager.onNotificatonStartDismissing();
setSwipingInProgress(true);
mAmbientState.onBeginDrag(v);
+ updateContinuousShadowDrawing();
if (mAnimationsEnabled && (mIsExpanded || !isPinnedHeadsUp(v))) {
mDragAnimPendingChildren.add(v);
mNeedsAnimation = true;
@@ -2242,6 +2274,7 @@ public class NotificationStackScrollLayout extends ViewGroup
setAnimationRunning(true);
mAnimationEvents.clear();
updateBackground();
+ updateViewShadows();
} else {
applyCurrentState();
}
@@ -2824,6 +2857,43 @@ public class NotificationStackScrollLayout extends ViewGroup
}
runAnimationFinishedRunnables();
updateBackground();
+ updateViewShadows();
+ }
+
+ private void updateViewShadows() {
+ // we need to work around an issue where the shadow would not cast between siblings when
+ // their z difference is between 0 and 0.1
+
+ // Lefts first sort by Z difference
+ for (int i = 0; i < getChildCount(); i++) {
+ ExpandableView child = (ExpandableView) getChildAt(i);
+ if (child.getVisibility() != GONE) {
+ mTmpSortedChildren.add(child);
+ }
+ }
+ Collections.sort(mTmpSortedChildren, mViewPositionComparator);
+
+ // Now lets update the shadow for the views
+ ExpandableView previous = null;
+ for (int i = 0; i < mTmpSortedChildren.size(); i++) {
+ ExpandableView expandableView = mTmpSortedChildren.get(i);
+ float translationZ = expandableView.getTranslationZ();
+ float otherZ = previous == null ? translationZ : previous.getTranslationZ();
+ float diff = otherZ - translationZ;
+ if (diff <= 0.0f || diff >= FakeShadowView.SHADOW_SIBLING_TRESHOLD) {
+ // There is no fake shadow to be drawn
+ expandableView.setFakeShadowIntensity(0.0f, 0.0f, 0, 0);
+ } else {
+ float yLocation = previous.getTranslationY() + previous.getActualHeight() -
+ expandableView.getTranslationY();
+ expandableView.setFakeShadowIntensity(diff / FakeShadowView.SHADOW_SIBLING_TRESHOLD,
+ previous.getOutlineAlpha(), (int) yLocation,
+ previous.getOutlineTranslation());
+ }
+ previous = expandableView;
+ }
+
+ mTmpSortedChildren.clear();
}
public void goToFullShade(long delay) {
@@ -3262,6 +3332,7 @@ public class NotificationStackScrollLayout extends ViewGroup
getViewTreeObserver().removeOnPreDrawListener(mBackgroundUpdater);
}
mAnimationRunning = animationRunning;
+ updateContinuousShadowDrawing();
}
}
@@ -3549,6 +3620,18 @@ public class NotificationStackScrollLayout extends ViewGroup
}
}
+ private void updateContinuousShadowDrawing() {
+ boolean continuousShadowUpdate = mAnimationRunning
+ || !mAmbientState.getDraggedViews().isEmpty();
+ if (continuousShadowUpdate != mContinuousShadowUpdate) {
+ if (continuousShadowUpdate) {
+ getViewTreeObserver().addOnPreDrawListener(mShadowUpdater);
+ } else {
+ getViewTreeObserver().removeOnPreDrawListener(mShadowUpdater);
+ }
+ }
+ }
+
static class AnimationEvent {
static AnimationFilter[] FILTERS = new AnimationFilter[] {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index e87b36397c7a..d78d62680860 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -24,6 +24,7 @@ import android.view.ViewGroup;
import com.android.systemui.R;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.ExpandableView;
+import com.android.systemui.statusbar.notification.FakeShadowView;
import java.util.ArrayList;
import java.util.HashSet;
@@ -605,20 +606,40 @@ public class StackScrollAlgorithm {
private void updateZValuesForState(StackScrollState resultState,
StackScrollAlgorithmState algorithmState, AmbientState ambientState) {
int childCount = algorithmState.visibleChildren.size();
- int childrenOnTop = 0;
+ float childrenOnTop = 0.0f;
for (int i = childCount - 1; i >= 0; i--) {
ExpandableView child = algorithmState.visibleChildren.get(i);
StackViewState childViewState = resultState.getViewStateForView(child);
if (i > (childCount - 1 - algorithmState.itemsInBottomStack)) {
// We are in the bottom stack
float numItemsAbove = i - (childCount - 1 - algorithmState.itemsInBottomStack);
- childViewState.zTranslation = mZBasicHeight
- - numItemsAbove * mZDistanceBetweenElements;
+ float zSubtraction;
+ if (numItemsAbove <= 1.0f) {
+ float factor = 0.2f;
+ // Lets fade in slower to the threshold to make the shadow fade in look nicer
+ if (numItemsAbove <= factor) {
+ zSubtraction = FakeShadowView.SHADOW_SIBLING_TRESHOLD
+ * numItemsAbove * (1.0f / factor);
+ } else {
+ zSubtraction = FakeShadowView.SHADOW_SIBLING_TRESHOLD
+ + (numItemsAbove - factor) * (1.0f / (1.0f - factor))
+ * (mZDistanceBetweenElements
+ - FakeShadowView.SHADOW_SIBLING_TRESHOLD);
+ }
+ } else {
+ zSubtraction = numItemsAbove * mZDistanceBetweenElements;
+ }
+ childViewState.zTranslation = mZBasicHeight - zSubtraction;
} else if (child.mustStayOnScreen()
&& childViewState.yTranslation < ambientState.getTopPadding()
+ ambientState.getStackTranslation()) {
- // TODO; do this more cleanly
- childrenOnTop++;
+ if (childrenOnTop != 0.0f) {
+ childrenOnTop++;
+ } else {
+ float overlap = ambientState.getTopPadding()
+ + ambientState.getStackTranslation() - childViewState.yTranslation;
+ childrenOnTop += Math.min(1.0f, overlap / childViewState.height);
+ }
childViewState.zTranslation = mZBasicHeight
+ childrenOnTop * mZDistanceBetweenElements;
} else {