/*
* Copyright (C) 2014 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.google.android.apps.santatracker.map.cardstream;
import android.animation.TimeAnimator;
import android.annotation.TargetApi;
import android.os.Build;
import android.support.v17.leanback.R;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Interpolator;
/**
* Animators for highlighting behavior when an item gains focus.
*/
class TvFocusAnimator {
private static final int DURATION_MS = 150;
private void onItemFocused(View view, boolean hasFocus) {
view.setSelected(hasFocus);
getOrCreateAnimator(view).animateFocus(hasFocus, false);
}
void onInitializeView(View view) {
getOrCreateAnimator(view).animateFocus(false, true);
}
private FocusAnimator getOrCreateAnimator(View view) {
FocusAnimator animator = (FocusAnimator) view.getTag(R.id.lb_focus_animator);
if (animator == null) {
final float scale = view.getResources().getFraction(
R.fraction.lb_focus_zoom_factor_xsmall, 1, 1);
animator = new FocusAnimator(view, scale, DURATION_MS);
view.setTag(R.id.lb_focus_animator, animator);
}
return animator;
}
static final class FocusChangeListener implements View.OnFocusChangeListener {
final private TvFocusAnimator mAnimator;
FocusChangeListener(TvFocusAnimator animator) {
mAnimator = animator;
}
@Override
public void onFocusChange(View view, boolean hasFocus) {
mAnimator.onItemFocused(view, hasFocus);
}
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private static class FocusAnimator implements TimeAnimator.TimeListener {
private final View mView;
private final int mDuration;
private final float mScaleDiff;
private final TimeAnimator mAnimator = new TimeAnimator();
private final Interpolator mInterpolator = new AccelerateDecelerateInterpolator();
private float mFocusLevel = 0f;
private float mFocusLevelStart;
private float mFocusLevelDelta;
FocusAnimator(View view, float scale, int duration) {
mView = view;
mDuration = duration;
mScaleDiff = scale - 1f;
mAnimator.setTimeListener(this);
}
void animateFocus(boolean select, boolean immediate) {
endAnimation();
final float end = select ? 1 : 0;
if (immediate) {
setFocusLevel(end);
} else if (mFocusLevel != end) {
mFocusLevelStart = mFocusLevel;
mFocusLevelDelta = end - mFocusLevelStart;
mAnimator.start();
}
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
void setFocusLevel(float level) {
mFocusLevel = level;
float scale = 1f + mScaleDiff * level;
mView.setElevation(5 * scale);
mView.setScaleX(scale);
mView.setScaleY(scale);
}
void endAnimation() {
mAnimator.end();
}
@Override
public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) {
float fraction;
if (totalTime >= mDuration) {
fraction = 1;
mAnimator.end();
} else {
fraction = (float) (totalTime / (double) mDuration);
}
if (mInterpolator != null) {
fraction = mInterpolator.getInterpolation(fraction);
}
setFocusLevel(mFocusLevelStart + fraction * mFocusLevelDelta);
}
}
}