Skip to content
Snippets Groups Projects
ButtonSwitcher.java 5.79 KiB
/**
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy
 * of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

package com.android.inputmethod.dictionarypack;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewPropertyAnimator;
import android.widget.Button;
import android.widget.FrameLayout;

import com.android.inputmethod.latin.R;

/**
 * A view that handles buttons inside it according to a status.
 */
public class ButtonSwitcher extends FrameLayout {
    public static final int NOT_INITIALIZED = -1;
    public static final int STATUS_NO_BUTTON = 0;
    public static final int STATUS_INSTALL = 1;
    public static final int STATUS_CANCEL = 2;
    public static final int STATUS_DELETE = 3;
    // One of the above
    private int mStatus = NOT_INITIALIZED;
    private int mAnimateToStatus = NOT_INITIALIZED;

    // Animation directions
    public static final int ANIMATION_IN = 1;
    public static final int ANIMATION_OUT = 2;

    private Button mInstallButton;
    private Button mCancelButton;
    private Button mDeleteButton;
    private OnClickListener mOnClickListener;

    public ButtonSwitcher(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ButtonSwitcher(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onLayout(final boolean changed, final int left, final int top, final int right,
            final int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        mInstallButton = (Button)findViewById(R.id.dict_install_button);
        mCancelButton = (Button)findViewById(R.id.dict_cancel_button);
        mDeleteButton = (Button)findViewById(R.id.dict_delete_button);
        mInstallButton.setOnClickListener(mOnClickListener);
        mCancelButton.setOnClickListener(mOnClickListener);
        mDeleteButton.setOnClickListener(mOnClickListener);
        setButtonPositionWithoutAnimation(mStatus);
        if (mAnimateToStatus != NOT_INITIALIZED) {
            // We have been asked to animate before we were ready, so we took a note of it.
            // We are now ready: launch the animation.
            animateButtonPosition(mStatus, mAnimateToStatus);
            mStatus = mAnimateToStatus;
            mAnimateToStatus = NOT_INITIALIZED;
        }
    }

    private Button getButton(final int status) {
        switch(status) {
        case STATUS_INSTALL:
            return mInstallButton;
        case STATUS_CANCEL:
            return mCancelButton;
        case STATUS_DELETE:
            return mDeleteButton;
        default:
            return null;
        }
    }

    public void setStatusAndUpdateVisuals(final int status) {
        if (mStatus == NOT_INITIALIZED) {
            setButtonPositionWithoutAnimation(status);
            mStatus = status;
        } else {
            if (null == mInstallButton) {
                // We may come here before we have been layout. In this case we don't know our
                // size yet so we can't start animations so we need to remember what animation to
                // start once layout has gone through.
                mAnimateToStatus = status;
            } else {
                animateButtonPosition(mStatus, status);
                mStatus = status;
            }
        }
    }

    private void setButtonPositionWithoutAnimation(final int status) {
        // This may be called by setStatus() before the layout has come yet.
        if (null == mInstallButton) return;
        final int width = getWidth();
        // Set to out of the screen if that's not the currently displayed status
        mInstallButton.setTranslationX(STATUS_INSTALL == status ? 0 : width);
        mCancelButton.setTranslationX(STATUS_CANCEL == status ? 0 : width);
        mDeleteButton.setTranslationX(STATUS_DELETE == status ? 0 : width);
    }

    private void animateButtonPosition(final int oldStatus, final int newStatus) {
        final View oldButton = getButton(oldStatus);
        final View newButton = getButton(newStatus);
        if (null != oldButton && null != newButton) {
            // Transition between two buttons : animate out, then in
            animateButton(oldButton, ANIMATION_OUT).setListener(
                    new AnimatorListenerAdapter() {
                        @Override
                        public void onAnimationEnd(final Animator animation) {
                            animateButton(newButton, ANIMATION_IN);
                        }
                    });
        } else if (null != oldButton) {
            animateButton(oldButton, ANIMATION_OUT);
        } else if (null != newButton) {
            animateButton(newButton, ANIMATION_IN);
        }
    }

    public void setInternalOnClickListener(final OnClickListener listener) {
        mOnClickListener = listener;
    }

    private ViewPropertyAnimator animateButton(final View button, final int direction) {
        final float outerX = getWidth();
        final float innerX = button.getX() - button.getTranslationX();
        if (ANIMATION_IN == direction) {
            return button.animate().translationX(0);
        } else {
            return button.animate().translationX(outerX - innerX);
        }
    }
}