1bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka/* 2bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka * Copyright (C) 2014 The Android Open Source Project 3bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka * 4bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka * Licensed under the Apache License, Version 2.0 (the "License"); 5bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka * you may not use this file except in compliance with the License. 6bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka * You may obtain a copy of the License at 7bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka * 8bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka * http://www.apache.org/licenses/LICENSE-2.0 9bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka * 10bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka * Unless required by applicable law or agreed to in writing, software 11bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka * distributed under the License is distributed on an "AS IS" BASIS, 12bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka * See the License for the specific language governing permissions and 14bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka * limitations under the License. 15bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka */ 16bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka 17bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaokapackage com.android.inputmethod.keyboard.internal; 18bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka 19bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaokaimport android.animation.Animator; 20bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaokaimport android.animation.AnimatorListenerAdapter; 21bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaokaimport android.content.Context; 22bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaokaimport android.view.View; 23bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaokaimport android.view.ViewGroup; 24bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka 25bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaokaimport com.android.inputmethod.keyboard.Key; 265b91b551e5ffaf2c2e691dfbd434f21c82293986Jean Chalardimport com.android.inputmethod.latin.common.CoordinateUtils; 27bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaokaimport com.android.inputmethod.latin.utils.ViewLayoutUtils; 28bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka 29bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaokaimport java.util.ArrayDeque; 30bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaokaimport java.util.HashMap; 31bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka 32bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka/** 33bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka * This class controls pop up key previews. This class decides: 34bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka * - what kind of key previews should be shown. 35bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka * - where key previews should be placed. 36bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka * - how key previews should be shown and dismissed. 37bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka */ 38bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaokapublic final class KeyPreviewChoreographer { 39615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka // Free {@link KeyPreviewView} pool that can be used for key preview. 40615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka private final ArrayDeque<KeyPreviewView> mFreeKeyPreviewViews = new ArrayDeque<>(); 41615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka // Map from {@link Key} to {@link KeyPreviewView} that is currently being displayed as key 42615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka // preview. 43615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka private final HashMap<Key,KeyPreviewView> mShowingKeyPreviewViews = new HashMap<>(); 44bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka 45bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka private final KeyPreviewDrawParams mParams; 46bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka 47bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka public KeyPreviewChoreographer(final KeyPreviewDrawParams params) { 48bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka mParams = params; 49bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka } 50bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka 51615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka public KeyPreviewView getKeyPreviewView(final Key key, final ViewGroup placerView) { 52615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka KeyPreviewView keyPreviewView = mShowingKeyPreviewViews.remove(key); 53615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka if (keyPreviewView != null) { 54615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka return keyPreviewView; 55bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka } 56615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka keyPreviewView = mFreeKeyPreviewViews.poll(); 57615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka if (keyPreviewView != null) { 58615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka return keyPreviewView; 59bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka } 60bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka final Context context = placerView.getContext(); 61615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka keyPreviewView = new KeyPreviewView(context, null /* attrs */); 62615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka keyPreviewView.setBackgroundResource(mParams.mPreviewBackgroundResId); 63615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka placerView.addView(keyPreviewView, ViewLayoutUtils.newLayoutParam(placerView, 0, 0)); 64615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka return keyPreviewView; 65bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka } 66bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka 67bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka public boolean isShowingKeyPreview(final Key key) { 68615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka return mShowingKeyPreviewViews.containsKey(key); 69bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka } 70bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka 71bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka public void dismissKeyPreview(final Key key, final boolean withAnimation) { 72bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka if (key == null) { 73bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka return; 74bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka } 75615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka final KeyPreviewView keyPreviewView = mShowingKeyPreviewViews.get(key); 76615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka if (keyPreviewView == null) { 77bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka return; 78bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka } 79615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka final Object tag = keyPreviewView.getTag(); 80bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka if (withAnimation) { 81ac88f3d8459e17236654aa38debea749ecb631d1Tadashi G. Takaoka if (tag instanceof KeyPreviewAnimators) { 82ac88f3d8459e17236654aa38debea749ecb631d1Tadashi G. Takaoka final KeyPreviewAnimators animators = (KeyPreviewAnimators)tag; 83ac88f3d8459e17236654aa38debea749ecb631d1Tadashi G. Takaoka animators.startDismiss(); 847e9b0b42bfd5c51f4bc236a73df3f14cf583c989Tadashi G. Takaoka return; 85bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka } 86bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka } 87bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka // Dismiss preview without animation. 88615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka mShowingKeyPreviewViews.remove(key); 89bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka if (tag instanceof Animator) { 90bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka ((Animator)tag).cancel(); 91bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka } 92615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka keyPreviewView.setTag(null); 93615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka keyPreviewView.setVisibility(View.INVISIBLE); 94615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka mFreeKeyPreviewViews.add(keyPreviewView); 95bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka } 96bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka 9784405d2a6815a99992849e821e073835f2d892e3Tadashi G. Takaoka public void placeAndShowKeyPreview(final Key key, final KeyboardIconsSet iconsSet, 983ff72dd0daa9baaeb4d6b8ade59d65c1f0e8b34fTadashi G. Takaoka final KeyDrawParams drawParams, final int keyboardViewWidth, final int[] keyboardOrigin, 993ff72dd0daa9baaeb4d6b8ade59d65c1f0e8b34fTadashi G. Takaoka final ViewGroup placerView, final boolean withAnimation) { 100615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka final KeyPreviewView keyPreviewView = getKeyPreviewView(key, placerView); 1013ff72dd0daa9baaeb4d6b8ade59d65c1f0e8b34fTadashi G. Takaoka placeKeyPreview( 102615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka key, keyPreviewView, iconsSet, drawParams, keyboardViewWidth, keyboardOrigin); 103615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka showKeyPreview(key, keyPreviewView, withAnimation); 1043ff72dd0daa9baaeb4d6b8ade59d65c1f0e8b34fTadashi G. Takaoka } 1053ff72dd0daa9baaeb4d6b8ade59d65c1f0e8b34fTadashi G. Takaoka 106615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka private void placeKeyPreview(final Key key, final KeyPreviewView keyPreviewView, 107bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka final KeyboardIconsSet iconsSet, final KeyDrawParams drawParams, 108bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka final int keyboardViewWidth, final int[] originCoords) { 109615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka keyPreviewView.setPreviewVisual(key, iconsSet, drawParams); 110615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka keyPreviewView.measure( 111bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); 112615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka mParams.setGeometry(keyPreviewView); 113615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka final int previewWidth = keyPreviewView.getMeasuredWidth(); 114bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka final int previewHeight = mParams.mPreviewHeight; 115bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka final int keyDrawWidth = key.getDrawWidth(); 116bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka // The key preview is horizontally aligned with the center of the visible part of the 117bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka // parent key. If it doesn't fit in this {@link KeyboardView}, it is moved inward to fit and 118bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka // the left/right background is used if such background is specified. 119615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka final int keyPreviewPosition; 120bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka int previewX = key.getDrawX() - (previewWidth - keyDrawWidth) / 2 121bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka + CoordinateUtils.x(originCoords); 122bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka if (previewX < 0) { 123bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka previewX = 0; 124615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka keyPreviewPosition = KeyPreviewView.POSITION_LEFT; 125bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka } else if (previewX > keyboardViewWidth - previewWidth) { 126bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka previewX = keyboardViewWidth - previewWidth; 127615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka keyPreviewPosition = KeyPreviewView.POSITION_RIGHT; 128bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka } else { 129615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka keyPreviewPosition = KeyPreviewView.POSITION_MIDDLE; 130bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka } 131615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka final boolean hasMoreKeys = (key.getMoreKeys() != null); 132615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka keyPreviewView.setPreviewBackground(hasMoreKeys, keyPreviewPosition); 133bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka // The key preview is placed vertically above the top edge of the parent key with an 134bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka // arbitrary offset. 135bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka final int previewY = key.getY() - previewHeight + mParams.mPreviewOffset 136bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka + CoordinateUtils.y(originCoords); 137bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka 138bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka ViewLayoutUtils.placeViewAt( 139615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka keyPreviewView, previewX, previewY, previewWidth, previewHeight); 140615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka keyPreviewView.setPivotX(previewWidth / 2.0f); 141615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka keyPreviewView.setPivotY(previewHeight); 142bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka } 143bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka 1445f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka void showKeyPreview(final Key key, final KeyPreviewView keyPreviewView, 145bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka final boolean withAnimation) { 146bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka if (!withAnimation) { 147615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka keyPreviewView.setVisibility(View.VISIBLE); 148615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka mShowingKeyPreviewViews.put(key, keyPreviewView); 149bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka return; 150bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka } 151bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka 152bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka // Show preview with animation. 153ac88f3d8459e17236654aa38debea749ecb631d1Tadashi G. Takaoka final Animator showUpAnimator = createShowUpAnimator(key, keyPreviewView); 154ac88f3d8459e17236654aa38debea749ecb631d1Tadashi G. Takaoka final Animator dismissAnimator = createDismissAnimator(key, keyPreviewView); 155ac88f3d8459e17236654aa38debea749ecb631d1Tadashi G. Takaoka final KeyPreviewAnimators animators = new KeyPreviewAnimators( 156ac88f3d8459e17236654aa38debea749ecb631d1Tadashi G. Takaoka showUpAnimator, dismissAnimator); 157ac88f3d8459e17236654aa38debea749ecb631d1Tadashi G. Takaoka keyPreviewView.setTag(animators); 158ac88f3d8459e17236654aa38debea749ecb631d1Tadashi G. Takaoka animators.startShowUp(); 159bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka } 160bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka 161ac88f3d8459e17236654aa38debea749ecb631d1Tadashi G. Takaoka public Animator createShowUpAnimator(final Key key, final KeyPreviewView keyPreviewView) { 1625f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka final Animator showUpAnimator = mParams.createShowUpAnimator(keyPreviewView); 1635f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka showUpAnimator.addListener(new AnimatorListenerAdapter() { 164bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka @Override 165ac88f3d8459e17236654aa38debea749ecb631d1Tadashi G. Takaoka public void onAnimationStart(final Animator animator) { 166615f431465ed2b5f3511ddfcc4c6de7bbfc28151Tadashi G. Takaoka showKeyPreview(key, keyPreviewView, false /* withAnimation */); 167bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka } 168bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka }); 1695f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka return showUpAnimator; 170bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka } 171bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka 172ac88f3d8459e17236654aa38debea749ecb631d1Tadashi G. Takaoka private Animator createDismissAnimator(final Key key, final KeyPreviewView keyPreviewView) { 1735f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka final Animator dismissAnimator = mParams.createDismissAnimator(keyPreviewView); 1745f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka dismissAnimator.addListener(new AnimatorListenerAdapter() { 175bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka @Override 176ac88f3d8459e17236654aa38debea749ecb631d1Tadashi G. Takaoka public void onAnimationEnd(final Animator animator) { 177bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka dismissKeyPreview(key, false /* withAnimation */); 178bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka } 179bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka }); 1805f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka return dismissAnimator; 181bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka } 182bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka 183ac88f3d8459e17236654aa38debea749ecb631d1Tadashi G. Takaoka private static class KeyPreviewAnimators extends AnimatorListenerAdapter { 184ac88f3d8459e17236654aa38debea749ecb631d1Tadashi G. Takaoka private final Animator mShowUpAnimator; 185ac88f3d8459e17236654aa38debea749ecb631d1Tadashi G. Takaoka private final Animator mDismissAnimator; 186bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka 187ac88f3d8459e17236654aa38debea749ecb631d1Tadashi G. Takaoka public KeyPreviewAnimators(final Animator showUpAnimator, final Animator dismissAnimator) { 188ac88f3d8459e17236654aa38debea749ecb631d1Tadashi G. Takaoka mShowUpAnimator = showUpAnimator; 189ac88f3d8459e17236654aa38debea749ecb631d1Tadashi G. Takaoka mDismissAnimator = dismissAnimator; 190bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka } 191bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka 192276b1a2ebc6d5ea3fa36fa9271cdc6310db34021Tadashi G. Takaoka public void startShowUp() { 193ac88f3d8459e17236654aa38debea749ecb631d1Tadashi G. Takaoka mShowUpAnimator.start(); 194bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka } 195bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka 196276b1a2ebc6d5ea3fa36fa9271cdc6310db34021Tadashi G. Takaoka public void startDismiss() { 197ac88f3d8459e17236654aa38debea749ecb631d1Tadashi G. Takaoka if (mShowUpAnimator.isRunning()) { 198ac88f3d8459e17236654aa38debea749ecb631d1Tadashi G. Takaoka mShowUpAnimator.addListener(this); 199bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka return; 200bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka } 201ac88f3d8459e17236654aa38debea749ecb631d1Tadashi G. Takaoka mDismissAnimator.start(); 202bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka } 203bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka 204bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka @Override 205ac88f3d8459e17236654aa38debea749ecb631d1Tadashi G. Takaoka public void onAnimationEnd(final Animator animator) { 206ac88f3d8459e17236654aa38debea749ecb631d1Tadashi G. Takaoka mDismissAnimator.start(); 207bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka } 208bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka } 209bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka} 210