diff options
Diffstat (limited to 'java/com/android/incallui/answer/impl/hint/DotAnswerHint.java')
-rw-r--r-- | java/com/android/incallui/answer/impl/hint/DotAnswerHint.java | 285 |
1 files changed, 285 insertions, 0 deletions
diff --git a/java/com/android/incallui/answer/impl/hint/DotAnswerHint.java b/java/com/android/incallui/answer/impl/hint/DotAnswerHint.java new file mode 100644 index 000000000..70f3f73fc --- /dev/null +++ b/java/com/android/incallui/answer/impl/hint/DotAnswerHint.java @@ -0,0 +1,285 @@ +/* + * Copyright (C) 2016 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.incallui.answer.impl.hint; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.content.Context; +import android.support.annotation.DimenRes; +import android.support.v4.view.animation.FastOutSlowInInterpolator; +import android.util.TypedValue; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.Interpolator; +import android.view.animation.LinearInterpolator; +import android.widget.TextView; + +/** An Answer hint that uses a green swiping dot. */ +public class DotAnswerHint implements AnswerHint { + + private static final float ANSWER_HINT_SMALL_ALPHA = 0.8f; + private static final float ANSWER_HINT_MID_ALPHA = 0.5f; + private static final float ANSWER_HINT_LARGE_ALPHA = 0.2f; + + private static final long FADE_IN_DELAY_SCALE_MILLIS = 380; + private static final long FADE_IN_DURATION_SCALE_MILLIS = 200; + private static final long FADE_IN_DELAY_ALPHA_MILLIS = 340; + private static final long FADE_IN_DURATION_ALPHA_MILLIS = 50; + + private static final long SWIPE_UP_DURATION_ALPHA_MILLIS = 500; + + private static final long FADE_OUT_DELAY_SCALE_SMALL_MILLIS = 90; + private static final long FADE_OUT_DELAY_SCALE_MID_MILLIS = 70; + private static final long FADE_OUT_DELAY_SCALE_LARGE_MILLIS = 10; + private static final long FADE_OUT_DURATION_SCALE_MILLIS = 100; + private static final long FADE_OUT_DELAY_ALPHA_MILLIS = 130; + private static final long FADE_OUT_DURATION_ALPHA_MILLIS = 170; + + private final Context context; + private final long puckUpDurationMillis; + private final long puckUpDelayMillis; + + private View puck; + + private View answerHintSmall; + private View answerHintMid; + private View answerHintLarge; + private View answerHintContainer; + private AnimatorSet answerGestureHintAnim; + + public DotAnswerHint(Context context, long puckUpDurationMillis, long puckUpDelayMillis) { + this.context = context; + this.puckUpDurationMillis = puckUpDurationMillis; + this.puckUpDelayMillis = puckUpDelayMillis; + } + + @Override + public void onCreateView( + LayoutInflater inflater, ViewGroup container, View puck, TextView hintText) { + this.puck = puck; + View view = inflater.inflate(R.layout.dot_hint, container, true); + answerHintContainer = view.findViewById(R.id.answer_hint_container); + answerHintSmall = view.findViewById(R.id.answer_hint_small); + answerHintMid = view.findViewById(R.id.answer_hint_mid); + answerHintLarge = view.findViewById(R.id.answer_hint_large); + hintText.setTextSize( + TypedValue.COMPLEX_UNIT_PX, context.getResources().getDimension(R.dimen.hint_text_size)); + } + + @Override + public void onBounceStart() { + if (answerGestureHintAnim == null) { + answerGestureHintAnim = new AnimatorSet(); + int[] puckLocation = new int[2]; + puck.getLocationInWindow(puckLocation); + answerHintContainer.setY(puckLocation[1] + getDimension(R.dimen.hint_initial_offset)); + + Animator fadeIn = createFadeIn(); + + Animator swipeUp = + ObjectAnimator.ofFloat( + answerHintContainer, + View.TRANSLATION_Y, + puckLocation[1] - getDimension(R.dimen.hint_offset)); + swipeUp.setInterpolator(new FastOutSlowInInterpolator()); + swipeUp.setDuration(SWIPE_UP_DURATION_ALPHA_MILLIS); + + Animator fadeOut = createFadeOut(); + + answerGestureHintAnim.play(fadeIn).after(puckUpDelayMillis); + answerGestureHintAnim.play(swipeUp).after(fadeIn); + // The fade out should start fading the alpha just as the puck is dropping. Scaling will start + // a bit earlier. + answerGestureHintAnim + .play(fadeOut) + .after(puckUpDelayMillis + puckUpDurationMillis - FADE_OUT_DELAY_ALPHA_MILLIS); + + fadeIn.addListener( + new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + super.onAnimationStart(animation); + answerHintSmall.setAlpha(0); + answerHintSmall.setScaleX(1); + answerHintSmall.setScaleY(1); + answerHintMid.setAlpha(0); + answerHintMid.setScaleX(1); + answerHintMid.setScaleY(1); + answerHintLarge.setAlpha(0); + answerHintLarge.setScaleX(1); + answerHintLarge.setScaleY(1); + answerHintContainer.setY(puckLocation[1] + getDimension(R.dimen.hint_initial_offset)); + answerHintContainer.setVisibility(View.VISIBLE); + } + }); + } + + answerGestureHintAnim.start(); + } + + private Animator createFadeIn() { + AnimatorSet set = new AnimatorSet(); + set.play( + createFadeInScaleAndAlpha( + answerHintSmall, + R.dimen.hint_small_begin_size, + R.dimen.hint_small_end_size, + ANSWER_HINT_SMALL_ALPHA)) + .with( + createFadeInScaleAndAlpha( + answerHintMid, + R.dimen.hint_mid_begin_size, + R.dimen.hint_mid_end_size, + ANSWER_HINT_MID_ALPHA)) + .with( + createFadeInScaleAndAlpha( + answerHintLarge, + R.dimen.hint_large_begin_size, + R.dimen.hint_large_end_size, + ANSWER_HINT_LARGE_ALPHA)); + return set; + } + + private Animator createFadeInScaleAndAlpha( + View target, @DimenRes int beginSize, @DimenRes int endSize, float endAlpha) { + Animator scale = + createUniformScaleAnimator( + target, + getDimension(beginSize), + getDimension(beginSize), + getDimension(endSize), + FADE_IN_DURATION_SCALE_MILLIS, + FADE_IN_DELAY_SCALE_MILLIS, + new LinearInterpolator()); + Animator alpha = + createAlphaAnimator( + target, + 0f, + endAlpha, + FADE_IN_DURATION_ALPHA_MILLIS, + FADE_IN_DELAY_ALPHA_MILLIS, + new LinearInterpolator()); + AnimatorSet set = new AnimatorSet(); + set.play(scale).with(alpha); + return set; + } + + private Animator createFadeOut() { + AnimatorSet set = new AnimatorSet(); + set.play( + createFadeOutScaleAndAlpha( + answerHintSmall, + R.dimen.hint_small_begin_size, + R.dimen.hint_small_end_size, + FADE_OUT_DELAY_SCALE_SMALL_MILLIS, + ANSWER_HINT_SMALL_ALPHA)) + .with( + createFadeOutScaleAndAlpha( + answerHintMid, + R.dimen.hint_mid_begin_size, + R.dimen.hint_mid_end_size, + FADE_OUT_DELAY_SCALE_MID_MILLIS, + ANSWER_HINT_MID_ALPHA)) + .with( + createFadeOutScaleAndAlpha( + answerHintLarge, + R.dimen.hint_large_begin_size, + R.dimen.hint_large_end_size, + FADE_OUT_DELAY_SCALE_LARGE_MILLIS, + ANSWER_HINT_LARGE_ALPHA)); + return set; + } + + private Animator createFadeOutScaleAndAlpha( + View target, + @DimenRes int beginSize, + @DimenRes int endSize, + long scaleDelay, + float endAlpha) { + Animator scale = + createUniformScaleAnimator( + target, + getDimension(beginSize), + getDimension(endSize), + getDimension(beginSize), + FADE_OUT_DURATION_SCALE_MILLIS, + scaleDelay, + new LinearInterpolator()); + Animator alpha = + createAlphaAnimator( + target, + endAlpha, + 0.0f, + FADE_OUT_DURATION_ALPHA_MILLIS, + FADE_OUT_DELAY_ALPHA_MILLIS, + new LinearInterpolator()); + AnimatorSet set = new AnimatorSet(); + set.play(scale).with(alpha); + return set; + } + + @Override + public void onBounceEnd() { + if (answerGestureHintAnim != null) { + answerGestureHintAnim.end(); + answerGestureHintAnim = null; + answerHintContainer.setVisibility(View.GONE); + } + } + + @Override + public void onAnswered() { + AnswerHintFactory.increaseAnsweredCount(context); + } + + private float getDimension(@DimenRes int id) { + return context.getResources().getDimension(id); + } + + private static Animator createUniformScaleAnimator( + View target, + float original, + float begin, + float end, + long duration, + long delay, + Interpolator interpolator) { + float scaleBegin = begin / original; + float scaleEnd = end / original; + Animator scaleX = ObjectAnimator.ofFloat(target, View.SCALE_X, scaleBegin, scaleEnd); + Animator scaleY = ObjectAnimator.ofFloat(target, View.SCALE_Y, scaleBegin, scaleEnd); + scaleX.setDuration(duration); + scaleY.setDuration(duration); + scaleX.setInterpolator(interpolator); + scaleY.setInterpolator(interpolator); + AnimatorSet set = new AnimatorSet(); + set.play(scaleX).with(scaleY).after(delay); + return set; + } + + private static Animator createAlphaAnimator( + View target, float begin, float end, long duration, long delay, Interpolator interpolator) { + Animator alpha = ObjectAnimator.ofFloat(target, View.ALPHA, begin, end); + alpha.setDuration(duration); + alpha.setInterpolator(interpolator); + alpha.setStartDelay(delay); + return alpha; + } +} |