/* * Copyright (C) 2016 Google Inc. All Rights Reserved. * * 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.google.android.apps.santatracker.launch; import android.content.Context; import android.os.Build; import android.os.CountDownTimer; import android.view.View; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.widget.TextView; import com.google.android.apps.santatracker.R; import java.lang.ref.WeakReference; import java.text.DecimalFormat; import java.util.GregorianCalendar; public class LaunchCountdown { /** * Listener for LaunchCountdown and convenience method to draw CountDown UI itself. */ public interface LaunchCountdownContext{ void onCountdownFinished(); View getCountdownView(); Context getActivityContext(); Context getApplicationContext(); } private CountDownTimer mTimer; private TextView mTvDays; private TextView mTvDays2; private TextView mTvHours; private TextView mTvHours2; private TextView mTvMinutes; private TextView mTvMinutes2; private TextView mTvSeconds; private TextView mTvSeconds2; boolean mDaysPrimary = true; Animation mDaysIn, mDaysOut; boolean mHoursPrimary = true; Animation mHoursIn, mHoursOut; boolean mMinutesPrimary = true; Animation mMinutesIn, mMinutesOut; boolean mSecondsPrimary = true; Animation mSecondsIn, mSecondsOut; long mCountdownTime = -1; private WeakReference<LaunchCountdownContext> mLaunchContextRef; public LaunchCountdown(LaunchCountdownContext context) { mLaunchContextRef = new WeakReference<>(context); final View countdownView = context.getCountdownView(); mTvDays = (TextView) countdownView.findViewById(R.id.countdown_days_1); mTvDays2 = (TextView) countdownView.findViewById(R.id.countdown_days_2); mTvHours = (TextView) countdownView.findViewById(R.id.countdown_hours_1); mTvHours2 = (TextView) countdownView.findViewById(R.id.countdown_hours_2); mTvMinutes = (TextView) countdownView.findViewById(R.id.countdown_minutes_1); mTvMinutes2 = (TextView) countdownView.findViewById(R.id.countdown_minutes_2); mTvSeconds = (TextView) countdownView.findViewById(R.id.countdown_seconds_1); mTvSeconds2 = (TextView) countdownView.findViewById(R.id.countdown_seconds_2); } /** * Starts the countdown timer. */ public void startTimer(long timer) { final LaunchCountdownContext launchContext = mLaunchContextRef.get(); if (timer < 0 || Math.abs(timer - mCountdownTime) < 1000 || launchContext == null) { return; } mCountdownTime = timer; // cancel timer if already running cancel(); final Context context = launchContext.getApplicationContext(); mDaysIn = AnimationUtils.loadAnimation(context, R.anim.slide_in_bottom); mDaysOut = AnimationUtils.loadAnimation(context, R.anim.slide_out_top); mHoursIn = AnimationUtils.loadAnimation(context, R.anim.slide_in_bottom); mHoursOut = AnimationUtils.loadAnimation(context, R.anim.slide_out_top); mMinutesIn = AnimationUtils.loadAnimation(context, R.anim.slide_in_bottom); mMinutesOut = AnimationUtils.loadAnimation(context, R.anim.slide_out_top); mSecondsIn = AnimationUtils.loadAnimation(context, R.anim.slide_in_bottom); mSecondsOut = AnimationUtils.loadAnimation(context, R.anim.slide_out_top); mTimer = new CountDownTimer(mCountdownTime, 1000) { private DecimalFormat mDF = new DecimalFormat("00"); private boolean initialRound = true; @Override public void onTick(long millisUntilFinished) { int iDays = (int) Math.floor(millisUntilFinished / (24 * 60 * 60 * 1000)); int iHours = (int) Math.floor(millisUntilFinished / (60 * 60 * 1000) % 24); int iMinutes = (int) Math.floor(millisUntilFinished / (60 * 1000) % 60); int iSeconds = (int) Math.floor(millisUntilFinished / (1000) % 60); GregorianCalendar calendar = new GregorianCalendar(); calendar.setTimeInMillis(millisUntilFinished); String days = mDF.format(iDays); if (animateValue(days, mTvDays, mTvDays2, mDaysIn, mDaysOut, mDaysPrimary, initialRound)) { mDaysPrimary = !mDaysPrimary; } String hours = mDF.format(iHours); if (animateValue(hours, mTvHours, mTvHours2, mHoursIn, mHoursOut, mHoursPrimary, initialRound)) { mHoursPrimary = !mHoursPrimary; } String minutes = mDF.format(iMinutes); if (animateValue(minutes, mTvMinutes, mTvMinutes2, mMinutesIn, mMinutesOut, mMinutesPrimary, initialRound)) { mMinutesPrimary = !mMinutesPrimary; } String seconds = mDF.format(iSeconds); if (animateValue(seconds, mTvSeconds, mTvSeconds2, mSecondsIn, mSecondsOut, mSecondsPrimary, initialRound)) { mSecondsPrimary = !mSecondsPrimary; } if (initialRound) { initialRound = false; } } // Returns true if animation was triggered. private boolean animateValue(String value, TextView viewOne, TextView viewTwo, Animation animIn, Animation animOut, boolean usePrimary, boolean initialRound) { if (viewOne == null || viewTwo == null) { return false; } boolean rc = false; if (Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) { if (initialRound) { viewOne.setText(value); viewOne.setContentDescription(viewOne.getText()); viewTwo.setText(value); viewTwo.setContentDescription(viewTwo.getText()); viewOne.startAnimation(animIn); viewTwo.startAnimation(animOut); //noinspection ConstantConditions return rc; } String one = viewOne.getText().toString(); String two = viewTwo.getText().toString(); if (usePrimary) { if (value.compareTo(two) != 0) { viewOne.setText(value); viewOne.setContentDescription(viewOne.getText()); viewOne.clearAnimation(); viewOne.startAnimation(animIn); viewTwo.clearAnimation(); viewTwo.startAnimation(animOut); rc = true; } } else { if (value.compareTo(one) != 0) { viewTwo.setText(value); viewTwo.setContentDescription(viewTwo.getText()); viewTwo.clearAnimation(); viewTwo.startAnimation(animIn); viewOne.clearAnimation(); viewOne.startAnimation(animOut); rc = true; } } } else { // Skip animations on ICS and below. viewOne.setText(value); viewOne.setContentDescription(viewOne.getText()); if (initialRound) { viewOne.setVisibility(View.VISIBLE); } } return rc; } @Override public void onFinish() { final LaunchCountdownContext launchContext = mLaunchContextRef.get(); if (launchContext != null) { launchContext.onCountdownFinished(); } } }; mTimer.start(); } public void cancel() { if (mTimer != null) { mTimer.cancel(); } mTimer = null; } }