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