blob: 36b761f575f0ca5022cc723a19cf56e78a936dbf [file] [log] [blame]
/*
* 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.graphics.drawable.Drawable;
import android.support.annotation.DimenRes;
import android.support.annotation.NonNull;
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.ImageView;
import android.widget.TextView;
import com.android.dialer.common.Assert;
/**
* An Answer hint that animates a {@link Drawable} payload with animation similar to {@link
* DotAnswerHint}.
*/
public final class PawAnswerHint implements AnswerHint {
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_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 static final float IMAGE_SCALE = 1.5f;
private static final float FADE_SCALE = 2.0f;
private final Context context;
private final Drawable payload;
private final long puckUpDurationMillis;
private final long puckUpDelayMillis;
private View puck;
private View payloadView;
private View answerHintContainer;
private AnimatorSet answerGestureHintAnim;
public PawAnswerHint(
@NonNull Context context,
@NonNull Drawable payload,
long puckUpDurationMillis,
long puckUpDelayMillis) {
this.context = Assert.isNotNull(context);
this.payload = Assert.isNotNull(payload);
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.paw_hint, container, true);
answerHintContainer = view.findViewById(R.id.answer_hint_container);
payloadView = view.findViewById(R.id.paw_image);
hintText.setTextSize(
TypedValue.COMPLEX_UNIT_PX, context.getResources().getDimension(R.dimen.hint_text_size));
((ImageView) payloadView).setImageDrawable(payload);
}
@Override
public void onBounceStart() {
if (answerGestureHintAnim == null) {
answerGestureHintAnim = new AnimatorSet();
answerHintContainer.setY(puck.getY() + getDimension(R.dimen.hint_initial_offset));
Animator fadeIn = createFadeIn();
Animator swipeUp =
ObjectAnimator.ofFloat(
answerHintContainer,
View.TRANSLATION_Y,
puck.getY() - 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);
payloadView.setAlpha(0);
payloadView.setScaleX(1);
payloadView.setScaleY(1);
answerHintContainer.setY(puck.getY() + getDimension(R.dimen.hint_initial_offset));
answerHintContainer.setVisibility(View.VISIBLE);
}
});
}
answerGestureHintAnim.start();
}
private Animator createFadeIn() {
AnimatorSet set = new AnimatorSet();
set.play(createFadeInScaleAndAlpha(payloadView));
return set;
}
private static Animator createFadeInScaleAndAlpha(View target) {
Animator scale =
createUniformScaleAnimator(
target,
FADE_SCALE,
IMAGE_SCALE,
FADE_IN_DURATION_SCALE_MILLIS,
FADE_IN_DELAY_SCALE_MILLIS,
new LinearInterpolator());
Animator alpha =
createAlphaAnimator(
target,
0f,
1.0f,
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(payloadView, FADE_OUT_DELAY_SCALE_SMALL_MILLIS));
return set;
}
private static Animator createFadeOutScaleAndAlpha(View target, long scaleDelay) {
Animator scale =
createUniformScaleAnimator(
target,
IMAGE_SCALE,
FADE_SCALE,
FADE_OUT_DURATION_SCALE_MILLIS,
scaleDelay,
new LinearInterpolator());
Animator alpha =
createAlphaAnimator(
target,
1.0f,
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() {
// Do nothing
}
private float getDimension(@DimenRes int id) {
return context.getResources().getDimension(id);
}
private static Animator createUniformScaleAnimator(
View target,
float scaleBegin,
float scaleEnd,
long duration,
long delay,
Interpolator interpolator) {
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;
}
}