ButtonSwitcher.java revision 513c63e877320bca4860dadc88e3a14ffb861e36
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
17package com.android.inputmethod.dictionarypack;
18
19import android.animation.Animator;
20import android.animation.AnimatorListenerAdapter;
21import android.content.Context;
22import android.util.AttributeSet;
23import android.view.View;
24import android.view.ViewPropertyAnimator;
25import android.widget.Button;
26import android.widget.FrameLayout;
27
28import com.android.inputmethod.latin.R;
29
30/**
31 * A view that handles buttons inside it according to a status.
32 */
33public 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 OnClickListener mOnClickListener;
51
52    public ButtonSwitcher(Context context, AttributeSet attrs) {
53        super(context, attrs);
54    }
55
56    public ButtonSwitcher(Context context, AttributeSet attrs, int defStyle) {
57        super(context, attrs, defStyle);
58    }
59
60    @Override
61    protected void onLayout(final boolean changed, final int left, final int top, final int right,
62            final int bottom) {
63        super.onLayout(changed, left, top, right, bottom);
64        mInstallButton = (Button)findViewById(R.id.dict_install_button);
65        mCancelButton = (Button)findViewById(R.id.dict_cancel_button);
66        mDeleteButton = (Button)findViewById(R.id.dict_delete_button);
67        mInstallButton.setOnClickListener(mOnClickListener);
68        mCancelButton.setOnClickListener(mOnClickListener);
69        mDeleteButton.setOnClickListener(mOnClickListener);
70        setButtonPositionWithoutAnimation(mStatus);
71        if (mAnimateToStatus != NOT_INITIALIZED) {
72            // We have been asked to animate before we were ready, so we took a note of it.
73            // We are now ready: launch the animation.
74            animateButtonPosition(mStatus, mAnimateToStatus);
75            mStatus = mAnimateToStatus;
76            mAnimateToStatus = NOT_INITIALIZED;
77        }
78    }
79
80    private Button getButton(final int status) {
81        switch(status) {
82        case STATUS_INSTALL:
83            return mInstallButton;
84        case STATUS_CANCEL:
85            return mCancelButton;
86        case STATUS_DELETE:
87            return mDeleteButton;
88        default:
89            return null;
90        }
91    }
92
93    public void setStatusAndUpdateVisuals(final int status) {
94        if (mStatus == NOT_INITIALIZED) {
95            setButtonPositionWithoutAnimation(status);
96            mStatus = status;
97        } else {
98            if (null == mInstallButton) {
99                // We may come here before we have been layout. In this case we don't know our
100                // size yet so we can't start animations so we need to remember what animation to
101                // start once layout has gone through.
102                mAnimateToStatus = status;
103            } else {
104                animateButtonPosition(mStatus, status);
105                mStatus = status;
106            }
107        }
108    }
109
110    private void setButtonPositionWithoutAnimation(final int status) {
111        // This may be called by setStatus() before the layout has come yet.
112        if (null == mInstallButton) return;
113        final int width = getWidth();
114        // Set to out of the screen if that's not the currently displayed status
115        mInstallButton.setTranslationX(STATUS_INSTALL == status ? 0 : width);
116        mCancelButton.setTranslationX(STATUS_CANCEL == status ? 0 : width);
117        mDeleteButton.setTranslationX(STATUS_DELETE == status ? 0 : width);
118    }
119
120    private void animateButtonPosition(final int oldStatus, final int newStatus) {
121        final View oldButton = getButton(oldStatus);
122        final View newButton = getButton(newStatus);
123        if (null != oldButton && null != newButton) {
124            // Transition between two buttons : animate out, then in
125            animateButton(oldButton, ANIMATION_OUT).setListener(
126                    new AnimatorListenerAdapter() {
127                        @Override
128                        public void onAnimationEnd(final Animator animation) {
129                            animateButton(newButton, ANIMATION_IN);
130                        }
131                    });
132        } else if (null != oldButton) {
133            animateButton(oldButton, ANIMATION_OUT);
134        } else if (null != newButton) {
135            animateButton(newButton, ANIMATION_IN);
136        }
137    }
138
139    public void setInternalOnClickListener(final OnClickListener listener) {
140        mOnClickListener = listener;
141    }
142
143    private ViewPropertyAnimator animateButton(final View button, final int direction) {
144        final float outerX = getWidth();
145        final float innerX = button.getX() - button.getTranslationX();
146        if (ANIMATION_IN == direction) {
147            return button.animate().translationX(0);
148        } else {
149            return button.animate().translationX(outerX - innerX);
150        }
151    }
152}
153