• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ButtonSwitcher(Context context, AttributeSet attrs)53     public ButtonSwitcher(Context context, AttributeSet attrs) {
54         super(context, attrs);
55     }
56 
ButtonSwitcher(Context context, AttributeSet attrs, int defStyle)57     public ButtonSwitcher(Context context, AttributeSet attrs, int defStyle) {
58         super(context, attrs, defStyle);
59     }
60 
reset(final DictionaryListInterfaceState interfaceState)61     public void reset(final DictionaryListInterfaceState interfaceState) {
62         mStatus = NOT_INITIALIZED;
63         mAnimateToStatus = NOT_INITIALIZED;
64         mInterfaceState = interfaceState;
65     }
66 
67     @Override
onLayout(final boolean changed, final int left, final int top, final int right, final int bottom)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 
getButton(final int status)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 
setStatusAndUpdateVisuals(final int status)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 
setButtonPositionWithoutAnimation(final int status)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     // The helper method for {@link AnimatorListenerAdapter}.
animateButtonIfStatusIsEqual(final View newButton, final int newStatus)126     void animateButtonIfStatusIsEqual(final View newButton, final int newStatus) {
127         if (newStatus != mStatus) return;
128         animateButton(newButton, ANIMATION_IN);
129     }
130 
animateButtonPosition(final int oldStatus, final int newStatus)131     private void animateButtonPosition(final int oldStatus, final int newStatus) {
132         final View oldButton = getButton(oldStatus);
133         final View newButton = getButton(newStatus);
134         if (null != oldButton && null != newButton) {
135             // Transition between two buttons : animate out, then in
136             animateButton(oldButton, ANIMATION_OUT).setListener(new AnimatorListenerAdapter() {
137                 @Override
138                 public void onAnimationEnd(final Animator animation) {
139                     animateButtonIfStatusIsEqual(newButton, newStatus);
140                 }
141             });
142         } else if (null != oldButton) {
143             animateButton(oldButton, ANIMATION_OUT);
144         } else if (null != newButton) {
145             animateButton(newButton, ANIMATION_IN);
146         }
147     }
148 
setInternalOnClickListener(final OnClickListener listener)149     public void setInternalOnClickListener(final OnClickListener listener) {
150         mOnClickListener = listener;
151         if (null != mInstallButton) {
152             // Already laid out : do it now
153             mInstallButton.setOnClickListener(mOnClickListener);
154             mCancelButton.setOnClickListener(mOnClickListener);
155             mDeleteButton.setOnClickListener(mOnClickListener);
156         }
157     }
158 
animateButton(final View button, final int direction)159     private ViewPropertyAnimator animateButton(final View button, final int direction) {
160         final float outerX = getWidth();
161         final float innerX = button.getX() - button.getTranslationX();
162         mInterfaceState.removeFromCache((View)getParent());
163         if (ANIMATION_IN == direction) {
164             button.setClickable(true);
165             return button.animate().translationX(0);
166         }
167         button.setClickable(false);
168         return button.animate().translationX(outerX - innerX);
169     }
170 }
171