Home | History | Annotate | Download | only in ui
      1 /*
      2  * Copyright (C) 2014 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 
     17 package com.android.camera.ui;
     18 
     19 import java.util.Locale;
     20 
     21 import android.content.Context;
     22 import android.graphics.RectF;
     23 import android.os.Handler;
     24 import android.os.Message;
     25 import android.util.AttributeSet;
     26 import android.view.View;
     27 import android.widget.FrameLayout;
     28 import android.widget.TextView;
     29 
     30 import com.android.camera.debug.Log;
     31 import com.android.camera2.R;
     32 
     33 /**
     34  * This class manages the looks of the countdown.
     35  */
     36 public class CountDownView extends FrameLayout {
     37 
     38     private static final Log.Tag TAG = new Log.Tag("CountDownView");
     39     private static final int SET_TIMER_TEXT = 1;
     40     private static final long ANIMATION_DURATION_MS = 800;
     41     private TextView mRemainingSecondsView;
     42     private int mRemainingSecs = 0;
     43     private OnCountDownStatusListener mListener;
     44     private final Handler mHandler = new MainHandler();
     45     private final RectF mPreviewArea = new RectF();
     46 
     47     /**
     48      * Listener that gets notified when the countdown status has
     49      * been updated (i.e. remaining seconds changed, or finished).
     50      */
     51     public interface OnCountDownStatusListener {
     52         /**
     53          * Gets notified when the remaining seconds for the countdown
     54          * has changed.
     55          *
     56          * @param remainingSeconds seconds remained for countdown
     57          */
     58         public void onRemainingSecondsChanged(int remainingSeconds);
     59 
     60         /**
     61          * Gets called when countdown is finished.
     62          */
     63         public void onCountDownFinished();
     64     }
     65 
     66     public CountDownView(Context context, AttributeSet attrs) {
     67         super(context, attrs);
     68     }
     69 
     70     /**
     71      * Returns whether countdown is on-going.
     72      */
     73     public boolean isCountingDown() {
     74         return mRemainingSecs > 0;
     75     };
     76 
     77     /**
     78      * Responds to preview area change by centering th countdown UI in the new
     79      * preview area.
     80      */
     81     public void onPreviewAreaChanged(RectF previewArea) {
     82         mPreviewArea.set(previewArea);
     83     }
     84 
     85     private void remainingSecondsChanged(int newVal) {
     86         mRemainingSecs = newVal;
     87         if (mListener != null) {
     88             mListener.onRemainingSecondsChanged(mRemainingSecs);
     89         }
     90 
     91         if (newVal == 0) {
     92             // Countdown has finished.
     93             setVisibility(View.INVISIBLE);
     94             if (mListener != null) {
     95                 mListener.onCountDownFinished();
     96             }
     97         } else {
     98             Locale locale = getResources().getConfiguration().locale;
     99             String localizedValue = String.format(locale, "%d", newVal);
    100             mRemainingSecondsView.setText(localizedValue);
    101             // Fade-out animation.
    102             startFadeOutAnimation();
    103             // Schedule the next remainingSecondsChanged() call in 1 second
    104             mHandler.sendEmptyMessageDelayed(SET_TIMER_TEXT, 1000);
    105         }
    106     }
    107 
    108     private void startFadeOutAnimation() {
    109         int textWidth = mRemainingSecondsView.getMeasuredWidth();
    110         int textHeight = mRemainingSecondsView.getMeasuredHeight();
    111         mRemainingSecondsView.setScaleX(1f);
    112         mRemainingSecondsView.setScaleY(1f);
    113         mRemainingSecondsView.setTranslationX(mPreviewArea.centerX() - textWidth / 2);
    114         mRemainingSecondsView.setTranslationY(mPreviewArea.centerY() - textHeight / 2);
    115         mRemainingSecondsView.setPivotX(textWidth / 2);
    116         mRemainingSecondsView.setPivotY(textHeight / 2);
    117         mRemainingSecondsView.setAlpha(1f);
    118         float endScale = 2.5f;
    119         mRemainingSecondsView.animate().scaleX(endScale).scaleY(endScale)
    120                 .alpha(0f).setDuration(ANIMATION_DURATION_MS).start();
    121     }
    122 
    123     @Override
    124     protected void onFinishInflate() {
    125         super.onFinishInflate();
    126         mRemainingSecondsView = (TextView) findViewById(R.id.remaining_seconds);
    127     }
    128 
    129     /**
    130      * Sets a listener that gets notified when the status of countdown has changed.
    131      */
    132     public void setCountDownStatusListener(OnCountDownStatusListener listener) {
    133         mListener = listener;
    134     }
    135 
    136     /**
    137      * Starts showing countdown in the UI.
    138      *
    139      * @param sec duration of the countdown, in seconds
    140      */
    141     public void startCountDown(int sec) {
    142         if (sec <= 0) {
    143             Log.w(TAG, "Invalid input for countdown timer: " + sec + " seconds");
    144             return;
    145         }
    146         if (isCountingDown()) {
    147             cancelCountDown();
    148         }
    149         setVisibility(View.VISIBLE);
    150         remainingSecondsChanged(sec);
    151     }
    152 
    153     /**
    154      * Cancels the on-going countdown in the UI, if any.
    155      */
    156     public void cancelCountDown() {
    157         if (mRemainingSecs > 0) {
    158             mRemainingSecs = 0;
    159             mHandler.removeMessages(SET_TIMER_TEXT);
    160             setVisibility(View.INVISIBLE);
    161         }
    162     }
    163 
    164     private class MainHandler extends Handler {
    165         @Override
    166         public void handleMessage(Message message) {
    167             if (message.what == SET_TIMER_TEXT) {
    168                 remainingSecondsChanged(mRemainingSecs -1);
    169             }
    170         }
    171     }
    172 }