1 /* 2 * Copyright (C) 2014 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.graphics.PorterDuff.Mode.SRC_ATOP; 20 21 import android.annotation.ColorInt; 22 import android.content.Context; 23 import android.content.res.ColorStateList; 24 import android.content.res.Configuration; 25 import android.content.res.Resources; 26 import android.graphics.ColorFilter; 27 import android.graphics.PorterDuffColorFilter; 28 import android.graphics.drawable.Drawable; 29 import android.util.AttributeSet; 30 import android.util.IndentingPrintWriter; 31 import android.view.View; 32 import android.widget.TextView; 33 34 import androidx.annotation.NonNull; 35 36 import com.android.settingslib.Utils; 37 import com.android.systemui.R; 38 import com.android.systemui.statusbar.notification.stack.ExpandableViewState; 39 import com.android.systemui.statusbar.notification.stack.ViewState; 40 import com.android.systemui.util.DumpUtilsKt; 41 42 import java.io.PrintWriter; 43 44 public class FooterView extends StackScrollerDecorView { 45 private FooterViewButton mClearAllButton; 46 private FooterViewButton mManageButton; 47 private boolean mShowHistory; 48 // String cache, for performance reasons. 49 // Reading them from a Resources object can be quite slow sometimes. 50 private String mManageNotificationText; 51 private String mManageNotificationHistoryText; 52 53 // Footer label 54 private TextView mSeenNotifsFooterTextView; 55 private String mSeenNotifsFilteredText; 56 private Drawable mSeenNotifsFilteredIcon; 57 FooterView(Context context, AttributeSet attrs)58 public FooterView(Context context, AttributeSet attrs) { 59 super(context, attrs); 60 } 61 62 @Override findContentView()63 protected View findContentView() { 64 return findViewById(R.id.content); 65 } 66 findSecondaryView()67 protected View findSecondaryView() { 68 return findViewById(R.id.dismiss_text); 69 } 70 71 @Override dump(PrintWriter pwOriginal, String[] args)72 public void dump(PrintWriter pwOriginal, String[] args) { 73 IndentingPrintWriter pw = DumpUtilsKt.asIndenting(pwOriginal); 74 super.dump(pw, args); 75 DumpUtilsKt.withIncreasedIndent(pw, () -> { 76 pw.println("visibility: " + DumpUtilsKt.visibilityString(getVisibility())); 77 pw.println("manageButton showHistory: " + mShowHistory); 78 pw.println("manageButton visibility: " 79 + DumpUtilsKt.visibilityString(mClearAllButton.getVisibility())); 80 pw.println("dismissButton visibility: " 81 + DumpUtilsKt.visibilityString(mClearAllButton.getVisibility())); 82 }); 83 } 84 85 @Override onFinishInflate()86 protected void onFinishInflate() { 87 super.onFinishInflate(); 88 mClearAllButton = (FooterViewButton) findSecondaryView(); 89 mManageButton = findViewById(R.id.manage_text); 90 mSeenNotifsFooterTextView = findViewById(R.id.unlock_prompt_footer); 91 updateResources(); 92 updateContent(); 93 updateColors(); 94 } 95 setFooterLabelVisible(boolean isVisible)96 public void setFooterLabelVisible(boolean isVisible) { 97 if (isVisible) { 98 mManageButton.setVisibility(View.GONE); 99 mClearAllButton.setVisibility(View.GONE); 100 mSeenNotifsFooterTextView.setVisibility(View.VISIBLE); 101 } else { 102 mManageButton.setVisibility(View.VISIBLE); 103 mClearAllButton.setVisibility(View.VISIBLE); 104 mSeenNotifsFooterTextView.setVisibility(View.GONE); 105 } 106 } 107 setManageButtonClickListener(OnClickListener listener)108 public void setManageButtonClickListener(OnClickListener listener) { 109 mManageButton.setOnClickListener(listener); 110 } 111 setClearAllButtonClickListener(OnClickListener listener)112 public void setClearAllButtonClickListener(OnClickListener listener) { 113 mClearAllButton.setOnClickListener(listener); 114 } 115 isOnEmptySpace(float touchX, float touchY)116 public boolean isOnEmptySpace(float touchX, float touchY) { 117 return touchX < mContent.getX() 118 || touchX > mContent.getX() + mContent.getWidth() 119 || touchY < mContent.getY() 120 || touchY > mContent.getY() + mContent.getHeight(); 121 } 122 showHistory(boolean showHistory)123 public void showHistory(boolean showHistory) { 124 if (mShowHistory == showHistory) { 125 return; 126 } 127 mShowHistory = showHistory; 128 updateContent(); 129 } 130 updateContent()131 private void updateContent() { 132 if (mShowHistory) { 133 mManageButton.setText(mManageNotificationHistoryText); 134 mManageButton.setContentDescription(mManageNotificationHistoryText); 135 } else { 136 mManageButton.setText(mManageNotificationText); 137 mManageButton.setContentDescription(mManageNotificationText); 138 } 139 mSeenNotifsFooterTextView.setText(mSeenNotifsFilteredText); 140 mSeenNotifsFooterTextView 141 .setCompoundDrawablesRelative(mSeenNotifsFilteredIcon, null, null, null); 142 } 143 isHistoryShown()144 public boolean isHistoryShown() { 145 return mShowHistory; 146 } 147 148 @Override onConfigurationChanged(Configuration newConfig)149 protected void onConfigurationChanged(Configuration newConfig) { 150 super.onConfigurationChanged(newConfig); 151 updateColors(); 152 mClearAllButton.setText(R.string.clear_all_notifications_text); 153 mClearAllButton.setContentDescription( 154 mContext.getString(R.string.accessibility_clear_all)); 155 updateResources(); 156 updateContent(); 157 } 158 159 /** 160 * Update the text and background colors for the current color palette and night mode setting. 161 */ updateColors()162 public void updateColors() { 163 Resources.Theme theme = mContext.getTheme(); 164 final @ColorInt int textColor = getResources().getColor(R.color.notif_pill_text, theme); 165 final Drawable clearAllBg = theme.getDrawable(R.drawable.notif_footer_btn_background); 166 final Drawable manageBg = theme.getDrawable(R.drawable.notif_footer_btn_background); 167 // TODO(b/282173943): Remove redundant tinting once Resources are thread-safe 168 final @ColorInt int buttonBgColor = 169 Utils.getColorAttrDefaultColor(mContext, com.android.internal.R.attr.colorSurface); 170 final ColorFilter bgColorFilter = new PorterDuffColorFilter(buttonBgColor, SRC_ATOP); 171 if (buttonBgColor != 0) { 172 clearAllBg.setColorFilter(bgColorFilter); 173 manageBg.setColorFilter(bgColorFilter); 174 } 175 mClearAllButton.setBackground(clearAllBg); 176 mClearAllButton.setTextColor(textColor); 177 mManageButton.setBackground(manageBg); 178 mManageButton.setTextColor(textColor); 179 final @ColorInt int labelTextColor = 180 Utils.getColorAttrDefaultColor(mContext, android.R.attr.textColorPrimary); 181 mSeenNotifsFooterTextView.setTextColor(labelTextColor); 182 mSeenNotifsFooterTextView.setCompoundDrawableTintList( 183 ColorStateList.valueOf(labelTextColor)); 184 } 185 updateResources()186 private void updateResources() { 187 mManageNotificationText = getContext().getString(R.string.manage_notifications_text); 188 mManageNotificationHistoryText = getContext() 189 .getString(R.string.manage_notifications_history_text); 190 int unlockIconSize = getResources() 191 .getDimensionPixelSize(R.dimen.notifications_unseen_footer_icon_size); 192 mSeenNotifsFilteredText = getContext().getString(R.string.unlock_to_see_notif_text); 193 mSeenNotifsFilteredIcon = getContext().getDrawable(R.drawable.ic_friction_lock_closed); 194 mSeenNotifsFilteredIcon.setBounds(0, 0, unlockIconSize, unlockIconSize); 195 } 196 197 @Override 198 @NonNull createExpandableViewState()199 public ExpandableViewState createExpandableViewState() { 200 return new FooterViewState(); 201 } 202 203 public class FooterViewState extends ExpandableViewState { 204 /** 205 * used to hide the content of the footer to animate. 206 * #hide is applied without animation, but #hideContent has animation. 207 */ 208 public boolean hideContent; 209 210 @Override copyFrom(ViewState viewState)211 public void copyFrom(ViewState viewState) { 212 super.copyFrom(viewState); 213 if (viewState instanceof FooterViewState) { 214 hideContent = ((FooterViewState) viewState).hideContent; 215 } 216 } 217 218 @Override applyToView(View view)219 public void applyToView(View view) { 220 super.applyToView(view); 221 if (view instanceof FooterView) { 222 FooterView footerView = (FooterView) view; 223 footerView.setContentVisible(!hideContent); 224 } 225 } 226 } 227 } 228