blob: a474255e16f02e95d1a65c9c450fd9b468d53349 [file] [log] [blame]
/*
* Copyright (C) 2020 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.emergency.widgets.countdown;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import androidx.annotation.GuardedBy;
import com.android.emergency.R;
import java.time.Duration;
/**
* The renderer which renders the text view to show how many seconds left to count down.
*/
public class CountDownRenderer {
@GuardedBy("this")
private final Paint mTimerTextPaint;
@GuardedBy("this")
private final Paint mUnitTextPaint;
@GuardedBy("this")
private RectF mBounds = null;
@GuardedBy("this")
private boolean mIsRevealed = false;
@GuardedBy("this")
private Duration mCountDownLeft;
private Context mContext;
private String mSecondUnitText;
private float mUnitTextLeftMargin;
CountDownRenderer(Context context) {
mContext = context;
mTimerTextPaint = new Paint();
mTimerTextPaint.setTextAlign(Paint.Align.CENTER);
mTimerTextPaint.setTypeface(Typeface.SANS_SERIF);
mTimerTextPaint.setColor(Color.WHITE);
mTimerTextPaint.setAntiAlias(true);
mUnitTextPaint = new Paint();
mUnitTextPaint.setTypeface(Typeface.SANS_SERIF);
mUnitTextPaint.setTextAlign(Paint.Align.CENTER);
mUnitTextPaint.setColor(Color.WHITE);
mUnitTextPaint.setAntiAlias(true);
mSecondUnitText = context.getString(R.string.count_down_unit);
}
/** Shows the count down rendering. */
synchronized void show() {
mIsRevealed = true;
}
/** Returns true if count down text should be displayed, false otherwise. */
synchronized boolean isRevealed() {
return mIsRevealed;
}
/**
* Draws the count down text.
*
* <p>Called from {@link LoopingAnimationThread}.
*/
synchronized void draw(Canvas canvas) {
if (!mIsRevealed || mBounds == null || mCountDownLeft == null) {
return;
}
String timerText = Long.toString(mCountDownLeft.getSeconds());
RectF timerTextBounds = measureText(timerText, mTimerTextPaint);
RectF unitTextBounds = measureText(mSecondUnitText, mUnitTextPaint);
// Shift timer text and unit text to share baseline.
unitTextBounds.offset(0, timerTextBounds.height() - unitTextBounds.height());
// Calculate final text bound that all text will be drawn inside of.
RectF finalTextBounds =
new RectF(
0,
0,
timerTextBounds.width() + unitTextBounds.width() + mUnitTextLeftMargin,
timerTextBounds.height());
// Offset unit text bounds to right of timer text bounds.
unitTextBounds.offset(timerTextBounds.width() + mUnitTextLeftMargin, 0);
// Center final text bounds in provided bounds and place timer text and unit text inside.
finalTextBounds.offset(
mBounds.left + (mBounds.width() - finalTextBounds.width()) * 0.5f,
mBounds.bottom - (mBounds.height() - finalTextBounds.height()));
timerTextBounds.offset(finalTextBounds.left, finalTextBounds.top);
unitTextBounds.offset(finalTextBounds.left, finalTextBounds.top);
// Draw text.
canvas.drawText(
timerText, timerTextBounds.centerX(), timerTextBounds.bottom, mTimerTextPaint);
canvas.drawText(
mSecondUnitText, unitTextBounds.centerX(), unitTextBounds.bottom, mUnitTextPaint);
}
/**
* Sets the bounds text should be drawn in.
*
* <p>Called from ui thread.
*/
synchronized void updateBounds(RectF loopBounds, float totalDiameter) {
this.mBounds =
new RectF(loopBounds.left, loopBounds.top, loopBounds.right, loopBounds.bottom);
float textSizeToBoundsRatio =
mContext.getResources().getFloat(
R.dimen.count_down_view_text_size_to_diameter_ratio);
float unitTextToTimerTextSizeRatio =
mContext.getResources().getFloat(
R.dimen.count_down_view_unit_text_to_time_text_size_ratio);
float unitTextLeftMarginToBoundsRatio =
mContext.getResources().getFloat(
R.dimen.count_down_view_unit_text_left_margin_to_diameter_ratio);
mTimerTextPaint.setTextSize(textSizeToBoundsRatio * totalDiameter);
mUnitTextPaint.setTextSize(
textSizeToBoundsRatio * unitTextToTimerTextSizeRatio * totalDiameter);
mUnitTextLeftMargin = unitTextLeftMarginToBoundsRatio * totalDiameter;
}
private static RectF measureText(String text, Paint textPaint) {
Rect textBounds = new Rect();
textPaint.getTextBounds(text, 0, text.length(), textBounds);
RectF textBoundsF = new RectF(textBounds);
// Readjust text to be aligned to origin as their top left.
textBoundsF.offset(-textBounds.left, -textBounds.top);
return textBoundsF;
}
synchronized void setCountDownLeft(Duration timeLeft) {
mCountDownLeft = timeLeft;
}
}