Home | History | Annotate | Download | only in dictionarypack
      1 /**
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
      5  * use this file except in compliance with the License. You may obtain a copy
      6  * 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, WITHOUT
     12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
     13  * License for the specific language governing permissions and limitations
     14  * under the License.
     15  */
     16 
     17 package com.android.inputmethod.dictionarypack;
     18 
     19 import android.animation.Animator;
     20 import android.animation.AnimatorListenerAdapter;
     21 import android.content.Context;
     22 import android.util.AttributeSet;
     23 import android.view.View;
     24 import android.view.ViewPropertyAnimator;
     25 import android.widget.Button;
     26 import android.widget.FrameLayout;
     27 
     28 import com.android.inputmethod.latin.R;
     29 
     30 /**
     31  * A view that handles buttons inside it according to a status.
     32  */
     33 public class ButtonSwitcher extends FrameLayout {
     34     public static final int NOT_INITIALIZED = -1;
     35     public static final int STATUS_NO_BUTTON = 0;
     36     public static final int STATUS_INSTALL = 1;
     37     public static final int STATUS_CANCEL = 2;
     38     public static final int STATUS_DELETE = 3;
     39     // One of the above
     40     private int mStatus = NOT_INITIALIZED;
     41     private int mAnimateToStatus = NOT_INITIALIZED;
     42 
     43     // Animation directions
     44     public static final int ANIMATION_IN = 1;
     45     public static final int ANIMATION_OUT = 2;
     46 
     47     private Button mInstallButton;
     48     private Button mCancelButton;
     49     private Button mDeleteButton;
     50     private DictionaryListInterfaceState mInterfaceState;
     51     private OnClickListener mOnClickListener;
     52 
     53     public ButtonSwitcher(Context context, AttributeSet attrs) {
     54         super(context, attrs);
     55     }
     56 
     57     public ButtonSwitcher(Context context, AttributeSet attrs, int defStyle) {
     58         super(context, attrs, defStyle);
     59     }
     60 
     61     public void reset(final DictionaryListInterfaceState interfaceState) {
     62         mStatus = NOT_INITIALIZED;
     63         mAnimateToStatus = NOT_INITIALIZED;
     64         mInterfaceState = interfaceState;
     65     }
     66 
     67     @Override
     68     protected void onLayout(final boolean changed, final int left, final int top, final int right,
     69             final int bottom) {
     70         super.onLayout(changed, left, top, right, bottom);
     71         mInstallButton = (Button)findViewById(R.id.dict_install_button);
     72         mCancelButton = (Button)findViewById(R.id.dict_cancel_button);
     73         mDeleteButton = (Button)findViewById(R.id.dict_delete_button);
     74         setInternalOnClickListener(mOnClickListener);
     75         setButtonPositionWithoutAnimation(mStatus);
     76         if (mAnimateToStatus != NOT_INITIALIZED) {
     77             // We have been asked to animate before we were ready, so we took a note of it.
     78             // We are now ready: launch the animation.
     79             animateButtonPosition(mStatus, mAnimateToStatus);
     80             mStatus = mAnimateToStatus;
     81             mAnimateToStatus = NOT_INITIALIZED;
     82         }
     83     }
     84 
     85     private Button getButton(final int status) {
     86         switch(status) {
     87         case STATUS_INSTALL:
     88             return mInstallButton;
     89         case STATUS_CANCEL:
     90             return mCancelButton;
     91         case STATUS_DELETE:
     92             return mDeleteButton;
     93         default:
     94             return null;
     95         }
     96     }
     97 
     98     public void setStatusAndUpdateVisuals(final int status) {
     99         if (mStatus == NOT_INITIALIZED) {
    100             setButtonPositionWithoutAnimation(status);
    101             mStatus = status;
    102         } else {
    103             if (null == mInstallButton) {
    104                 // We may come here before we have been layout. In this case we don't know our
    105                 // size yet so we can't start animations so we need to remember what animation to
    106                 // start once layout has gone through.
    107                 mAnimateToStatus = status;
    108             } else {
    109                 animateButtonPosition(mStatus, status);
    110                 mStatus = status;
    111             }
    112         }
    113     }
    114 
    115     private void setButtonPositionWithoutAnimation(final int status) {
    116         // This may be called by setStatus() before the layout has come yet.
    117         if (null == mInstallButton) return;
    118         final int width = getWidth();
    119         // Set to out of the screen if that's not the currently displayed status
    120         mInstallButton.setTranslationX(STATUS_INSTALL == status ? 0 : width);
    121         mCancelButton.setTranslationX(STATUS_CANCEL == status ? 0 : width);
    122         mDeleteButton.setTranslationX(STATUS_DELETE == status ? 0 : width);
    123     }
    124 
    125     private void animateButtonPosition(final int oldStatus, final int newStatus) {
    126         final View oldButton = getButton(oldStatus);
    127         final View newButton = getButton(newStatus);
    128         if (null != oldButton && null != newButton) {
    129             // Transition between two buttons : animate out, then in
    130             animateButton(oldButton, ANIMATION_OUT).setListener(
    131                     new AnimatorListenerAdapter() {
    132                         @Override
    133                         public void onAnimationEnd(final Animator animation) {
    134                             if (newStatus != mStatus) return;
    135                             animateButton(newButton, ANIMATION_IN);
    136                         }
    137                     });
    138         } else if (null != oldButton) {
    139             animateButton(oldButton, ANIMATION_OUT);
    140         } else if (null != newButton) {
    141             animateButton(newButton, ANIMATION_IN);
    142         }
    143     }
    144 
    145     public void setInternalOnClickListener(final OnClickListener listener) {
    146         mOnClickListener = listener;
    147         if (null != mInstallButton) {
    148             // Already laid out : do it now
    149             mInstallButton.setOnClickListener(mOnClickListener);
    150             mCancelButton.setOnClickListener(mOnClickListener);
    151             mDeleteButton.setOnClickListener(mOnClickListener);
    152         }
    153     }
    154 
    155     private ViewPropertyAnimator animateButton(final View button, final int direction) {
    156         final float outerX = getWidth();
    157         final float innerX = button.getX() - button.getTranslationX();
    158         mInterfaceState.removeFromCache((View)getParent());
    159         if (ANIMATION_IN == direction) {
    160             button.setClickable(true);
    161             return button.animate().translationX(0);
    162         } else {
    163             button.setClickable(false);
    164             return button.animate().translationX(outerX - innerX);
    165         }
    166     }
    167 }
    168