Merge "Added fake shadows in order to have the shadow nicely fade in" into nyc-dev

am: 9d120733a6

* commit '9d120733a66801a721108eb740596ab3ff08c940':
  Added fake shadows in order to have the shadow nicely fade in
This commit is contained in:
Selim Cinek
2016-02-23 01:20:57 +00:00
committed by android-build-merger
8 changed files with 238 additions and 6 deletions

View File

@@ -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>

View File

@@ -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>

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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.
*/

View File

@@ -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();
}
}
}
}

View File

@@ -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[] {

View File

@@ -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 {