blob: de96887db9fb4a0910deba889b8177263378ee75 [file] [log] [blame]
John Reck918988c2014-05-19 10:28:35 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view;
18
19import android.animation.TimeInterpolator;
20import android.view.ViewPropertyAnimator.NameValuesHolder;
John Recka0b13bd2014-07-01 08:34:47 -070021import android.view.animation.Interpolator;
22import android.view.animation.LinearInterpolator;
John Reck918988c2014-05-19 10:28:35 -070023
24import com.android.internal.view.animation.FallbackLUTInterpolator;
25
26import java.util.ArrayList;
27
28
29/**
30 * This is a RenderThread driven backend for ViewPropertyAnimator.
31 */
32class ViewPropertyAnimatorRT {
33
John Recka0b13bd2014-07-01 08:34:47 -070034 private static final Interpolator sLinearInterpolator = new LinearInterpolator();
35
John Reck918988c2014-05-19 10:28:35 -070036 private final View mView;
37
38 private RenderNodeAnimator mAnimators[] = new RenderNodeAnimator[RenderNodeAnimator.LAST_VALUE + 1];
39
40 ViewPropertyAnimatorRT(View view) {
41 mView = view;
42 }
43
44 /**
45 * @return true if ViewPropertyAnimatorRT handled the animation,
46 * false if ViewPropertyAnimator needs to handle it
47 */
48 public boolean startAnimation(ViewPropertyAnimator parent) {
49 cancelAnimators(parent.mPendingAnimations);
50 if (!canHandleAnimator(parent)) {
51 return false;
52 }
53 doStartAnimation(parent);
54 return true;
55 }
56
John Reck22184722014-06-20 07:19:30 -070057 public void cancelAll() {
58 for (int i = 0; i < mAnimators.length; i++) {
59 if (mAnimators[i] != null) {
60 mAnimators[i].cancel();
61 mAnimators[i] = null;
62 }
63 }
64 }
65
John Reck918988c2014-05-19 10:28:35 -070066 private void doStartAnimation(ViewPropertyAnimator parent) {
67 int size = parent.mPendingAnimations.size();
68
69 long startDelay = parent.getStartDelay();
70 long duration = parent.getDuration();
71 TimeInterpolator interpolator = parent.getInterpolator();
John Recka0b13bd2014-07-01 08:34:47 -070072 if (interpolator == null) {
73 // Documented to be LinearInterpolator in ValueAnimator.setInterpolator
74 interpolator = sLinearInterpolator;
75 }
John Reck918988c2014-05-19 10:28:35 -070076 if (!RenderNodeAnimator.isNativeInterpolator(interpolator)) {
77 interpolator = new FallbackLUTInterpolator(interpolator, duration);
78 }
79 for (int i = 0; i < size; i++) {
80 NameValuesHolder holder = parent.mPendingAnimations.get(i);
81 int property = RenderNodeAnimator.mapViewPropertyToRenderProperty(holder.mNameConstant);
82
John Reck44244ff2014-06-20 14:44:58 -070083 final float finalValue = holder.mFromValue + holder.mDeltaValue;
John Reck291161a2014-07-22 07:31:09 -070084 RenderNodeAnimator animator = new RenderNodeAnimator(property, finalValue);
John Reck918988c2014-05-19 10:28:35 -070085 animator.setStartDelay(startDelay);
86 animator.setDuration(duration);
87 animator.setInterpolator(interpolator);
88 animator.setTarget(mView);
89 animator.start();
John Reck44244ff2014-06-20 14:44:58 -070090
John Reck8d8af3c2014-07-01 15:23:45 -070091 mAnimators[property] = animator;
John Reck918988c2014-05-19 10:28:35 -070092 }
93
94 parent.mPendingAnimations.clear();
95 }
96
97 private boolean canHandleAnimator(ViewPropertyAnimator parent) {
98 // TODO: Can we eliminate this entirely?
99 // If RenderNode.animatorProperties() can be toggled to point at staging
100 // instead then RNA can be used as the animators for software as well
101 // as the updateListener fallback paths. If this can be toggled
102 // at the top level somehow, combined with requiresUiRedraw, we could
103 // ensure that RT does not self-animate, allowing for safe driving of
104 // the animators from the UI thread using the same mechanisms
105 // ViewPropertyAnimator does, just with everything sitting on a single
106 // animator subsystem instead of multiple.
107
108 if (parent.getUpdateListener() != null) {
109 return false;
110 }
111 if (parent.getListener() != null) {
112 // TODO support
113 return false;
114 }
115 if (!mView.isHardwareAccelerated()) {
116 // TODO handle this maybe?
117 return false;
118 }
119 if (parent.hasActions()) {
120 return false;
121 }
122 // Here goes nothing...
123 return true;
124 }
125
John Reck918988c2014-05-19 10:28:35 -0700126 private void cancelAnimators(ArrayList<NameValuesHolder> mPendingAnimations) {
127 int size = mPendingAnimations.size();
128 for (int i = 0; i < size; i++) {
129 NameValuesHolder holder = mPendingAnimations.get(i);
130 int property = RenderNodeAnimator.mapViewPropertyToRenderProperty(holder.mNameConstant);
131 if (mAnimators[property] != null) {
132 mAnimators[property].cancel();
133 mAnimators[property] = null;
134 }
135 }
136 }
137
138}