From f3354b658fbcc145ef66475404b298ec4c3be5e0 Mon Sep 17 00:00:00 2001 From: Danny Lin Date: Tue, 3 Nov 2020 13:17:29 -0800 Subject: [crdroid][11.0] SystemUI: Restore typographic clock face This reverts commits 583067c4e4799b0a633d8e861698c8fc2a5c7a6f and 37fe8022174fc809ef4622f7d6c69f9bdff06913. This clock face still works fine and we can expose it in ThemePicker. Changes made for forward-porting to Android 11: - Added SmallClockPosition to manage preferred Y position - Adjusted resources class imports for res-keyguard merge - Updated arguments to ColorExtractor#getColors Change-Id: If75c593e3403962e1a7ffa6fae0734f785d79589 --- .../drawable-xxxhdpi/type_thumbnail.png | Bin 0 -> 6315 bytes .../res-keyguard/layout/type_aod_clock.xml | 23 +++ .../res-keyguard/layout/typographic_clock.xml | 26 +++ packages/SystemUI/res-keyguard/values/strings.xml | 102 ++++++++++ .../com/android/keyguard/clock/ClockLayout.java | 8 + .../com/android/keyguard/clock/ClockManager.java | 1 + .../keyguard/clock/TypeClockController.java | 211 +++++++++++++++++++++ .../android/keyguard/clock/TypographicClock.java | 130 +++++++++++++ 8 files changed, 501 insertions(+) create mode 100644 packages/SystemUI/res-keyguard/drawable-xxxhdpi/type_thumbnail.png create mode 100644 packages/SystemUI/res-keyguard/layout/type_aod_clock.xml create mode 100644 packages/SystemUI/res-keyguard/layout/typographic_clock.xml create mode 100644 packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java create mode 100644 packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java diff --git a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/type_thumbnail.png b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/type_thumbnail.png new file mode 100644 index 000000000000..2bfd655e37de Binary files /dev/null and b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/type_thumbnail.png differ diff --git a/packages/SystemUI/res-keyguard/layout/type_aod_clock.xml b/packages/SystemUI/res-keyguard/layout/type_aod_clock.xml new file mode 100644 index 000000000000..28ff5a253317 --- /dev/null +++ b/packages/SystemUI/res-keyguard/layout/type_aod_clock.xml @@ -0,0 +1,23 @@ + + + + + diff --git a/packages/SystemUI/res-keyguard/layout/typographic_clock.xml b/packages/SystemUI/res-keyguard/layout/typographic_clock.xml new file mode 100644 index 000000000000..73bb4b9a0fc9 --- /dev/null +++ b/packages/SystemUI/res-keyguard/layout/typographic_clock.xml @@ -0,0 +1,26 @@ + + + diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml index 4b6621379b44..91df39056849 100644 --- a/packages/SystemUI/res-keyguard/values/strings.xml +++ b/packages/SystemUI/res-keyguard/values/strings.xml @@ -318,11 +318,113 @@ number">%d remaining attempt before SIM becomes permanently unusable. number">%d remaining attempts before SIM becomes permanently unusable. Contact carrier for details. + + + It\u2019s\n^1\n^2 + It\u2019s\n^1\n^2 + It\u2019s\n^1\n^2 + + + + + Twelve + One + Two + Three + Four + Five + Six + Seven + Eight + Nine + Ten + Eleven + + + + + O\u2019Clock + Oh One + Oh Two + Oh Three + Oh Four + Oh Five + Oh Six + Oh Seven + Oh Eight + Oh Nine + Ten + Eleven + Twelve + Thirteen + Fourteen + Fifteen + Sixteen + Seventeen + Eighteen + Nineteen + Twenty + Twenty\nOne + Twenty\nTwo + Twenty\nThree + Twenty\nFour + Twenty\nFive + Twenty\nSix + Twenty\nSeven + Twenty\nEight + Twenty\nNine + Thirty + Thirty\nOne + Thirty\nTwo + Thirty\nThree + Thirty\nFour + Thirty\nFive + Thirty\nSix + Thirty\nSeven + Thirty\nEight + Thirty\nNine + Forty + Forty\nOne + Forty\nTwo + Forty\nThree + Forty\nFour + Forty\nFive + Forty\nSix + Forty\nSeven + Forty\nEight + Forty\nNine + Fifty + Fifty\nOne + Fifty\nTwo + Fifty\nThree + Fifty\nFour + Fifty\nFive + Fifty\nSix + Fifty\nSeven + Fifty\nEight + Fifty\nNine + + Default Bubble Analog + + Type diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java index d44d89e63e8f..ccb495fcec28 100644 --- a/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java +++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java @@ -37,6 +37,7 @@ public class ClockLayout extends FrameLayout { * Clock face views. */ private View mAnalogClock; + private View mTypeClock; /** * Pixel shifting amplitudes used to prevent screen burn-in. @@ -62,6 +63,7 @@ public class ClockLayout extends FrameLayout { protected void onFinishInflate() { super.onFinishInflate(); mAnalogClock = findViewById(R.id.analog_clock); + mTypeClock = findViewById(R.id.type_clock); // Get pixel shifting X, Y amplitudes from resources. Resources resources = getResources(); @@ -105,5 +107,11 @@ public class ClockLayout extends FrameLayout { mAnalogClock.setY(Math.max(0f, 0.5f * (getHeight() - mAnalogClock.getHeight())) + ANALOG_CLOCK_SHIFT_FACTOR * offsetY); } + + // Put the typographic clock part way down the screen. + if (mTypeClock != null) { + mTypeClock.setX(offsetX); + mTypeClock.setY(0.2f * getHeight() + offsetY); + } } } diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java index 2200b22b8b27..fd5c99e75a1f 100644 --- a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java +++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java @@ -150,6 +150,7 @@ public final class ClockManager { LayoutInflater layoutInflater = injectionInflater.injectable(LayoutInflater.from(context)); addBuiltinClock(() -> new DefaultClockController(res, layoutInflater, colorExtractor)); + addBuiltinClock(() -> new TypeClockController(res, layoutInflater, colorExtractor)); // Store the size of the display for generation of clock preview. DisplayMetrics dm = res.getDisplayMetrics(); diff --git a/packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java new file mode 100644 index 000000000000..890ba1da0911 --- /dev/null +++ b/packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2019 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.keyguard.clock; + +import android.app.WallpaperManager; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Color; +import android.graphics.Paint.Style; +import android.view.LayoutInflater; +import android.view.View; + +import com.android.internal.colorextraction.ColorExtractor; +import com.android.systemui.R; +import com.android.systemui.colorextraction.SysuiColorExtractor; +import com.android.systemui.plugins.ClockPlugin; + +import java.util.TimeZone; + +/** + * Plugin for a custom Typographic clock face that displays the time in words. + */ +public class TypeClockController implements ClockPlugin { + + /** + * Resources used to get title and thumbnail. + */ + private final Resources mResources; + + /** + * LayoutInflater used to inflate custom clock views. + */ + private final LayoutInflater mLayoutInflater; + + /** + * Extracts accent color from wallpaper. + */ + private final SysuiColorExtractor mColorExtractor; + + /** + * Computes preferred position of clock. + */ + private final SmallClockPosition mClockPosition; + + /** + * Renders preview from clock view. + */ + private final ViewPreviewer mRenderer = new ViewPreviewer(); + + /** + * Custom clock shown on AOD screen and behind stack scroller on lock. + */ + private View mView; + private TypographicClock mTypeClock; + + /** + * Small clock shown on lock screen above stack scroller. + */ + private TypographicClock mLockClock; + + /** + * Controller for transition into dark state. + */ + private CrossFadeDarkController mDarkController; + + /** + * Create a TypeClockController instance. + * + * @param res Resources contains title and thumbnail. + * @param inflater Inflater used to inflate custom clock views. + * @param colorExtractor Extracts accent color from wallpaper. + */ + TypeClockController(Resources res, LayoutInflater inflater, + SysuiColorExtractor colorExtractor) { + mResources = res; + mLayoutInflater = inflater; + mColorExtractor = colorExtractor; + mClockPosition = new SmallClockPosition(res); + } + + private void createViews() { + mView = mLayoutInflater.inflate(R.layout.type_aod_clock, null); + mTypeClock = mView.findViewById(R.id.type_clock); + + // For now, this view is used to hide the default digital clock. + // Need better transition to lock screen. + mLockClock = (TypographicClock) mLayoutInflater.inflate(R.layout.typographic_clock, null); + mLockClock.setVisibility(View.GONE); + + mDarkController = new CrossFadeDarkController(mView, mLockClock); + } + + @Override + public void onDestroyView() { + mView = null; + mTypeClock = null; + mLockClock = null; + mDarkController = null; + } + + @Override + public String getName() { + return "type"; + } + + @Override + public String getTitle() { + return mResources.getString(R.string.clock_title_type); + } + + @Override + public Bitmap getThumbnail() { + return BitmapFactory.decodeResource(mResources, R.drawable.type_thumbnail); + } + + @Override + public Bitmap getPreview(int width, int height) { + + // Use the big clock view for the preview + View view = getBigClockView(); + + // Initialize state of plugin before generating preview. + setDarkAmount(1f); + setTextColor(Color.WHITE); + ColorExtractor.GradientColors colors = mColorExtractor.getColors( + WallpaperManager.FLAG_LOCK); + setColorPalette(colors.supportsDarkText(), colors.getColorPalette()); + onTimeTick(); + + return mRenderer.createPreview(view, width, height); + } + + @Override + public View getView() { + if (mLockClock == null) { + createViews(); + } + return mLockClock; + } + + @Override + public View getBigClockView() { + if (mView == null) { + createViews(); + } + return mView; + } + + @Override + public int getPreferredY(int totalHeight) { + return mClockPosition.getPreferredY(); + } + + @Override + public void setStyle(Style style) {} + + @Override + public void setTextColor(int color) { + mTypeClock.setTextColor(color); + mLockClock.setTextColor(color); + } + + @Override + public void setColorPalette(boolean supportsDarkText, int[] colorPalette) { + if (colorPalette == null || colorPalette.length == 0) { + return; + } + final int color = colorPalette[Math.max(0, colorPalette.length - 5)]; + mTypeClock.setClockColor(color); + mLockClock.setClockColor(color); + } + + @Override + public void onTimeTick() { + mTypeClock.onTimeChanged(); + mLockClock.onTimeChanged(); + } + + @Override + public void setDarkAmount(float darkAmount) { + if (mDarkController != null) { + mDarkController.setDarkAmount(darkAmount); + } + mClockPosition.setDarkAmount(darkAmount); + } + + @Override + public void onTimeZoneChanged(TimeZone timeZone) { + mTypeClock.onTimeZoneChanged(timeZone); + mLockClock.onTimeZoneChanged(timeZone); + } + + @Override + public boolean shouldShowStatusArea() { + return false; + } +} diff --git a/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java b/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java new file mode 100644 index 000000000000..c84c598498d0 --- /dev/null +++ b/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2019 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.keyguard.clock; + +import android.content.Context; +import android.content.res.Resources; +import android.text.Annotation; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.SpannedString; +import android.text.TextUtils; +import android.text.format.DateFormat; +import android.text.style.ForegroundColorSpan; +import android.util.AttributeSet; +import android.widget.TextView; + +import com.android.systemui.R; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.TimeZone; + +/** + * Clock that presents the time in words. + */ +public class TypographicClock extends TextView { + + private static final String ANNOTATION_COLOR = "color"; + + private final Resources mResources; + private final String[] mHours; + private final String[] mMinutes; + private int mAccentColor; + private final Calendar mTime = Calendar.getInstance(TimeZone.getDefault()); + private String mDescFormat; + private TimeZone mTimeZone; + + public TypographicClock(Context context) { + this(context, null); + } + + public TypographicClock(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public TypographicClock(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + mDescFormat = ((SimpleDateFormat) DateFormat.getTimeFormat(context)).toLocalizedPattern(); + mResources = context.getResources(); + mHours = mResources.getStringArray(R.array.type_clock_hours); + mMinutes = mResources.getStringArray(R.array.type_clock_minutes); + mAccentColor = mResources.getColor(R.color.typeClockAccentColor, null); + } + + /** + * Call when the time changes to update the text of the time. + */ + public void onTimeChanged() { + mTime.setTimeInMillis(System.currentTimeMillis()); + setContentDescription(DateFormat.format(mDescFormat, mTime)); + final int hour = mTime.get(Calendar.HOUR) % 12; + final int minute = mTime.get(Calendar.MINUTE) % 60; + + // Get the quantity based on the hour for languages like Portuguese and Czech. + SpannedString typeTemplate = (SpannedString) mResources.getQuantityText( + R.plurals.type_clock_header, hour); + + // Find the "color" annotation and set the foreground color to the accent color. + Annotation[] annotations = typeTemplate.getSpans(0, typeTemplate.length(), + Annotation.class); + SpannableString spanType = new SpannableString(typeTemplate); + for (int i = 0; i < annotations.length; i++) { + Annotation annotation = annotations[i]; + String key = annotation.getValue(); + if (ANNOTATION_COLOR.equals(key)) { + spanType.setSpan(new ForegroundColorSpan(mAccentColor), + spanType.getSpanStart(annotation), spanType.getSpanEnd(annotation), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + } + } + + setText(TextUtils.expandTemplate(spanType, mHours[hour], mMinutes[minute])); + } + + /** + * Call when the time zone has changed to update clock time. + * + * @param timeZone The updated time zone that will be used. + */ + public void onTimeZoneChanged(TimeZone timeZone) { + mTimeZone = timeZone; + mTime.setTimeZone(timeZone); + } + + /** + * Sets the accent color used on the clock face. + */ + public void setClockColor(int color) { + mAccentColor = color; + onTimeChanged(); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + mTime.setTimeZone(mTimeZone != null ? mTimeZone : TimeZone.getDefault()); + onTimeChanged(); + } + + /** + * Overriding hasOverlappingRendering as false to improve performance of crossfading. + */ + @Override + public boolean hasOverlappingRendering() { + return false; + } +} -- cgit v1.2.3