blob: abb4cf63ead9df8e1e2f8cedee6c38b9663d3fa3 [file] [log] [blame]
/*
* 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.notification;
import android.content.Context;
import android.graphics.Color;
import android.service.notification.StatusBarNotification;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.TransformableView;
import com.android.systemui.statusbar.ViewTransformationHelper;
/**
* Wraps a notification view inflated from a template.
*/
public class NotificationTemplateViewWrapper extends NotificationHeaderViewWrapper {
private static final int mDarkProgressTint = 0xffffffff;
protected ImageView mPicture;
private ProgressBar mProgressBar;
private TextView mTitle;
private TextView mText;
private View mActionsContainer;
private int mContentHeight;
private int mMinHeightHint;
protected NotificationTemplateViewWrapper(Context ctx, View view,
ExpandableNotificationRow row) {
super(ctx, view, row);
mTransformationHelper.setCustomTransformation(
new ViewTransformationHelper.CustomTransformation() {
@Override
public boolean transformTo(TransformState ownState,
TransformableView notification, final float transformationAmount) {
if (!(notification instanceof HybridNotificationView)) {
return false;
}
TransformState otherState = notification.getCurrentState(
TRANSFORMING_VIEW_TITLE);
final View text = ownState.getTransformedView();
CrossFadeHelper.fadeOut(text, transformationAmount);
if (otherState != null) {
ownState.transformViewVerticalTo(otherState, this,
transformationAmount);
otherState.recycle();
}
return true;
}
@Override
public boolean customTransformTarget(TransformState ownState,
TransformState otherState) {
float endY = getTransformationY(ownState, otherState);
ownState.setTransformationEndY(endY);
return true;
}
@Override
public boolean transformFrom(TransformState ownState,
TransformableView notification, float transformationAmount) {
if (!(notification instanceof HybridNotificationView)) {
return false;
}
TransformState otherState = notification.getCurrentState(
TRANSFORMING_VIEW_TITLE);
final View text = ownState.getTransformedView();
CrossFadeHelper.fadeIn(text, transformationAmount);
if (otherState != null) {
ownState.transformViewVerticalFrom(otherState, this,
transformationAmount);
otherState.recycle();
}
return true;
}
@Override
public boolean initTransformation(TransformState ownState,
TransformState otherState) {
float startY = getTransformationY(ownState, otherState);
ownState.setTransformationStartY(startY);
return true;
}
private float getTransformationY(TransformState ownState,
TransformState otherState) {
int[] otherStablePosition = otherState.getLaidOutLocationOnScreen();
int[] ownStablePosition = ownState.getLaidOutLocationOnScreen();
return (otherStablePosition[1]
+ otherState.getTransformedView().getHeight()
- ownStablePosition[1]) * 0.33f;
}
}, TRANSFORMING_VIEW_TEXT);
}
private void resolveTemplateViews(StatusBarNotification notification) {
mPicture = (ImageView) mView.findViewById(com.android.internal.R.id.right_icon);
if (mPicture != null) {
mPicture.setTag(ImageTransformState.ICON_TAG,
notification.getNotification().getLargeIcon());
}
mTitle = (TextView) mView.findViewById(com.android.internal.R.id.title);
mText = (TextView) mView.findViewById(com.android.internal.R.id.text);
final View progress = mView.findViewById(com.android.internal.R.id.progress);
if (progress instanceof ProgressBar) {
mProgressBar = (ProgressBar) progress;
} else {
// It's still a viewstub
mProgressBar = null;
}
mActionsContainer = mView.findViewById(com.android.internal.R.id.actions_container);
}
@Override
public void onContentUpdated(ExpandableNotificationRow row) {
// Reinspect the notification. Before the super call, because the super call also updates
// the transformation types and we need to have our values set by then.
resolveTemplateViews(row.getStatusBarNotification());
super.onContentUpdated(row);
}
@Override
protected void updateInvertHelper() {
super.updateInvertHelper();
View mainColumn = mView.findViewById(com.android.internal.R.id.notification_main_column);
if (mainColumn != null) {
mInvertHelper.addTarget(mainColumn);
}
}
@Override
protected void updateTransformedTypes() {
// This also clears the existing types
super.updateTransformedTypes();
if (mTitle != null) {
mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TITLE,
mTitle);
}
if (mText != null) {
mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TEXT,
mText);
}
if (mPicture != null) {
mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_IMAGE,
mPicture);
}
if (mProgressBar != null) {
mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_PROGRESS,
mProgressBar);
}
}
@Override
public void setDark(boolean dark, boolean fade, long delay) {
if (dark == mDark && mDarkInitialized) {
return;
}
super.setDark(dark, fade, delay);
setPictureDark(dark, fade, delay);
setProgressBarDark(dark, fade, delay);
}
private void setProgressBarDark(boolean dark, boolean fade, long delay) {
if (mProgressBar != null) {
if (fade) {
fadeProgressDark(mProgressBar, dark, delay);
} else {
updateProgressDark(mProgressBar, dark);
}
}
}
private void fadeProgressDark(final ProgressBar target, final boolean dark, long delay) {
getDozer().startIntensityAnimation(animation -> {
float t = (float) animation.getAnimatedValue();
updateProgressDark(target, t);
}, dark, delay, null /* listener */);
}
private void updateProgressDark(ProgressBar target, float intensity) {
int color = interpolateColor(mColor, mDarkProgressTint, intensity);
target.getIndeterminateDrawable().mutate().setTint(color);
target.getProgressDrawable().mutate().setTint(color);
}
private void updateProgressDark(ProgressBar target, boolean dark) {
updateProgressDark(target, dark ? 1f : 0f);
}
private void setPictureDark(boolean dark, boolean fade, long delay) {
if (mPicture != null) {
getDozer().setImageDark(mPicture, dark, fade, delay, true /* useGrayscale */);
}
}
private static int interpolateColor(int source, int target, float t) {
int aSource = Color.alpha(source);
int rSource = Color.red(source);
int gSource = Color.green(source);
int bSource = Color.blue(source);
int aTarget = Color.alpha(target);
int rTarget = Color.red(target);
int gTarget = Color.green(target);
int bTarget = Color.blue(target);
return Color.argb(
(int) (aSource * (1f - t) + aTarget * t),
(int) (rSource * (1f - t) + rTarget * t),
(int) (gSource * (1f - t) + gTarget * t),
(int) (bSource * (1f - t) + bTarget * t));
}
@Override
public void setContentHeight(int contentHeight, int minHeightHint) {
super.setContentHeight(contentHeight, minHeightHint);
mContentHeight = contentHeight;
mMinHeightHint = minHeightHint;
updateActionOffset();
}
private void updateActionOffset() {
if (mActionsContainer != null) {
// We should never push the actions higher than they are in the headsup view.
int constrainedContentHeight = Math.max(mContentHeight, mMinHeightHint);
mActionsContainer.setTranslationY(constrainedContentHeight - mView.getHeight());
}
}
}