Home | History | Annotate | Download | only in speaker
      1 /*
      2  * Copyright (C) 2015 Google Inc. All Rights Reserved.
      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.example.android.wearable.speaker;
     18 
     19 import android.animation.Animator;
     20 import android.animation.AnimatorListenerAdapter;
     21 import android.animation.AnimatorSet;
     22 import android.animation.ObjectAnimator;
     23 import android.graphics.Point;
     24 import android.graphics.Rect;
     25 import android.view.View;
     26 import android.view.animation.DecelerateInterpolator;
     27 import android.widget.ImageView;
     28 
     29 /**
     30  * A helper class to provide a simple animation when user selects any of the three icons on the
     31  * main UI.
     32  */
     33 public class UIAnimation {
     34 
     35     private AnimatorSet mCurrentAnimator;
     36     private final int[] mLargeDrawables = new int[]{R.drawable.ic_mic_120dp,
     37             R.drawable.ic_play_arrow_120dp, R.drawable.ic_audiotrack_120dp};
     38     private final ImageView[] mThumbs;
     39     private ImageView expandedImageView;
     40     private final View mContainerView;
     41     private final int mAnimationDurationTime;
     42 
     43     private UIStateListener mListener;
     44     private UIState mState = UIState.HOME;
     45 
     46     public UIAnimation(View containerView, ImageView[] thumbs, ImageView expandedView,
     47             int animationDuration, UIStateListener listener) {
     48         mContainerView = containerView;
     49         mThumbs = thumbs;
     50         expandedImageView = expandedView;
     51         mAnimationDurationTime = animationDuration;
     52         mListener = listener;
     53 
     54         mThumbs[0].setOnClickListener(new View.OnClickListener() {
     55             @Override
     56             public void onClick(View view) {
     57                 zoomImageFromThumb(0);
     58             }
     59         });
     60 
     61         mThumbs[1].setOnClickListener(new View.OnClickListener() {
     62             @Override
     63             public void onClick(View view) {
     64                 zoomImageFromThumb(1);
     65             }
     66         });
     67 
     68         mThumbs[2].setOnClickListener(new View.OnClickListener() {
     69             @Override
     70             public void onClick(View view) {
     71                 zoomImageFromThumb(2);
     72             }
     73         });
     74     }
     75 
     76     private void zoomImageFromThumb(final int index) {
     77         int imageResId = mLargeDrawables[index];
     78         final ImageView thumbView = mThumbs[index];
     79         if (mCurrentAnimator != null) {
     80             return;
     81         }
     82 
     83         expandedImageView.setImageResource(imageResId);
     84 
     85         final Rect startBounds = new Rect();
     86         final Rect finalBounds = new Rect();
     87         final Point globalOffset = new Point();
     88         thumbView.getGlobalVisibleRect(startBounds);
     89         mContainerView.getGlobalVisibleRect(finalBounds, globalOffset);
     90         startBounds.offset(-globalOffset.x, -globalOffset.y);
     91         finalBounds.offset(-globalOffset.x, -globalOffset.y);
     92         float startScale;
     93         if ((float) finalBounds.width() / finalBounds.height()
     94                 > (float) startBounds.width() / startBounds.height()) {
     95             startScale = (float) startBounds.height() / finalBounds.height();
     96             float startWidth = startScale * finalBounds.width();
     97             float deltaWidth = (startWidth - startBounds.width()) / 2;
     98             startBounds.left -= deltaWidth;
     99             startBounds.right += deltaWidth;
    100         } else {
    101             startScale = (float) startBounds.width() / finalBounds.width();
    102             float startHeight = startScale * finalBounds.height();
    103             float deltaHeight = (startHeight - startBounds.height()) / 2;
    104             startBounds.top -= deltaHeight;
    105             startBounds.bottom += deltaHeight;
    106         }
    107 
    108         for(int k=0; k < 3; k++) {
    109             mThumbs[k].setAlpha(0f);
    110         }
    111         expandedImageView.setVisibility(View.VISIBLE);
    112 
    113         expandedImageView.setPivotX(0f);
    114         expandedImageView.setPivotY(0f);
    115 
    116         AnimatorSet zommInAnimator = new AnimatorSet();
    117         zommInAnimator.play(ObjectAnimator
    118                 .ofFloat(expandedImageView, View.X, startBounds.left, finalBounds.left)).with(
    119                 ObjectAnimator.ofFloat(expandedImageView, View.Y, startBounds.top, finalBounds
    120                         .top)).with(
    121                 ObjectAnimator.ofFloat(expandedImageView, View.SCALE_X, startScale, 1f))
    122                 .with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_Y, startScale, 1f));
    123         zommInAnimator.setDuration(mAnimationDurationTime);
    124         zommInAnimator.setInterpolator(new DecelerateInterpolator());
    125         zommInAnimator.addListener(new AnimatorListenerAdapter() {
    126             @Override
    127             public void onAnimationEnd(Animator animation) {
    128                 mCurrentAnimator = null;
    129                 if (mListener != null) {
    130                     mState = UIState.getUIState(index);
    131                     mListener.onUIStateChanged(mState);
    132                 }
    133             }
    134 
    135             @Override
    136             public void onAnimationCancel(Animator animation) {
    137                 mCurrentAnimator = null;
    138             }
    139         });
    140         zommInAnimator.start();
    141         mCurrentAnimator = zommInAnimator;
    142 
    143         final float startScaleFinal = startScale;
    144         expandedImageView.setOnClickListener(new View.OnClickListener() {
    145             @Override
    146             public void onClick(View view) {
    147                 if (mCurrentAnimator != null) {
    148                     return;
    149                 }
    150                 AnimatorSet zoomOutAnimator = new AnimatorSet();
    151                 zoomOutAnimator.play(ObjectAnimator
    152                         .ofFloat(expandedImageView, View.X, startBounds.left))
    153                         .with(ObjectAnimator
    154                                 .ofFloat(expandedImageView,
    155                                         View.Y, startBounds.top))
    156                         .with(ObjectAnimator
    157                                 .ofFloat(expandedImageView,
    158                                         View.SCALE_X, startScaleFinal))
    159                         .with(ObjectAnimator
    160                                 .ofFloat(expandedImageView,
    161                                         View.SCALE_Y, startScaleFinal));
    162                 zoomOutAnimator.setDuration(mAnimationDurationTime);
    163                 zoomOutAnimator.setInterpolator(new DecelerateInterpolator());
    164                 zoomOutAnimator.addListener(new AnimatorListenerAdapter() {
    165                     @Override
    166                     public void onAnimationEnd(Animator animation) {
    167                         for (int k = 0; k < 3; k++) {
    168                             mThumbs[k].setAlpha(1f);
    169                         }
    170                         expandedImageView.setVisibility(View.GONE);
    171                         mCurrentAnimator = null;
    172                         if (mListener != null) {
    173                             mState = UIState.HOME;
    174                             mListener.onUIStateChanged(mState);
    175                         }
    176                     }
    177 
    178                     @Override
    179                     public void onAnimationCancel(Animator animation) {
    180                         thumbView.setAlpha(1f);
    181                         expandedImageView.setVisibility(View.GONE);
    182                         mCurrentAnimator = null;
    183                     }
    184                 });
    185                 zoomOutAnimator.start();
    186                 mCurrentAnimator = zoomOutAnimator;
    187             }
    188         });
    189     }
    190 
    191     public enum UIState {
    192         MIC_UP(0), SOUND_UP(1), MUSIC_UP(2), HOME(3);
    193         private int mState;
    194 
    195         UIState(int state) {
    196             mState = state;
    197         }
    198 
    199         static UIState getUIState(int state) {
    200             for(UIState uiState : values()) {
    201                 if (uiState.mState == state) {
    202                     return uiState;
    203                 }
    204             }
    205            return null;
    206         }
    207     }
    208 
    209     public interface UIStateListener {
    210         void onUIStateChanged(UIState state);
    211     }
    212 
    213     public void transitionToHome() {
    214         if (mState == UIState.HOME) {
    215             return;
    216         }
    217         expandedImageView.callOnClick();
    218 
    219     }
    220 }
    221