Kunhung Li | 29007e6 | 2018-07-30 19:30:25 +0800 | [diff] [blame] | 1 | package com.android.keyguard; |
| 2 | |
Lucas Dupin | e570af6 | 2019-02-10 14:52:30 -0800 | [diff] [blame] | 3 | import android.animation.Animator; |
Lucas Dupin | 4349952 | 2019-03-04 16:45:58 -0800 | [diff] [blame] | 4 | import android.animation.AnimatorListenerAdapter; |
Lucas Dupin | e570af6 | 2019-02-10 14:52:30 -0800 | [diff] [blame] | 5 | import android.animation.AnimatorSet; |
| 6 | import android.animation.ValueAnimator; |
Robert Snoeberger | 0397c84 | 2019-02-07 14:25:46 -0500 | [diff] [blame] | 7 | import android.app.WallpaperManager; |
Kunhung Li | 29007e6 | 2018-07-30 19:30:25 +0800 | [diff] [blame] | 8 | import android.content.Context; |
| 9 | import android.graphics.Paint; |
| 10 | import android.graphics.Paint.Style; |
Lucas Dupin | e570af6 | 2019-02-10 14:52:30 -0800 | [diff] [blame] | 11 | import android.transition.ChangeBounds; |
| 12 | import android.transition.Transition; |
| 13 | import android.transition.TransitionManager; |
| 14 | import android.transition.TransitionValues; |
Kunhung Li | 29007e6 | 2018-07-30 19:30:25 +0800 | [diff] [blame] | 15 | import android.util.AttributeSet; |
Lucas Dupin | e570af6 | 2019-02-10 14:52:30 -0800 | [diff] [blame] | 16 | import android.util.MathUtils; |
| 17 | import android.util.TypedValue; |
Kunhung Li | 29007e6 | 2018-07-30 19:30:25 +0800 | [diff] [blame] | 18 | import android.view.View; |
| 19 | import android.view.ViewGroup; |
| 20 | import android.widget.FrameLayout; |
Robert Snoeberger | e3b3e78 | 2018-12-17 13:32:15 -0500 | [diff] [blame] | 21 | import android.widget.RelativeLayout; |
Kunhung Li | 29007e6 | 2018-07-30 19:30:25 +0800 | [diff] [blame] | 22 | import android.widget.TextClock; |
| 23 | |
| 24 | import androidx.annotation.VisibleForTesting; |
| 25 | |
Robert Snoeberger | 0397c84 | 2019-02-07 14:25:46 -0500 | [diff] [blame] | 26 | import com.android.internal.colorextraction.ColorExtractor; |
Robert Snoeberger | 15b4af1 | 2019-01-18 15:37:27 -0500 | [diff] [blame] | 27 | import com.android.keyguard.clock.ClockManager; |
Kunhung Li | 29007e6 | 2018-07-30 19:30:25 +0800 | [diff] [blame] | 28 | import com.android.systemui.Dependency; |
Lucas Dupin | e570af6 | 2019-02-10 14:52:30 -0800 | [diff] [blame] | 29 | import com.android.systemui.Interpolators; |
Robert Snoeberger | 0397c84 | 2019-02-07 14:25:46 -0500 | [diff] [blame] | 30 | import com.android.systemui.colorextraction.SysuiColorExtractor; |
Kunhung Li | 29007e6 | 2018-07-30 19:30:25 +0800 | [diff] [blame] | 31 | import com.android.systemui.plugins.ClockPlugin; |
Beverly | 8fdb533 | 2019-02-04 14:29:49 -0500 | [diff] [blame] | 32 | import com.android.systemui.plugins.statusbar.StatusBarStateController; |
Robert Snoeberger | 6085408 | 2019-01-04 13:13:17 -0500 | [diff] [blame] | 33 | import com.android.systemui.statusbar.StatusBarState; |
Kunhung Li | 29007e6 | 2018-07-30 19:30:25 +0800 | [diff] [blame] | 34 | |
Lucas Dupin | 4349952 | 2019-03-04 16:45:58 -0800 | [diff] [blame] | 35 | import java.io.FileDescriptor; |
| 36 | import java.io.PrintWriter; |
| 37 | import java.util.Arrays; |
Robert Snoeberger | 9c1074f | 2018-12-07 17:35:21 -0500 | [diff] [blame] | 38 | import java.util.TimeZone; |
Robert Snoeberger | 33ce6d9 | 2018-10-26 10:52:38 -0400 | [diff] [blame] | 39 | |
Kunhung Li | 29007e6 | 2018-07-30 19:30:25 +0800 | [diff] [blame] | 40 | /** |
| 41 | * Switch to show plugin clock when plugin is connected, otherwise it will show default clock. |
| 42 | */ |
Robert Snoeberger | e3b3e78 | 2018-12-17 13:32:15 -0500 | [diff] [blame] | 43 | public class KeyguardClockSwitch extends RelativeLayout { |
Robert Snoeberger | 046ee9c | 2019-01-10 18:29:38 -0500 | [diff] [blame] | 44 | |
Lucas Dupin | e570af6 | 2019-02-10 14:52:30 -0800 | [diff] [blame] | 45 | private final Transition mTransition; |
Kunhung Li | 29007e6 | 2018-07-30 19:30:25 +0800 | [diff] [blame] | 46 | /** |
| 47 | * Optional/alternative clock injected via plugin. |
| 48 | */ |
| 49 | private ClockPlugin mClockPlugin; |
| 50 | /** |
| 51 | * Default clock. |
| 52 | */ |
| 53 | private TextClock mClockView; |
Robert Snoeberger | e3b3e78 | 2018-12-17 13:32:15 -0500 | [diff] [blame] | 54 | /** |
| 55 | * Frame for default and custom clock. |
| 56 | */ |
Robert Snoeberger | 6a0140a | 2018-12-20 12:46:17 -0500 | [diff] [blame] | 57 | private FrameLayout mSmallClockFrame; |
| 58 | /** |
| 59 | * Container for big custom clock. |
| 60 | */ |
| 61 | private ViewGroup mBigClockContainer; |
Robert Snoeberger | e3b3e78 | 2018-12-17 13:32:15 -0500 | [diff] [blame] | 62 | /** |
| 63 | * Status area (date and other stuff) shown below the clock. Plugin can decide whether |
| 64 | * or not to show it below the alternate clock. |
| 65 | */ |
| 66 | private View mKeyguardStatusArea; |
Robert Snoeberger | 8bf1a3c | 2019-01-10 10:30:09 -0500 | [diff] [blame] | 67 | /** |
Robert Snoeberger | 58f2315 | 2019-01-10 15:51:32 -0500 | [diff] [blame] | 68 | * Maintain state so that a newly connected plugin can be initialized. |
| 69 | */ |
| 70 | private float mDarkAmount; |
Lucas Dupin | e570af6 | 2019-02-10 14:52:30 -0800 | [diff] [blame] | 71 | /** |
| 72 | * If the Keyguard Slice has a header (big center-aligned text.) |
| 73 | */ |
| 74 | private boolean mShowingHeader; |
Robert Snoeberger | 0397c84 | 2019-02-07 14:25:46 -0500 | [diff] [blame] | 75 | private boolean mSupportsDarkText; |
| 76 | private int[] mColorPalette; |
Kunhung Li | 29007e6 | 2018-07-30 19:30:25 +0800 | [diff] [blame] | 77 | |
Robert Snoeberger | 6085408 | 2019-01-04 13:13:17 -0500 | [diff] [blame] | 78 | private final StatusBarStateController.StateListener mStateListener = |
| 79 | new StatusBarStateController.StateListener() { |
| 80 | @Override |
| 81 | public void onStateChanged(int newState) { |
| 82 | if (mBigClockContainer == null) { |
| 83 | return; |
| 84 | } |
| 85 | if (newState == StatusBarState.SHADE) { |
| 86 | if (mBigClockContainer.getVisibility() == View.VISIBLE) { |
| 87 | mBigClockContainer.setVisibility(View.INVISIBLE); |
| 88 | } |
| 89 | } else { |
| 90 | if (mBigClockContainer.getVisibility() == View.INVISIBLE) { |
| 91 | mBigClockContainer.setVisibility(View.VISIBLE); |
| 92 | } |
| 93 | } |
| 94 | } |
| 95 | }; |
Kunhung Li | 29007e6 | 2018-07-30 19:30:25 +0800 | [diff] [blame] | 96 | |
Robert Snoeberger | 15b4af1 | 2019-01-18 15:37:27 -0500 | [diff] [blame] | 97 | private ClockManager.ClockChangedListener mClockChangedListener = this::setClockPlugin; |
Robert Snoeberger | 046ee9c | 2019-01-10 18:29:38 -0500 | [diff] [blame] | 98 | |
Robert Snoeberger | 0397c84 | 2019-02-07 14:25:46 -0500 | [diff] [blame] | 99 | /** |
| 100 | * Listener for changes to the color palette. |
| 101 | * |
| 102 | * The color palette changes when the wallpaper is changed. |
| 103 | */ |
| 104 | private SysuiColorExtractor.OnColorsChangedListener mColorsListener = (extractor, which) -> { |
| 105 | if ((which & WallpaperManager.FLAG_LOCK) != 0) { |
| 106 | if (extractor instanceof SysuiColorExtractor) { |
| 107 | updateColors((SysuiColorExtractor) extractor); |
| 108 | } else { |
| 109 | updateColors(Dependency.get(SysuiColorExtractor.class)); |
| 110 | } |
| 111 | } |
| 112 | }; |
| 113 | |
Kunhung Li | 29007e6 | 2018-07-30 19:30:25 +0800 | [diff] [blame] | 114 | public KeyguardClockSwitch(Context context) { |
| 115 | this(context, null); |
| 116 | } |
| 117 | |
| 118 | public KeyguardClockSwitch(Context context, AttributeSet attrs) { |
| 119 | super(context, attrs); |
Lucas Dupin | e570af6 | 2019-02-10 14:52:30 -0800 | [diff] [blame] | 120 | mTransition = new ClockBoundsTransition(); |
Kunhung Li | 29007e6 | 2018-07-30 19:30:25 +0800 | [diff] [blame] | 121 | } |
| 122 | |
Lucas Dupin | 7fc9dc1 | 2019-01-03 09:19:43 -0800 | [diff] [blame] | 123 | /** |
| 124 | * Returns if this view is presenting a custom clock, or the default implementation. |
| 125 | */ |
| 126 | public boolean hasCustomClock() { |
| 127 | return mClockPlugin != null; |
| 128 | } |
| 129 | |
Kunhung Li | 29007e6 | 2018-07-30 19:30:25 +0800 | [diff] [blame] | 130 | @Override |
| 131 | protected void onFinishInflate() { |
| 132 | super.onFinishInflate(); |
| 133 | mClockView = findViewById(R.id.default_clock_view); |
Robert Snoeberger | 6a0140a | 2018-12-20 12:46:17 -0500 | [diff] [blame] | 134 | mSmallClockFrame = findViewById(R.id.clock_view); |
Robert Snoeberger | e3b3e78 | 2018-12-17 13:32:15 -0500 | [diff] [blame] | 135 | mKeyguardStatusArea = findViewById(R.id.keyguard_status_area); |
Kunhung Li | 29007e6 | 2018-07-30 19:30:25 +0800 | [diff] [blame] | 136 | } |
| 137 | |
| 138 | @Override |
| 139 | protected void onAttachedToWindow() { |
| 140 | super.onAttachedToWindow(); |
Robert Snoeberger | 15b4af1 | 2019-01-18 15:37:27 -0500 | [diff] [blame] | 141 | Dependency.get(ClockManager.class).addOnClockChangedListener(mClockChangedListener); |
Robert Snoeberger | 6085408 | 2019-01-04 13:13:17 -0500 | [diff] [blame] | 142 | Dependency.get(StatusBarStateController.class).addCallback(mStateListener); |
Robert Snoeberger | 0397c84 | 2019-02-07 14:25:46 -0500 | [diff] [blame] | 143 | SysuiColorExtractor colorExtractor = Dependency.get(SysuiColorExtractor.class); |
| 144 | colorExtractor.addOnColorsChangedListener(mColorsListener); |
| 145 | updateColors(colorExtractor); |
Kunhung Li | 29007e6 | 2018-07-30 19:30:25 +0800 | [diff] [blame] | 146 | } |
| 147 | |
| 148 | @Override |
| 149 | protected void onDetachedFromWindow() { |
| 150 | super.onDetachedFromWindow(); |
Robert Snoeberger | 15b4af1 | 2019-01-18 15:37:27 -0500 | [diff] [blame] | 151 | Dependency.get(ClockManager.class).removeOnClockChangedListener(mClockChangedListener); |
Robert Snoeberger | 6085408 | 2019-01-04 13:13:17 -0500 | [diff] [blame] | 152 | Dependency.get(StatusBarStateController.class).removeCallback(mStateListener); |
Robert Snoeberger | 0397c84 | 2019-02-07 14:25:46 -0500 | [diff] [blame] | 153 | Dependency.get(SysuiColorExtractor.class) |
| 154 | .removeOnColorsChangedListener(mColorsListener); |
Robert Snoeberger | d747025 | 2019-03-04 16:05:36 -0500 | [diff] [blame] | 155 | setClockPlugin(null); |
Kunhung Li | 29007e6 | 2018-07-30 19:30:25 +0800 | [diff] [blame] | 156 | } |
| 157 | |
Robert Snoeberger | 8bf1a3c | 2019-01-10 10:30:09 -0500 | [diff] [blame] | 158 | private void setClockPlugin(ClockPlugin plugin) { |
| 159 | // Disconnect from existing plugin. |
| 160 | if (mClockPlugin != null) { |
| 161 | View smallClockView = mClockPlugin.getView(); |
| 162 | if (smallClockView != null && smallClockView.getParent() == mSmallClockFrame) { |
| 163 | mSmallClockFrame.removeView(smallClockView); |
| 164 | } |
| 165 | if (mBigClockContainer != null) { |
| 166 | mBigClockContainer.removeAllViews(); |
| 167 | mBigClockContainer.setVisibility(View.GONE); |
| 168 | } |
| 169 | mClockPlugin = null; |
| 170 | } |
| 171 | if (plugin == null) { |
| 172 | mClockView.setVisibility(View.VISIBLE); |
| 173 | mKeyguardStatusArea.setVisibility(View.VISIBLE); |
| 174 | return; |
| 175 | } |
| 176 | // Attach small and big clock views to hierarchy. |
| 177 | View smallClockView = plugin.getView(); |
| 178 | if (smallClockView != null) { |
| 179 | mSmallClockFrame.addView(smallClockView, -1, |
| 180 | new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, |
| 181 | ViewGroup.LayoutParams.WRAP_CONTENT)); |
| 182 | mClockView.setVisibility(View.GONE); |
| 183 | } |
| 184 | View bigClockView = plugin.getBigClockView(); |
| 185 | if (bigClockView != null && mBigClockContainer != null) { |
| 186 | mBigClockContainer.addView(bigClockView); |
| 187 | mBigClockContainer.setVisibility(View.VISIBLE); |
| 188 | } |
| 189 | // Hide default clock. |
| 190 | if (!plugin.shouldShowStatusArea()) { |
| 191 | mKeyguardStatusArea.setVisibility(View.GONE); |
| 192 | } |
| 193 | // Initialize plugin parameters. |
| 194 | mClockPlugin = plugin; |
| 195 | mClockPlugin.setStyle(getPaint().getStyle()); |
| 196 | mClockPlugin.setTextColor(getCurrentTextColor()); |
Robert Snoeberger | 58f2315 | 2019-01-10 15:51:32 -0500 | [diff] [blame] | 197 | mClockPlugin.setDarkAmount(mDarkAmount); |
Robert Snoeberger | 0397c84 | 2019-02-07 14:25:46 -0500 | [diff] [blame] | 198 | if (mColorPalette != null) { |
| 199 | mClockPlugin.setColorPalette(mSupportsDarkText, mColorPalette); |
| 200 | } |
Robert Snoeberger | 8bf1a3c | 2019-01-10 10:30:09 -0500 | [diff] [blame] | 201 | } |
| 202 | |
Kunhung Li | 29007e6 | 2018-07-30 19:30:25 +0800 | [diff] [blame] | 203 | /** |
Robert Snoeberger | 6a0140a | 2018-12-20 12:46:17 -0500 | [diff] [blame] | 204 | * Set container for big clock face appearing behind NSSL and KeyguardStatusView. |
| 205 | */ |
| 206 | public void setBigClockContainer(ViewGroup container) { |
| 207 | if (mClockPlugin != null && container != null) { |
| 208 | View bigClockView = mClockPlugin.getBigClockView(); |
| 209 | if (bigClockView != null) { |
| 210 | container.addView(bigClockView); |
Robert Snoeberger | a1df7fb | 2019-02-11 14:00:14 -0500 | [diff] [blame] | 211 | if (container.getVisibility() == View.GONE) { |
| 212 | container.setVisibility(View.VISIBLE); |
| 213 | } |
Robert Snoeberger | 6a0140a | 2018-12-20 12:46:17 -0500 | [diff] [blame] | 214 | } |
| 215 | } |
| 216 | mBigClockContainer = container; |
| 217 | } |
| 218 | |
| 219 | /** |
Kunhung Li | 29007e6 | 2018-07-30 19:30:25 +0800 | [diff] [blame] | 220 | * It will also update plugin setStyle if plugin is connected. |
| 221 | */ |
| 222 | public void setStyle(Style style) { |
| 223 | mClockView.getPaint().setStyle(style); |
| 224 | if (mClockPlugin != null) { |
| 225 | mClockPlugin.setStyle(style); |
| 226 | } |
| 227 | } |
| 228 | |
| 229 | /** |
| 230 | * It will also update plugin setTextColor if plugin is connected. |
| 231 | */ |
| 232 | public void setTextColor(int color) { |
| 233 | mClockView.setTextColor(color); |
| 234 | if (mClockPlugin != null) { |
| 235 | mClockPlugin.setTextColor(color); |
| 236 | } |
| 237 | } |
| 238 | |
| 239 | public void setShowCurrentUserTime(boolean showCurrentUserTime) { |
| 240 | mClockView.setShowCurrentUserTime(showCurrentUserTime); |
| 241 | } |
| 242 | |
Kunhung Li | 29007e6 | 2018-07-30 19:30:25 +0800 | [diff] [blame] | 243 | public void setTextSize(int unit, float size) { |
| 244 | mClockView.setTextSize(unit, size); |
| 245 | } |
| 246 | |
| 247 | public void setFormat12Hour(CharSequence format) { |
| 248 | mClockView.setFormat12Hour(format); |
| 249 | } |
| 250 | |
| 251 | public void setFormat24Hour(CharSequence format) { |
| 252 | mClockView.setFormat24Hour(format); |
| 253 | } |
| 254 | |
Robert Snoeberger | e32efd7 | 2018-11-12 08:38:34 -0500 | [diff] [blame] | 255 | /** |
| 256 | * Set the amount (ratio) that the device has transitioned to doze. |
| 257 | * @param darkAmount Amount of transition to doze: 1f for doze and 0f for awake. |
| 258 | */ |
| 259 | public void setDarkAmount(float darkAmount) { |
Robert Snoeberger | 58f2315 | 2019-01-10 15:51:32 -0500 | [diff] [blame] | 260 | mDarkAmount = darkAmount; |
Robert Snoeberger | e32efd7 | 2018-11-12 08:38:34 -0500 | [diff] [blame] | 261 | if (mClockPlugin != null) { |
| 262 | mClockPlugin.setDarkAmount(darkAmount); |
| 263 | } |
| 264 | } |
| 265 | |
Kunhung Li | 29007e6 | 2018-07-30 19:30:25 +0800 | [diff] [blame] | 266 | public Paint getPaint() { |
| 267 | return mClockView.getPaint(); |
| 268 | } |
| 269 | |
| 270 | public int getCurrentTextColor() { |
| 271 | return mClockView.getCurrentTextColor(); |
| 272 | } |
| 273 | |
| 274 | public float getTextSize() { |
| 275 | return mClockView.getTextSize(); |
| 276 | } |
| 277 | |
| 278 | public void refresh() { |
| 279 | mClockView.refresh(); |
| 280 | } |
| 281 | |
| 282 | /** |
Robert Snoeberger | ffbe315 | 2018-11-08 15:53:27 -0500 | [diff] [blame] | 283 | * Notifies that time tick alarm from doze service fired. |
| 284 | */ |
| 285 | public void dozeTimeTick() { |
| 286 | if (mClockPlugin != null) { |
Robert Snoeberger | 9ad03f4 | 2019-02-28 14:47:49 -0500 | [diff] [blame] | 287 | mClockPlugin.onTimeTick(); |
Robert Snoeberger | ffbe315 | 2018-11-08 15:53:27 -0500 | [diff] [blame] | 288 | } |
| 289 | } |
| 290 | |
| 291 | /** |
Robert Snoeberger | 9c1074f | 2018-12-07 17:35:21 -0500 | [diff] [blame] | 292 | * Notifies that the time zone has changed. |
| 293 | */ |
| 294 | public void onTimeZoneChanged(TimeZone timeZone) { |
| 295 | if (mClockPlugin != null) { |
| 296 | mClockPlugin.onTimeZoneChanged(timeZone); |
| 297 | } |
| 298 | } |
| 299 | |
Robert Snoeberger | 0397c84 | 2019-02-07 14:25:46 -0500 | [diff] [blame] | 300 | private void updateColors(SysuiColorExtractor colorExtractor) { |
| 301 | ColorExtractor.GradientColors colors = colorExtractor.getColors(WallpaperManager.FLAG_LOCK, |
| 302 | true); |
| 303 | mSupportsDarkText = colors.supportsDarkText(); |
| 304 | mColorPalette = colors.getColorPalette(); |
| 305 | if (mClockPlugin != null) { |
| 306 | mClockPlugin.setColorPalette(mSupportsDarkText, mColorPalette); |
| 307 | } |
| 308 | } |
| 309 | |
Lucas Dupin | e570af6 | 2019-02-10 14:52:30 -0800 | [diff] [blame] | 310 | /** |
| 311 | * Sets if the keyguard slice is showing a center-aligned header. We need a smaller clock |
| 312 | * in these cases. |
| 313 | */ |
| 314 | public void setKeyguardShowingHeader(boolean hasHeader) { |
| 315 | if (mShowingHeader == hasHeader || hasCustomClock()) { |
| 316 | return; |
| 317 | } |
| 318 | mShowingHeader = hasHeader; |
| 319 | |
| 320 | TransitionManager.beginDelayedTransition((ViewGroup) mClockView.getParent(), mTransition); |
| 321 | int fontSize = mContext.getResources().getDimensionPixelSize(mShowingHeader |
| 322 | ? R.dimen.widget_small_font_size : R.dimen.widget_big_font_size); |
| 323 | int paddingBottom = mContext.getResources().getDimensionPixelSize(mShowingHeader |
| 324 | ? R.dimen.widget_vertical_padding_clock : R.dimen.header_subtitle_padding); |
| 325 | mClockView.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize); |
| 326 | mClockView.setPadding(mClockView.getPaddingLeft(), mClockView.getPaddingTop(), |
| 327 | mClockView.getPaddingRight(), paddingBottom); |
| 328 | } |
| 329 | |
Kunhung Li | 29007e6 | 2018-07-30 19:30:25 +0800 | [diff] [blame] | 330 | @VisibleForTesting (otherwise = VisibleForTesting.NONE) |
Robert Snoeberger | 15b4af1 | 2019-01-18 15:37:27 -0500 | [diff] [blame] | 331 | ClockManager.ClockChangedListener getClockChangedListener() { |
| 332 | return mClockChangedListener; |
Kunhung Li | 29007e6 | 2018-07-30 19:30:25 +0800 | [diff] [blame] | 333 | } |
Robert Snoeberger | 6085408 | 2019-01-04 13:13:17 -0500 | [diff] [blame] | 334 | |
| 335 | @VisibleForTesting (otherwise = VisibleForTesting.NONE) |
| 336 | StatusBarStateController.StateListener getStateListener() { |
| 337 | return mStateListener; |
| 338 | } |
Lucas Dupin | e570af6 | 2019-02-10 14:52:30 -0800 | [diff] [blame] | 339 | |
Lucas Dupin | 4349952 | 2019-03-04 16:45:58 -0800 | [diff] [blame] | 340 | public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { |
| 341 | pw.println("KeyguardClockSwitch:"); |
| 342 | pw.println(" mClockPlugin: " + mClockPlugin); |
| 343 | pw.println(" mClockView: " + mClockView); |
| 344 | pw.println(" mSmallClockFrame: " + mSmallClockFrame); |
| 345 | pw.println(" mBigClockContainer: " + mBigClockContainer); |
| 346 | pw.println(" mKeyguardStatusArea: " + mKeyguardStatusArea); |
| 347 | pw.println(" mDarkAmount: " + mDarkAmount); |
| 348 | pw.println(" mShowingHeader: " + mShowingHeader); |
| 349 | pw.println(" mSupportsDarkText: " + mSupportsDarkText); |
| 350 | pw.println(" mColorPalette: " + Arrays.toString(mColorPalette)); |
| 351 | } |
| 352 | |
Lucas Dupin | e570af6 | 2019-02-10 14:52:30 -0800 | [diff] [blame] | 353 | /** |
| 354 | * Special layout transition that scales the clock view as its bounds change, to make it look |
| 355 | * like the text is shrinking. |
| 356 | */ |
| 357 | private class ClockBoundsTransition extends ChangeBounds { |
| 358 | |
| 359 | ClockBoundsTransition() { |
| 360 | setDuration(KeyguardSliceView.DEFAULT_ANIM_DURATION / 2); |
| 361 | setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN); |
| 362 | } |
| 363 | |
| 364 | @Override |
| 365 | public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues, |
| 366 | TransitionValues endValues) { |
| 367 | Animator animator = super.createAnimator(sceneRoot, startValues, endValues); |
| 368 | if (animator == null || startValues.view != mClockView) { |
| 369 | return animator; |
| 370 | } |
| 371 | |
| 372 | ValueAnimator boundsAnimator = null; |
| 373 | if (animator instanceof AnimatorSet) { |
| 374 | Animator first = ((AnimatorSet) animator).getChildAnimations().get(0); |
| 375 | if (first instanceof ValueAnimator) { |
| 376 | boundsAnimator = (ValueAnimator) first; |
| 377 | } |
| 378 | } else if (animator instanceof ValueAnimator) { |
| 379 | boundsAnimator = (ValueAnimator) animator; |
| 380 | } |
| 381 | |
| 382 | if (boundsAnimator != null) { |
| 383 | float bigFontSize = mContext.getResources() |
| 384 | .getDimensionPixelSize(R.dimen.widget_big_font_size); |
| 385 | float smallFontSize = mContext.getResources() |
| 386 | .getDimensionPixelSize(R.dimen.widget_small_font_size); |
| 387 | float startScale = mShowingHeader |
| 388 | ? bigFontSize / smallFontSize : smallFontSize / bigFontSize; |
| 389 | boundsAnimator.addUpdateListener(animation -> { |
| 390 | float scale = MathUtils.lerp(startScale, 1f /* stop */, |
| 391 | animation.getAnimatedFraction()); |
Lucas Dupin | 4349952 | 2019-03-04 16:45:58 -0800 | [diff] [blame] | 392 | mClockView.setPivotX(mClockView.getWidth() / 2f); |
Lucas Dupin | e570af6 | 2019-02-10 14:52:30 -0800 | [diff] [blame] | 393 | mClockView.setPivotY(0); |
| 394 | mClockView.setScaleX(scale); |
| 395 | mClockView.setScaleY(scale); |
| 396 | }); |
Lucas Dupin | 4349952 | 2019-03-04 16:45:58 -0800 | [diff] [blame] | 397 | boundsAnimator.addListener(new AnimatorListenerAdapter() { |
| 398 | @Override |
| 399 | public void onAnimationEnd(Animator animator) { |
| 400 | mClockView.setScaleX(1f); |
| 401 | mClockView.setScaleY(1f); |
| 402 | } |
| 403 | |
| 404 | @Override |
| 405 | public void onAnimationCancel(Animator animator) { |
| 406 | onAnimationEnd(animator); |
| 407 | } |
| 408 | }); |
Lucas Dupin | e570af6 | 2019-02-10 14:52:30 -0800 | [diff] [blame] | 409 | } |
| 410 | |
| 411 | return animator; |
| 412 | } |
| 413 | } |
Kunhung Li | 29007e6 | 2018-07-30 19:30:25 +0800 | [diff] [blame] | 414 | } |