/*
 * 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 android.view;

import android.animation.TimeInterpolator;
import android.view.ViewPropertyAnimator.NameValuesHolder;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;

import com.android.internal.view.animation.FallbackLUTInterpolator;

import java.util.ArrayList;


This is a RenderThread driven backend for ViewPropertyAnimator.
/** * This is a RenderThread driven backend for ViewPropertyAnimator. */
class ViewPropertyAnimatorRT { private static final Interpolator sLinearInterpolator = new LinearInterpolator(); private final View mView; private RenderNodeAnimator mAnimators[] = new RenderNodeAnimator[RenderNodeAnimator.LAST_VALUE + 1]; ViewPropertyAnimatorRT(View view) { mView = view; }
Returns:true if ViewPropertyAnimatorRT handled the animation, false if ViewPropertyAnimator needs to handle it
/** * @return true if ViewPropertyAnimatorRT handled the animation, * false if ViewPropertyAnimator needs to handle it */
public boolean startAnimation(ViewPropertyAnimator parent) { cancelAnimators(parent.mPendingAnimations); if (!canHandleAnimator(parent)) { return false; } doStartAnimation(parent); return true; } public void cancelAll() { for (int i = 0; i < mAnimators.length; i++) { if (mAnimators[i] != null) { mAnimators[i].cancel(); mAnimators[i] = null; } } } private void doStartAnimation(ViewPropertyAnimator parent) { int size = parent.mPendingAnimations.size(); long startDelay = parent.getStartDelay(); long duration = parent.getDuration(); TimeInterpolator interpolator = parent.getInterpolator(); if (interpolator == null) { // Documented to be LinearInterpolator in ValueAnimator.setInterpolator interpolator = sLinearInterpolator; } if (!RenderNodeAnimator.isNativeInterpolator(interpolator)) { interpolator = new FallbackLUTInterpolator(interpolator, duration); } for (int i = 0; i < size; i++) { NameValuesHolder holder = parent.mPendingAnimations.get(i); int property = RenderNodeAnimator.mapViewPropertyToRenderProperty(holder.mNameConstant); final float finalValue = holder.mFromValue + holder.mDeltaValue; RenderNodeAnimator animator = new RenderNodeAnimator(property, finalValue); animator.setStartDelay(startDelay); animator.setDuration(duration); animator.setInterpolator(interpolator); animator.setTarget(mView); animator.start(); mAnimators[property] = animator; } parent.mPendingAnimations.clear(); } private boolean canHandleAnimator(ViewPropertyAnimator parent) { // TODO: Can we eliminate this entirely? // If RenderNode.animatorProperties() can be toggled to point at staging // instead then RNA can be used as the animators for software as well // as the updateListener fallback paths. If this can be toggled // at the top level somehow, combined with requiresUiRedraw, we could // ensure that RT does not self-animate, allowing for safe driving of // the animators from the UI thread using the same mechanisms // ViewPropertyAnimator does, just with everything sitting on a single // animator subsystem instead of multiple. if (parent.getUpdateListener() != null) { return false; } if (parent.getListener() != null) { // TODO support return false; } if (!mView.isHardwareAccelerated()) { // TODO handle this maybe? return false; } if (parent.hasActions()) { return false; } // Here goes nothing... return true; } private void cancelAnimators(ArrayList<NameValuesHolder> mPendingAnimations) { int size = mPendingAnimations.size(); for (int i = 0; i < size; i++) { NameValuesHolder holder = mPendingAnimations.get(i); int property = RenderNodeAnimator.mapViewPropertyToRenderProperty(holder.mNameConstant); if (mAnimators[property] != null) { mAnimators[property].cancel(); mAnimators[property] = null; } } } }