Merge "Baby steps"

This commit is contained in:
John Reck
2014-05-20 14:10:53 +00:00
committed by Android (Google) Code Review
6 changed files with 165 additions and 9 deletions

View File

@@ -48,6 +48,8 @@ public final class RenderNodeAnimator extends Animator {
public static final int Y = 9;
public static final int Z = 10;
public static final int ALPHA = 11;
// The last value in the enum, used for array size initialization
public static final int LAST_VALUE = ALPHA;
// Keep in sync with enum PaintFields in Animator.h
public static final int PAINT_STROKE_WIDTH = 0;
@@ -86,7 +88,7 @@ public final class RenderNodeAnimator extends Animator {
private boolean mStarted = false;
private boolean mFinished = false;
public int mapViewPropertyToRenderProperty(int viewProperty) {
public static int mapViewPropertyToRenderProperty(int viewProperty) {
return sViewPropertyAnimatorMap.get(viewProperty);
}
@@ -125,11 +127,15 @@ public final class RenderNodeAnimator extends Animator {
}
}
static boolean isNativeInterpolator(TimeInterpolator interpolator) {
return interpolator.getClass().isAnnotationPresent(HasNativeInterpolator.class);
}
private void applyInterpolator() {
if (mInterpolator == null) return;
long ni;
if (mInterpolator.getClass().isAnnotationPresent(HasNativeInterpolator.class)) {
if (isNativeInterpolator(mInterpolator)) {
ni = ((NativeInterpolatorFactory)mInterpolator).createNativeInterpolator();
} else {
long duration = nGetDuration(mNativePtr.get());

View File

@@ -19,6 +19,7 @@ package android.view;
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.animation.TimeInterpolator;
import android.os.Build;
import java.util.ArrayList;
import java.util.HashMap;
@@ -108,6 +109,11 @@ public class ViewPropertyAnimator {
*/
private ValueAnimator mTempValueAnimator;
/**
* A RenderThread-driven backend that may intercept startAnimation
*/
private ViewPropertyAnimatorRT mRTBackend;
/**
* This listener is the mechanism by which the underlying Animator causes changes to the
* properties currently being animated, as well as the cleanup after an animation is
@@ -227,7 +233,7 @@ public class ViewPropertyAnimator {
* values are used to calculate the animated value for a given animation fraction
* during the animation.
*/
private static class NameValuesHolder {
static class NameValuesHolder {
int mNameConstant;
float mFromValue;
float mDeltaValue;
@@ -247,6 +253,9 @@ public class ViewPropertyAnimator {
ViewPropertyAnimator(View view) {
mView = view;
view.ensureTransformationInfo();
if (view.getContext().getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.L) {
mRTBackend = new ViewPropertyAnimatorRT(view);
}
}
/**
@@ -371,6 +380,10 @@ public class ViewPropertyAnimator {
return this;
}
Animator.AnimatorListener getListener() {
return mListener;
}
/**
* Sets a listener for update events in the underlying ValueAnimator that runs
* the property animations. Note that the underlying animator is animating between
@@ -390,6 +403,10 @@ public class ViewPropertyAnimator {
return this;
}
ValueAnimator.AnimatorUpdateListener getUpdateListener() {
return mUpdateListener;
}
/**
* Starts the currently pending property animations immediately. Calling <code>start()</code>
* is optional because all animations start automatically at the next opportunity. However,
@@ -825,12 +842,22 @@ public class ViewPropertyAnimator {
return this;
}
boolean hasActions() {
return mPendingSetupAction != null
|| mPendingCleanupAction != null
|| mPendingOnStartAction != null
|| mPendingOnEndAction != null;
}
/**
* Starts the underlying Animator for a set of properties. We use a single animator that
* simply runs from 0 to 1, and then use that fractional value to set each property
* value accordingly.
*/
private void startAnimation() {
if (mRTBackend != null && mRTBackend.startAnimation(this)) {
return;
}
mView.setHasTransientState(true);
ValueAnimator animator = ValueAnimator.ofFloat(1.0f);
ArrayList<NameValuesHolder> nameValueList =

View File

@@ -0,0 +1,118 @@
/*
* 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 com.android.internal.view.animation.FallbackLUTInterpolator;
import java.util.ArrayList;
/**
* This is a RenderThread driven backend for ViewPropertyAnimator.
*/
class ViewPropertyAnimatorRT {
private final View mView;
private RenderNodeAnimator mAnimators[] = new RenderNodeAnimator[RenderNodeAnimator.LAST_VALUE + 1];
ViewPropertyAnimatorRT(View view) {
mView = view;
}
/**
* @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;
}
private void doStartAnimation(ViewPropertyAnimator parent) {
int size = parent.mPendingAnimations.size();
long startDelay = parent.getStartDelay();
long duration = parent.getDuration();
TimeInterpolator interpolator = parent.getInterpolator();
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);
RenderNodeAnimator animator = new RenderNodeAnimator(property, holder.mFromValue + holder.mDeltaValue);
animator.setStartDelay(startDelay);
animator.setDuration(duration);
animator.setInterpolator(interpolator);
animator.setTarget(mView);
animator.start();
}
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;
}
}
}
}

View File

@@ -24,10 +24,13 @@ import android.view.Choreographer;
* Interpolator that builds a lookup table to use. This is a fallback for
* building a native interpolator from a TimeInterpolator that is not marked
* with {@link HasNativeInterpolator}
*
* This implements TimeInterpolator to allow for easier interop with Animators
*/
@HasNativeInterpolator
public class FallbackLUTInterpolator implements NativeInterpolatorFactory {
public class FallbackLUTInterpolator implements NativeInterpolatorFactory, TimeInterpolator {
private TimeInterpolator mSourceInterpolator;
private final float mLut[];
/**
@@ -35,6 +38,7 @@ public class FallbackLUTInterpolator implements NativeInterpolatorFactory {
* interpolator creation
*/
public FallbackLUTInterpolator(TimeInterpolator interpolator, long duration) {
mSourceInterpolator = interpolator;
mLut = createLUT(interpolator, duration);
}
@@ -63,4 +67,9 @@ public class FallbackLUTInterpolator implements NativeInterpolatorFactory {
float[] lut = createLUT(interpolator, duration);
return NativeInterpolatorFactoryHelper.createLutInterpolator(lut);
}
@Override
public float getInterpolation(float input) {
return mSourceInterpolator.getInterpolation(input);
}
}

View File

@@ -1,7 +1,7 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_TAGS := tests
# Only compile source java files in this apk.
LOCAL_SRC_FILES := $(call all-java-files-under, src)

View File

@@ -4,10 +4,6 @@
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="18"
android:targetSdkVersion="18" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"