Robert Snoeberger | ce8c204 | 2019-01-17 10:36:02 -0500 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2019 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 | package com.android.keyguard.clock; |
| 17 | |
| 18 | import android.content.Context; |
| 19 | import android.content.res.Resources; |
Robert Snoeberger | 326d0c1 | 2019-02-05 11:09:48 -0500 | [diff] [blame] | 20 | import android.text.Annotation; |
| 21 | import android.text.Spannable; |
| 22 | import android.text.SpannableString; |
| 23 | import android.text.SpannedString; |
| 24 | import android.text.TextUtils; |
Robert Snoeberger | ce8c204 | 2019-01-17 10:36:02 -0500 | [diff] [blame] | 25 | import android.text.format.DateFormat; |
Robert Snoeberger | 326d0c1 | 2019-02-05 11:09:48 -0500 | [diff] [blame] | 26 | import android.text.style.ForegroundColorSpan; |
Robert Snoeberger | ce8c204 | 2019-01-17 10:36:02 -0500 | [diff] [blame] | 27 | import android.util.AttributeSet; |
Robert Snoeberger | ce8c204 | 2019-01-17 10:36:02 -0500 | [diff] [blame] | 28 | import android.widget.TextView; |
| 29 | |
| 30 | import com.android.keyguard.R; |
| 31 | |
| 32 | import java.text.SimpleDateFormat; |
| 33 | import java.util.Calendar; |
| 34 | import java.util.TimeZone; |
| 35 | |
| 36 | /** |
| 37 | * Clock that presents the time in words. |
| 38 | */ |
Robert Snoeberger | 326d0c1 | 2019-02-05 11:09:48 -0500 | [diff] [blame] | 39 | public class TypographicClock extends TextView { |
Robert Snoeberger | ce8c204 | 2019-01-17 10:36:02 -0500 | [diff] [blame] | 40 | |
Robert Snoeberger | 326d0c1 | 2019-02-05 11:09:48 -0500 | [diff] [blame] | 41 | private static final String ANNOTATION_COLOR = "color"; |
| 42 | |
| 43 | private final Resources mResources; |
Robert Snoeberger | ce8c204 | 2019-01-17 10:36:02 -0500 | [diff] [blame] | 44 | private final String[] mHours; |
| 45 | private final String[] mMinutes; |
Robert Snoeberger | 0397c84 | 2019-02-07 14:25:46 -0500 | [diff] [blame] | 46 | private int mAccentColor; |
Robert Snoeberger | 71e5079 | 2019-02-15 15:48:01 -0500 | [diff] [blame] | 47 | private final Calendar mTime = Calendar.getInstance(TimeZone.getDefault()); |
Robert Snoeberger | ce8c204 | 2019-01-17 10:36:02 -0500 | [diff] [blame] | 48 | private String mDescFormat; |
| 49 | private TimeZone mTimeZone; |
| 50 | |
| 51 | public TypographicClock(Context context) { |
| 52 | this(context, null); |
| 53 | } |
| 54 | |
| 55 | public TypographicClock(Context context, AttributeSet attrs) { |
| 56 | this(context, attrs, 0); |
| 57 | } |
| 58 | |
| 59 | public TypographicClock(Context context, AttributeSet attrs, int defStyleAttr) { |
| 60 | super(context, attrs, defStyleAttr); |
Robert Snoeberger | ce8c204 | 2019-01-17 10:36:02 -0500 | [diff] [blame] | 61 | mDescFormat = ((SimpleDateFormat) DateFormat.getTimeFormat(context)).toLocalizedPattern(); |
Robert Snoeberger | 326d0c1 | 2019-02-05 11:09:48 -0500 | [diff] [blame] | 62 | mResources = context.getResources(); |
| 63 | mHours = mResources.getStringArray(R.array.type_clock_hours); |
| 64 | mMinutes = mResources.getStringArray(R.array.type_clock_minutes); |
| 65 | mAccentColor = mResources.getColor(R.color.typeClockAccentColor, null); |
Robert Snoeberger | ce8c204 | 2019-01-17 10:36:02 -0500 | [diff] [blame] | 66 | } |
| 67 | |
| 68 | /** |
| 69 | * Call when the time changes to update the text of the time. |
| 70 | */ |
| 71 | public void onTimeChanged() { |
| 72 | mTime.setTimeInMillis(System.currentTimeMillis()); |
| 73 | setContentDescription(DateFormat.format(mDescFormat, mTime)); |
Robert Snoeberger | 326d0c1 | 2019-02-05 11:09:48 -0500 | [diff] [blame] | 74 | final int hour = mTime.get(Calendar.HOUR) % 12; |
| 75 | final int minute = mTime.get(Calendar.MINUTE) % 60; |
| 76 | |
| 77 | // Get the quantity based on the hour for languages like Portuguese and Czech. |
| 78 | SpannedString typeTemplate = (SpannedString) mResources.getQuantityText( |
| 79 | R.plurals.type_clock_header, hour); |
| 80 | |
| 81 | // Find the "color" annotation and set the foreground color to the accent color. |
| 82 | Annotation[] annotations = typeTemplate.getSpans(0, typeTemplate.length(), |
| 83 | Annotation.class); |
| 84 | SpannableString spanType = new SpannableString(typeTemplate); |
| 85 | for (int i = 0; i < annotations.length; i++) { |
| 86 | Annotation annotation = annotations[i]; |
| 87 | String key = annotation.getValue(); |
| 88 | if (ANNOTATION_COLOR.equals(key)) { |
| 89 | spanType.setSpan(new ForegroundColorSpan(mAccentColor), |
| 90 | spanType.getSpanStart(annotation), spanType.getSpanEnd(annotation), |
| 91 | Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); |
| 92 | } |
| 93 | } |
| 94 | |
| 95 | setText(TextUtils.expandTemplate(spanType, mHours[hour], mMinutes[minute])); |
Robert Snoeberger | ce8c204 | 2019-01-17 10:36:02 -0500 | [diff] [blame] | 96 | } |
| 97 | |
| 98 | /** |
| 99 | * Call when the time zone has changed to update clock time. |
| 100 | * |
| 101 | * @param timeZone The updated time zone that will be used. |
| 102 | */ |
| 103 | public void onTimeZoneChanged(TimeZone timeZone) { |
| 104 | mTimeZone = timeZone; |
| 105 | mTime.setTimeZone(timeZone); |
| 106 | } |
| 107 | |
Robert Snoeberger | 0397c84 | 2019-02-07 14:25:46 -0500 | [diff] [blame] | 108 | /** |
| 109 | * Sets the accent color used on the clock face. |
| 110 | */ |
| 111 | public void setClockColor(int color) { |
| 112 | mAccentColor = color; |
Robert Snoeberger | 71e5079 | 2019-02-15 15:48:01 -0500 | [diff] [blame] | 113 | onTimeChanged(); |
Robert Snoeberger | 0397c84 | 2019-02-07 14:25:46 -0500 | [diff] [blame] | 114 | } |
| 115 | |
Robert Snoeberger | ce8c204 | 2019-01-17 10:36:02 -0500 | [diff] [blame] | 116 | @Override |
| 117 | protected void onAttachedToWindow() { |
| 118 | super.onAttachedToWindow(); |
Robert Snoeberger | 71e5079 | 2019-02-15 15:48:01 -0500 | [diff] [blame] | 119 | mTime.setTimeZone(mTimeZone != null ? mTimeZone : TimeZone.getDefault()); |
Robert Snoeberger | ce8c204 | 2019-01-17 10:36:02 -0500 | [diff] [blame] | 120 | onTimeChanged(); |
| 121 | } |
Robert Snoeberger | 1f19d2c | 2019-03-06 10:03:05 -0500 | [diff] [blame] | 122 | |
| 123 | /** |
| 124 | * Overriding hasOverlappingRendering as false to improve performance of crossfading. |
| 125 | */ |
| 126 | @Override |
| 127 | public boolean hasOverlappingRendering() { |
| 128 | return false; |
| 129 | } |
Robert Snoeberger | ce8c204 | 2019-01-17 10:36:02 -0500 | [diff] [blame] | 130 | } |