1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy 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, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.inputmethod.keyboard.internal; 18 19 import android.animation.Animator; 20 import android.animation.AnimatorInflater; 21 import android.animation.AnimatorSet; 22 import android.animation.ObjectAnimator; 23 import android.content.res.TypedArray; 24 import android.view.View; 25 import android.view.animation.AccelerateInterpolator; 26 import android.view.animation.DecelerateInterpolator; 27 28 import com.android.inputmethod.latin.R; 29 30 public final class KeyPreviewDrawParams { 31 // XML attributes of {@link MainKeyboardView}. 32 public final int mPreviewOffset; 33 public final int mPreviewHeight; 34 public final int mPreviewBackgroundResId; 35 private final int mShowUpAnimatorResId; 36 private final int mDismissAnimatorResId; 37 private boolean mHasCustomAnimationParams; 38 private int mShowUpDuration; 39 private int mDismissDuration; 40 private float mShowUpStartXScale; 41 private float mShowUpStartYScale; 42 private float mDismissEndXScale; 43 private float mDismissEndYScale; 44 private int mLingerTimeout; 45 private boolean mShowPopup = true; 46 47 // The graphical geometry of the key preview. 48 // <-width-> 49 // +-------+ ^ 50 // | | | 51 // |preview| height (visible) 52 // | | | 53 // + + ^ v 54 // \ / |offset 55 // +-\ /-+ v 56 // | +-+ | 57 // |parent | 58 // | key| 59 // +-------+ 60 // The background of a {@link TextView} being used for a key preview may have invisible 61 // paddings. To align the more keys keyboard panel's visible part with the visible part of 62 // the background, we need to record the width and height of key preview that don't include 63 // invisible paddings. 64 private int mVisibleWidth; 65 private int mVisibleHeight; 66 // The key preview may have an arbitrary offset and its background that may have a bottom 67 // padding. To align the more keys keyboard and the key preview we also need to record the 68 // offset between the top edge of parent key and the bottom of the visible part of key 69 // preview background. 70 private int mVisibleOffset; 71 72 public KeyPreviewDrawParams(final TypedArray mainKeyboardViewAttr) { 73 mPreviewOffset = mainKeyboardViewAttr.getDimensionPixelOffset( 74 R.styleable.MainKeyboardView_keyPreviewOffset, 0); 75 mPreviewHeight = mainKeyboardViewAttr.getDimensionPixelSize( 76 R.styleable.MainKeyboardView_keyPreviewHeight, 0); 77 mPreviewBackgroundResId = mainKeyboardViewAttr.getResourceId( 78 R.styleable.MainKeyboardView_keyPreviewBackground, 0); 79 mLingerTimeout = mainKeyboardViewAttr.getInt( 80 R.styleable.MainKeyboardView_keyPreviewLingerTimeout, 0); 81 mShowUpAnimatorResId = mainKeyboardViewAttr.getResourceId( 82 R.styleable.MainKeyboardView_keyPreviewShowUpAnimator, 0); 83 mDismissAnimatorResId = mainKeyboardViewAttr.getResourceId( 84 R.styleable.MainKeyboardView_keyPreviewDismissAnimator, 0); 85 } 86 87 public void setVisibleOffset(final int previewVisibleOffset) { 88 mVisibleOffset = previewVisibleOffset; 89 } 90 91 public int getVisibleOffset() { 92 return mVisibleOffset; 93 } 94 95 public void setGeometry(final View previewTextView) { 96 final int previewWidth = previewTextView.getMeasuredWidth(); 97 final int previewHeight = mPreviewHeight; 98 // The width and height of visible part of the key preview background. The content marker 99 // of the background 9-patch have to cover the visible part of the background. 100 mVisibleWidth = previewWidth - previewTextView.getPaddingLeft() 101 - previewTextView.getPaddingRight(); 102 mVisibleHeight = previewHeight - previewTextView.getPaddingTop() 103 - previewTextView.getPaddingBottom(); 104 // The distance between the top edge of the parent key and the bottom of the visible part 105 // of the key preview background. 106 setVisibleOffset(mPreviewOffset - previewTextView.getPaddingBottom()); 107 } 108 109 public int getVisibleWidth() { 110 return mVisibleWidth; 111 } 112 113 public int getVisibleHeight() { 114 return mVisibleHeight; 115 } 116 117 public void setPopupEnabled(final boolean enabled, final int lingerTimeout) { 118 mShowPopup = enabled; 119 mLingerTimeout = lingerTimeout; 120 } 121 122 public boolean isPopupEnabled() { 123 return mShowPopup; 124 } 125 126 public int getLingerTimeout() { 127 return mLingerTimeout; 128 } 129 130 public void setAnimationParams(final boolean hasCustomAnimationParams, 131 final float showUpStartXScale, final float showUpStartYScale, final int showUpDuration, 132 final float dismissEndXScale, final float dismissEndYScale, final int dismissDuration) { 133 mHasCustomAnimationParams = hasCustomAnimationParams; 134 mShowUpStartXScale = showUpStartXScale; 135 mShowUpStartYScale = showUpStartYScale; 136 mShowUpDuration = showUpDuration; 137 mDismissEndXScale = dismissEndXScale; 138 mDismissEndYScale = dismissEndYScale; 139 mDismissDuration = dismissDuration; 140 } 141 142 private static final float KEY_PREVIEW_SHOW_UP_END_SCALE = 1.0f; 143 private static final AccelerateInterpolator ACCELERATE_INTERPOLATOR = 144 new AccelerateInterpolator(); 145 private static final DecelerateInterpolator DECELERATE_INTERPOLATOR = 146 new DecelerateInterpolator(); 147 148 public Animator createShowUpAnimator(final View target) { 149 if (mHasCustomAnimationParams) { 150 final ObjectAnimator scaleXAnimator = ObjectAnimator.ofFloat( 151 target, View.SCALE_X, mShowUpStartXScale, 152 KEY_PREVIEW_SHOW_UP_END_SCALE); 153 final ObjectAnimator scaleYAnimator = ObjectAnimator.ofFloat( 154 target, View.SCALE_Y, mShowUpStartYScale, 155 KEY_PREVIEW_SHOW_UP_END_SCALE); 156 final AnimatorSet showUpAnimator = new AnimatorSet(); 157 showUpAnimator.play(scaleXAnimator).with(scaleYAnimator); 158 showUpAnimator.setDuration(mShowUpDuration); 159 showUpAnimator.setInterpolator(DECELERATE_INTERPOLATOR); 160 return showUpAnimator; 161 } 162 final Animator animator = AnimatorInflater.loadAnimator( 163 target.getContext(), mShowUpAnimatorResId); 164 animator.setTarget(target); 165 animator.setInterpolator(DECELERATE_INTERPOLATOR); 166 return animator; 167 } 168 169 public Animator createDismissAnimator(final View target) { 170 if (mHasCustomAnimationParams) { 171 final ObjectAnimator scaleXAnimator = ObjectAnimator.ofFloat( 172 target, View.SCALE_X, mDismissEndXScale); 173 final ObjectAnimator scaleYAnimator = ObjectAnimator.ofFloat( 174 target, View.SCALE_Y, mDismissEndYScale); 175 final AnimatorSet dismissAnimator = new AnimatorSet(); 176 dismissAnimator.play(scaleXAnimator).with(scaleYAnimator); 177 final int dismissDuration = Math.min(mDismissDuration, mLingerTimeout); 178 dismissAnimator.setDuration(dismissDuration); 179 dismissAnimator.setInterpolator(ACCELERATE_INTERPOLATOR); 180 return dismissAnimator; 181 } 182 final Animator animator = AnimatorInflater.loadAnimator( 183 target.getContext(), mDismissAnimatorResId); 184 animator.setTarget(target); 185 animator.setInterpolator(ACCELERATE_INTERPOLATOR); 186 return animator; 187 } 188 } 189