1 /* 2 * Copyright (C) 2018 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.example.sampleleanbacklauncher.notifications; 18 19 import android.content.Context; 20 import android.content.res.Configuration; 21 import android.content.res.Resources; 22 import android.graphics.Canvas; 23 import android.graphics.Color; 24 import android.graphics.Paint; 25 import android.graphics.RectF; 26 import android.text.Layout; 27 import android.text.TextUtils; 28 import android.util.AttributeSet; 29 import android.view.View; 30 import android.view.ViewTreeObserver; 31 import android.widget.ImageView; 32 import android.widget.LinearLayout; 33 import android.widget.TextView; 34 35 import com.example.sampleleanbacklauncher.R; 36 37 /** 38 * View for a non-dismissible notification displayed in the notifications side panel. 39 */ 40 public class NotificationPanelItemView extends LinearLayout 41 implements ViewTreeObserver.OnGlobalFocusChangeListener { 42 private RectF mProgressBounds; 43 private Paint mProgressPaint; 44 private Paint mProgressMaxPaint; 45 private int mProgressStrokeWidth; 46 private int mProgressDiameter; 47 private int mProgressPaddingStart; 48 private int mProgressPaddingTop; 49 private int mProgressColor; 50 private int mProgressMaxColor; 51 private int mProgress; 52 private int mProgressMax; 53 private boolean mIsRtl; 54 private ImageView mIcon; 55 private TextView mTitle; 56 private TextView mText; 57 private TextView mExpandedText; 58 protected View mMainContentText; 59 protected String mNotificationKey; 60 private TvNotification mNotification; 61 NotificationPanelItemView(Context context)62 public NotificationPanelItemView(Context context) { 63 super(context); 64 initializeLayoutValues(); 65 } 66 NotificationPanelItemView(Context context, AttributeSet attrs)67 public NotificationPanelItemView(Context context, AttributeSet attrs) { 68 super(context, attrs); 69 initializeLayoutValues(); 70 } 71 initializeLayoutValues()72 private void initializeLayoutValues() { 73 Configuration config = getContext().getResources().getConfiguration(); 74 mIsRtl = (config.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL); 75 76 Resources res = getResources(); 77 mProgressStrokeWidth = res.getDimensionPixelSize( 78 R.dimen.notification_progress_stroke_width); 79 mProgressColor = res.getColor(R.color.notification_progress_stroke_color, null); 80 mProgressMaxColor = res.getColor(R.color.notification_progress_stroke_max_color, null); 81 mProgressDiameter = res.getDimensionPixelSize(R.dimen.notification_progress_circle_size); 82 mProgressPaddingTop = res.getDimensionPixelOffset( 83 R.dimen.notification_progress_circle_padding_top); 84 mProgressPaddingStart = res.getDimensionPixelOffset( 85 R.dimen.notification_progress_circle_padding_start); 86 87 mProgressPaint = new Paint(); 88 mProgressPaint.setAntiAlias(true); 89 mProgressPaint.setStyle(Paint.Style.STROKE); 90 mProgressPaint.setColor(mProgressColor); 91 mProgressPaint.setStrokeWidth(mProgressStrokeWidth); 92 93 mProgressMaxPaint = new Paint(); 94 mProgressMaxPaint.setAntiAlias(true); 95 mProgressMaxPaint.setStyle(Paint.Style.STROKE); 96 mProgressMaxPaint.setColor(mProgressMaxColor); 97 mProgressMaxPaint.setStrokeWidth(mProgressStrokeWidth); 98 } 99 100 @Override onAttachedToWindow()101 protected void onAttachedToWindow() { 102 super.onAttachedToWindow(); 103 getViewTreeObserver().addOnGlobalFocusChangeListener(this); 104 } 105 106 @Override onDetachedFromWindow()107 protected void onDetachedFromWindow() { 108 super.onDetachedFromWindow(); 109 getViewTreeObserver().removeOnGlobalFocusChangeListener(this); 110 } 111 112 @Override onFinishInflate()113 protected void onFinishInflate() { 114 super.onFinishInflate(); 115 mIcon = findViewById(R.id.notification_icon); 116 mTitle = findViewById(R.id.notification_title); 117 mText = findViewById(R.id.notification_text); 118 mMainContentText = findViewById(R.id.notification_container); 119 mExpandedText = findViewById(R.id.notification_expanded_text); 120 121 mMainContentText.setOnClickListener(new View.OnClickListener() { 122 @Override 123 public void onClick(View view) { 124 if (mNotificationKey != null) { 125 NotificationsUtils.openNotification(view.getContext(), mNotificationKey); 126 } 127 } 128 }); 129 } 130 setNotification(TvNotification notif)131 public void setNotification(TvNotification notif) { 132 mNotification = notif; 133 mNotificationKey = notif.getNotificationKey(); 134 mTitle.setText(notif.getTitle()); 135 mText.setText(notif.getText()); 136 if (!TextUtils.isEmpty(notif.getTitle())) { 137 if (!TextUtils.isEmpty(notif.getText())) { 138 String formatting = getResources().getString( 139 R.string.notification_content_description_format); 140 mMainContentText.setContentDescription( 141 String.format(formatting, notif.getTitle(), notif.getText())); 142 } else { 143 mMainContentText.setContentDescription(notif.getTitle()); 144 } 145 } else { 146 mMainContentText.setContentDescription(notif.getText()); 147 } 148 mExpandedText.setText(notif.getText()); 149 mIcon.setImageIcon(notif.getSmallIcon()); 150 setProgress(notif.getProgress(), notif.getProgressMax()); 151 mMainContentText.setVisibility(VISIBLE); 152 } 153 setProgress(int progress, int progressMax)154 public void setProgress(int progress, int progressMax) { 155 mProgress = progress; 156 mProgressMax = progressMax; 157 if (mProgressMax != 0) { 158 if (mProgressBounds == null) { 159 mProgressBounds = new RectF(); 160 } 161 setWillNotDraw(false); 162 } else { 163 mProgressBounds = null; 164 setWillNotDraw(true); 165 } 166 requestLayout(); 167 } 168 169 @Override onLayout(boolean changed, int l, int t, int r, int b)170 protected void onLayout(boolean changed, int l, int t, int r, int b) { 171 super.onLayout(changed, l, t, r, b); 172 if (mProgressBounds != null) { 173 int left, right; 174 int top = mProgressPaddingTop; 175 int bottom = top + mProgressDiameter; 176 if (mIsRtl) { 177 right = r - mProgressPaddingStart; 178 left = right - mProgressDiameter; 179 } else { 180 left = mProgressPaddingStart; 181 right = left + mProgressDiameter; 182 } 183 184 mProgressBounds.set(left, top, right, bottom); 185 } 186 } 187 188 @Override onDraw(Canvas canvas)189 protected void onDraw(Canvas canvas) { 190 super.onDraw(canvas); 191 192 if (mProgressMax != 0) { 193 float sweepAngle = 360f * mProgress / mProgressMax; 194 if (mIsRtl) { 195 canvas.drawArc(mProgressBounds, -90, -sweepAngle, false, mProgressPaint); 196 canvas.drawArc(mProgressBounds, -90, 360 - sweepAngle, false, 197 mProgressMaxPaint); 198 } else { 199 canvas.drawArc(mProgressBounds, -90, sweepAngle, false, mProgressPaint); 200 canvas.drawArc(mProgressBounds, sweepAngle - 90, 360 - sweepAngle, false, 201 mProgressMaxPaint); 202 } 203 } 204 } 205 isContentTextCutOff()206 private boolean isContentTextCutOff() { 207 Layout layout = mText.getLayout(); 208 if (layout != null) { 209 int lines = layout.getLineCount(); 210 if (lines > 0) { 211 int ellipsisCount = layout.getEllipsisCount(lines - 1); 212 if (ellipsisCount > 0) { 213 return true; 214 } 215 } 216 } 217 return false; 218 } 219 expandText()220 protected void expandText() { 221 mText.setVisibility(GONE); 222 mTitle.setMaxLines(2); 223 mExpandedText.setVisibility(VISIBLE); 224 setBackgroundColor( 225 getResources().getColor(R.color.notification_expanded_text_background)); 226 } 227 collapseText()228 protected void collapseText() { 229 mExpandedText.setVisibility(GONE); 230 mTitle.setMaxLines(1); 231 mText.setVisibility(VISIBLE); 232 setBackgroundColor(Color.TRANSPARENT); 233 } 234 235 @Override onGlobalFocusChanged(View oldFocus, View newFocus)236 public void onGlobalFocusChanged(View oldFocus, View newFocus) { 237 View currentFocus = getFocusedChild(); 238 if (currentFocus == null) { 239 collapseText(); 240 } else if ((newFocus == currentFocus || newFocus.getParent() == currentFocus) 241 && isContentTextCutOff()) { 242 expandText(); 243 } 244 } 245 } 246