1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package com.android.systemui.statusbar.notification.row;
18 
19 import static android.app.Notification.COLOR_INVALID;
20 
21 import android.annotation.Nullable;
22 import android.content.Context;
23 import android.content.res.TypedArray;
24 import android.text.TextUtils;
25 import android.util.AttributeSet;
26 import android.view.View;
27 import android.widget.TextView;
28 
29 import androidx.annotation.ColorInt;
30 
31 import com.android.internal.util.ContrastColorUtil;
32 import com.android.keyguard.AlphaOptimizedLinearLayout;
33 import com.android.systemui.R;
34 import com.android.systemui.statusbar.CrossFadeHelper;
35 import com.android.systemui.statusbar.TransformableView;
36 import com.android.systemui.statusbar.ViewTransformationHelper;
37 import com.android.systemui.statusbar.notification.NotificationFadeAware;
38 import com.android.systemui.statusbar.notification.TransformState;
39 
40 /**
41  * A hybrid view which may contain information about one ore more notifications.
42  */
43 public class HybridNotificationView extends AlphaOptimizedLinearLayout
44         implements TransformableView, NotificationFadeAware {
45 
46     protected final ViewTransformationHelper mTransformationHelper = new ViewTransformationHelper();
47     protected TextView mTitleView;
48     protected TextView mTextView;
49     protected int mPrimaryTextColor = COLOR_INVALID;
50     protected int mSecondaryTextColor = COLOR_INVALID;
51 
HybridNotificationView(Context context)52     public HybridNotificationView(Context context) {
53         this(context, null);
54     }
55 
HybridNotificationView(Context context, @Nullable AttributeSet attrs)56     public HybridNotificationView(Context context, @Nullable AttributeSet attrs) {
57         this(context, attrs, 0);
58     }
59 
HybridNotificationView(Context context, @Nullable AttributeSet attrs, int defStyleAttr)60     public HybridNotificationView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
61         this(context, attrs, defStyleAttr, 0);
62     }
63 
HybridNotificationView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes)64     public HybridNotificationView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
65             int defStyleRes) {
66         super(context, attrs, defStyleAttr, defStyleRes);
67     }
68 
getTitleView()69     public TextView getTitleView() {
70         return mTitleView;
71     }
72 
getTextView()73     public TextView getTextView() {
74         return mTextView;
75     }
76 
77     @Override
onFinishInflate()78     protected void onFinishInflate() {
79         super.onFinishInflate();
80         resolveThemeTextColors();
81         mTitleView = findViewById(R.id.notification_title);
82         mTextView = findViewById(R.id.notification_text);
83         applyTextColor(mTitleView, mPrimaryTextColor);
84         applyTextColor(mTextView, mSecondaryTextColor);
85         mTransformationHelper.setCustomTransformation(
86                 new FadeOutAndDownWithTitleTransformation(mTextView),
87                 TRANSFORMING_VIEW_TEXT);
88         mTransformationHelper.addTransformedView(TRANSFORMING_VIEW_TITLE, mTitleView);
89         mTransformationHelper.addTransformedView(TRANSFORMING_VIEW_TEXT, mTextView);
90     }
91 
applyTextColor(TextView textView, @ColorInt int textColor)92     protected void applyTextColor(TextView textView, @ColorInt int textColor) {
93         if (textColor != COLOR_INVALID) {
94             textView.setTextColor(textColor);
95         }
96     }
97 
resolveThemeTextColors()98     private void resolveThemeTextColors() {
99         try (TypedArray ta = mContext.getTheme().obtainStyledAttributes(
100                 android.R.style.Theme_DeviceDefault_DayNight, new int[]{
101                         android.R.attr.textColorPrimary,
102                         android.R.attr.textColorSecondary
103                 })) {
104             if (ta != null) {
105                 mPrimaryTextColor = ta.getColor(0, mPrimaryTextColor);
106                 mSecondaryTextColor = ta.getColor(1, mSecondaryTextColor);
107             }
108         }
109     }
110 
bind(@ullable CharSequence title, @Nullable CharSequence text, @Nullable View contentView)111     public void bind(@Nullable CharSequence title, @Nullable CharSequence text,
112             @Nullable View contentView) {
113         mTitleView.setText(title != null ? title.toString() : title);
114         mTitleView.setVisibility(TextUtils.isEmpty(title) ? GONE : VISIBLE);
115         if (TextUtils.isEmpty(text)) {
116             mTextView.setVisibility(GONE);
117             mTextView.setText(null);
118         } else {
119             mTextView.setVisibility(VISIBLE);
120             mTextView.setText(text.toString());
121         }
122         requestLayout();
123     }
124 
125     @Override
getCurrentState(int fadingView)126     public TransformState getCurrentState(int fadingView) {
127         return mTransformationHelper.getCurrentState(fadingView);
128     }
129 
130     @Override
transformTo(TransformableView notification, Runnable endRunnable)131     public void transformTo(TransformableView notification, Runnable endRunnable) {
132         mTransformationHelper.transformTo(notification, endRunnable);
133     }
134 
135     @Override
transformTo(TransformableView notification, float transformationAmount)136     public void transformTo(TransformableView notification, float transformationAmount) {
137         mTransformationHelper.transformTo(notification, transformationAmount);
138     }
139 
140     @Override
transformFrom(TransformableView notification)141     public void transformFrom(TransformableView notification) {
142         mTransformationHelper.transformFrom(notification);
143     }
144 
145     @Override
transformFrom(TransformableView notification, float transformationAmount)146     public void transformFrom(TransformableView notification, float transformationAmount) {
147         mTransformationHelper.transformFrom(notification, transformationAmount);
148     }
149 
150     @Override
setVisible(boolean visible)151     public void setVisible(boolean visible) {
152         setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
153         mTransformationHelper.setVisible(visible);
154     }
155 
156     @Override
setNotificationFaded(boolean faded)157     public void setNotificationFaded(boolean faded) {}
158 
159     protected static class FadeOutAndDownWithTitleTransformation extends
160             ViewTransformationHelper.CustomTransformation {
161 
162         private final View mView;
163 
FadeOutAndDownWithTitleTransformation(View view)164         public FadeOutAndDownWithTitleTransformation(View view) {
165             mView = view;
166         }
167 
168         @Override
transformTo(TransformState ownState, TransformableView notification, float transformationAmount)169         public boolean transformTo(TransformState ownState, TransformableView notification,
170                 float transformationAmount) {
171             // We want to transform to the same y location as the title
172             TransformState otherState = notification.getCurrentState(TRANSFORMING_VIEW_TITLE);
173             CrossFadeHelper.fadeOut(mView, transformationAmount);
174             if (otherState != null) {
175                 ownState.transformViewVerticalTo(otherState, transformationAmount);
176                 otherState.recycle();
177             }
178             return true;
179         }
180 
181         @Override
transformFrom(TransformState ownState, TransformableView notification, float transformationAmount)182         public boolean transformFrom(TransformState ownState,
183                 TransformableView notification, float transformationAmount) {
184             // We want to transform from the same y location as the title
185             TransformState otherState = notification.getCurrentState(TRANSFORMING_VIEW_TITLE);
186             CrossFadeHelper.fadeIn(mView, transformationAmount, true /* remap */);
187             if (otherState != null) {
188                 ownState.transformViewVerticalFrom(otherState, transformationAmount);
189                 otherState.recycle();
190             }
191             return true;
192         }
193     }
194 }
195