blob: 74d970464108d23e37e5391045eb598ec663a102 [file] [log] [blame]
/*
* Copyright (C) 2020 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.systemui.car.hvac;
import static com.android.systemui.car.hvac.AnimatedTemperatureView.isHorizontal;
import static com.android.systemui.car.hvac.AnimatedTemperatureView.isLeft;
import android.annotation.NonNull;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.RotateAnimation;
import android.view.animation.TranslateAnimation;
import android.widget.TextSwitcher;
/**
* Controls animating TemperatureView's text
*/
class TemperatureTextAnimator {
private static final DecelerateInterpolator DECELERATE_INTERPOLATOR =
new DecelerateInterpolator();
private static final AccelerateDecelerateInterpolator ACCELERATE_DECELERATE_INTERPOLATOR =
new AccelerateDecelerateInterpolator();
private static final int ROTATION_DEGREES = 15;
private static final int DURATION_MILLIS = 200;
private AnimatedTemperatureView mParent;
private final TextSwitcher mTextSwitcher;
private final String mTempFormat;
private final int mPivotOffset;
private final CharSequence mMinText;
private final CharSequence mMaxText;
private Animation mTextInAnimationUp;
private Animation mTextOutAnimationUp;
private Animation mTextInAnimationDown;
private Animation mTextOutAnimationDown;
private Animation mTextFadeInAnimation;
private Animation mTextFadeOutAnimation;
private float mLastTemp = Float.NaN;
TemperatureTextAnimator(AnimatedTemperatureView parent, TextSwitcher textSwitcher,
String tempFormat, int pivotOffset,
CharSequence minText, CharSequence maxText) {
mParent = parent;
mTextSwitcher = textSwitcher;
mTempFormat = tempFormat;
mPivotOffset = pivotOffset;
mMinText = minText;
mMaxText = maxText;
mParent.addOnLayoutChangeListener(
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) ->
setupAnimations(mParent.getGravity()));
}
void setTemp(float temp) {
if (Float.isNaN(temp)) {
mTextSwitcher.setInAnimation(mTextFadeInAnimation);
mTextSwitcher.setOutAnimation(mTextFadeOutAnimation);
mTextSwitcher.setText("--");
mLastTemp = temp;
return;
}
boolean isMinValue = mParent.isMinValue(temp);
boolean isMaxValue = mParent.isMaxValue(temp);
if (Float.isNaN(mLastTemp)) {
mTextSwitcher.setInAnimation(mTextFadeInAnimation);
mTextSwitcher.setOutAnimation(mTextFadeOutAnimation);
} else if (!isMinValue && (isMaxValue || temp > mLastTemp)) {
mTextSwitcher.setInAnimation(mTextInAnimationUp);
mTextSwitcher.setOutAnimation(mTextOutAnimationUp);
} else {
mTextSwitcher.setInAnimation(mTextInAnimationDown);
mTextSwitcher.setOutAnimation(mTextOutAnimationDown);
}
CharSequence text;
if (isMinValue) {
text = mMinText;
} else if (isMaxValue) {
text = mMaxText;
} else {
text = String.format(mTempFormat, temp);
}
mTextSwitcher.setText(text);
mLastTemp = temp;
}
private void setupAnimations(int gravity) {
mTextFadeInAnimation = createFadeAnimation(true);
mTextFadeOutAnimation = createFadeAnimation(false);
if (!isHorizontal(gravity)) {
mTextInAnimationUp = createTranslateFadeAnimation(true, true);
mTextOutAnimationUp = createTranslateFadeAnimation(false, true);
mTextInAnimationDown = createTranslateFadeAnimation(true, false);
mTextOutAnimationDown = createTranslateFadeAnimation(false, false);
} else {
boolean isLeft = isLeft(gravity, mTextSwitcher.getLayoutDirection());
mTextInAnimationUp = createRotateFadeAnimation(true, isLeft, true);
mTextOutAnimationUp = createRotateFadeAnimation(false, isLeft, true);
mTextInAnimationDown = createRotateFadeAnimation(true, isLeft, false);
mTextOutAnimationDown = createRotateFadeAnimation(false, isLeft, false);
}
}
@NonNull
private Animation createFadeAnimation(boolean in) {
AnimationSet set = new AnimationSet(true);
AlphaAnimation alphaAnimation = new AlphaAnimation(in ? 0 : 1, in ? 1 : 0);
alphaAnimation.setDuration(DURATION_MILLIS);
set.addAnimation(new RotateAnimation(0, 0)); // Undo any previous rotation
set.addAnimation(alphaAnimation);
return set;
}
@NonNull
private Animation createTranslateFadeAnimation(boolean in, boolean up) {
AnimationSet set = new AnimationSet(true);
set.setInterpolator(ACCELERATE_DECELERATE_INTERPOLATOR);
set.setDuration(DURATION_MILLIS);
int fromYDelta = in ? (up ? 1 : -1) : 0;
int toYDelta = in ? 0 : (up ? -1 : 1);
set.addAnimation(
new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0,
Animation.RELATIVE_TO_SELF, fromYDelta, Animation.RELATIVE_TO_SELF,
toYDelta));
set.addAnimation(new AlphaAnimation(in ? 0 : 1, in ? 1 : 0));
return set;
}
@NonNull
private Animation createRotateFadeAnimation(boolean in, boolean isLeft, boolean up) {
AnimationSet set = new AnimationSet(true);
set.setInterpolator(DECELERATE_INTERPOLATOR);
set.setDuration(DURATION_MILLIS);
float degrees = isLeft == up ? -ROTATION_DEGREES : ROTATION_DEGREES;
int pivotX = isLeft ? -mPivotOffset : mParent.getWidth() + mPivotOffset;
set.addAnimation(
new RotateAnimation(in ? -degrees : 0f, in ? 0f : degrees, Animation.ABSOLUTE,
pivotX, Animation.ABSOLUTE, 0f));
set.addAnimation(new AlphaAnimation(in ? 0 : 1, in ? 1 : 0));
return set;
}
}