blob: ae78336347940543ce50598229aab3f7cc9876ca [file] [log] [blame]
Joshua Tsuji06785ab2020-06-08 11:18:40 -04001/*
2 * Copyright (C) 2020 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 */
16package com.android.systemui.bubbles.animation;
17
18import android.graphics.Matrix;
19
20import androidx.dynamicanimation.animation.DynamicAnimation;
21import androidx.dynamicanimation.animation.FloatPropertyCompat;
22
23/**
24 * Matrix whose scale properties can be animated using physics animations, via the {@link #SCALE_X}
25 * and {@link #SCALE_Y} FloatProperties.
26 *
27 * This is useful when you need to perform a scale animation with a pivot point, since pivot points
28 * are not supported by standard View scale operations but are supported by matrices.
29 *
30 * NOTE: DynamicAnimation assumes that all custom properties are denominated in pixels, and thus
31 * considers 1 to be the smallest user-visible change for custom properties. This means that if you
32 * animate {@link #SCALE_X} and {@link #SCALE_Y} to 3f, for example, the animation would have only
33 * three frames.
34 *
35 * To work around this, whenever animating to a desired scale value, animate to the value returned
36 * by {@link #getAnimatableValueForScaleFactor} instead. The SCALE_X and SCALE_Y properties will
37 * convert that (larger) value into the appropriate scale factor when scaling the matrix.
38 */
39public class AnimatableScaleMatrix extends Matrix {
40
41 /**
42 * The X value of the scale.
43 *
44 * NOTE: This must be set or animated to the value returned by
45 * {@link #getAnimatableValueForScaleFactor}, not the desired scale factor itself.
46 */
47 public static final FloatPropertyCompat<AnimatableScaleMatrix> SCALE_X =
48 new FloatPropertyCompat<AnimatableScaleMatrix>("matrixScaleX") {
49 @Override
50 public float getValue(AnimatableScaleMatrix object) {
51 return getAnimatableValueForScaleFactor(object.mScaleX);
52 }
53
54 @Override
55 public void setValue(AnimatableScaleMatrix object, float value) {
56 object.setScaleX(value * DynamicAnimation.MIN_VISIBLE_CHANGE_SCALE);
57 }
58 };
59
60 /**
61 * The Y value of the scale.
62 *
63 * NOTE: This must be set or animated to the value returned by
64 * {@link #getAnimatableValueForScaleFactor}, not the desired scale factor itself.
65 */
66 public static final FloatPropertyCompat<AnimatableScaleMatrix> SCALE_Y =
67 new FloatPropertyCompat<AnimatableScaleMatrix>("matrixScaleY") {
68 @Override
69 public float getValue(AnimatableScaleMatrix object) {
70 return getAnimatableValueForScaleFactor(object.mScaleY);
71 }
72
73 @Override
74 public void setValue(AnimatableScaleMatrix object, float value) {
75 object.setScaleY(value * DynamicAnimation.MIN_VISIBLE_CHANGE_SCALE);
76 }
77 };
78
79 private float mScaleX = 1f;
80 private float mScaleY = 1f;
81
82 private float mPivotX = 0f;
83 private float mPivotY = 0f;
84
85 /**
86 * Return the value to animate SCALE_X or SCALE_Y to in order to achieve the desired scale
87 * factor.
88 */
89 public static float getAnimatableValueForScaleFactor(float scale) {
90 return scale * (1f / DynamicAnimation.MIN_VISIBLE_CHANGE_SCALE);
91 }
92
93 @Override
94 public void setScale(float sx, float sy, float px, float py) {
95 mScaleX = sx;
96 mScaleY = sy;
97 mPivotX = px;
98 mPivotY = py;
99 super.setScale(mScaleX, mScaleY, mPivotX, mPivotY);
100 }
101
102 public void setScaleX(float scaleX) {
103 mScaleX = scaleX;
104 super.setScale(mScaleX, mScaleY, mPivotX, mPivotY);
105 }
106
107 public void setScaleY(float scaleY) {
108 mScaleY = scaleY;
109 super.setScale(mScaleX, mScaleY, mPivotX, mPivotY);
110 }
111
112 public void setPivotX(float pivotX) {
113 mPivotX = pivotX;
114 super.setScale(mScaleX, mScaleY, mPivotX, mPivotY);
115 }
116
117 public void setPivotY(float pivotY) {
118 mPivotY = pivotY;
119 super.setScale(mScaleX, mScaleY, mPivotX, mPivotY);
120 }
121
122 public float getScaleX() {
123 return mScaleX;
124 }
125
126 public float getScaleY() {
127 return mScaleY;
128 }
129
130 public float getPivotX() {
131 return mPivotX;
132 }
133
134 public float getPivotY() {
135 return mPivotY;
136 }
137}