1 /* 2 * Copyright (C) 2022 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 17 package android.view.animation; 18 19 import android.content.Context; 20 import android.content.res.TypedArray; 21 import android.graphics.Insets; 22 import android.util.AttributeSet; 23 import android.view.WindowInsets; 24 25 /** 26 * An animation that controls the outset of an object. 27 * 28 * @hide 29 */ 30 public class ExtendAnimation extends Animation { 31 protected Insets mFromInsets = Insets.NONE; 32 protected Insets mToInsets = Insets.NONE; 33 34 private int mFromLeftType = ABSOLUTE; 35 private int mFromTopType = ABSOLUTE; 36 private int mFromRightType = ABSOLUTE; 37 private int mFromBottomType = ABSOLUTE; 38 39 private int mToLeftType = ABSOLUTE; 40 private int mToTopType = ABSOLUTE; 41 private int mToRightType = ABSOLUTE; 42 private int mToBottomType = ABSOLUTE; 43 44 private float mFromLeftValue; 45 private float mFromTopValue; 46 private float mFromRightValue; 47 private float mFromBottomValue; 48 49 private float mToLeftValue; 50 private float mToTopValue; 51 private float mToRightValue; 52 private float mToBottomValue; 53 54 /** 55 * Constructor used when an ExtendAnimation is loaded from a resource. 56 * 57 * @param context Application context to use 58 * @param attrs Attribute set from which to read values 59 */ ExtendAnimation(Context context, AttributeSet attrs)60 public ExtendAnimation(Context context, AttributeSet attrs) { 61 super(context, attrs); 62 63 TypedArray a = context.obtainStyledAttributes(attrs, 64 com.android.internal.R.styleable.ExtendAnimation); 65 66 Description d = Description.parseValue(a.peekValue( 67 com.android.internal.R.styleable.ExtendAnimation_fromExtendLeft), context); 68 mFromLeftType = d.type; 69 mFromLeftValue = d.value; 70 71 d = Description.parseValue(a.peekValue( 72 com.android.internal.R.styleable.ExtendAnimation_fromExtendTop), context); 73 mFromTopType = d.type; 74 mFromTopValue = d.value; 75 76 d = Description.parseValue(a.peekValue( 77 com.android.internal.R.styleable.ExtendAnimation_fromExtendRight), context); 78 mFromRightType = d.type; 79 mFromRightValue = d.value; 80 81 d = Description.parseValue(a.peekValue( 82 com.android.internal.R.styleable.ExtendAnimation_fromExtendBottom), context); 83 mFromBottomType = d.type; 84 mFromBottomValue = d.value; 85 86 87 d = Description.parseValue(a.peekValue( 88 com.android.internal.R.styleable.ExtendAnimation_toExtendLeft), context); 89 mToLeftType = d.type; 90 mToLeftValue = d.value; 91 92 d = Description.parseValue(a.peekValue( 93 com.android.internal.R.styleable.ExtendAnimation_toExtendTop), context); 94 mToTopType = d.type; 95 mToTopValue = d.value; 96 97 d = Description.parseValue(a.peekValue( 98 com.android.internal.R.styleable.ExtendAnimation_toExtendRight), context); 99 mToRightType = d.type; 100 mToRightValue = d.value; 101 102 d = Description.parseValue(a.peekValue( 103 com.android.internal.R.styleable.ExtendAnimation_toExtendBottom), context); 104 mToBottomType = d.type; 105 mToBottomValue = d.value; 106 107 a.recycle(); 108 } 109 110 /** 111 * Constructor to use when building an ExtendAnimation from code 112 * 113 * @param fromInsets the insets to animate from 114 * @param toInsets the insets to animate to 115 */ ExtendAnimation(Insets fromInsets, Insets toInsets)116 public ExtendAnimation(Insets fromInsets, Insets toInsets) { 117 if (fromInsets == null || toInsets == null) { 118 throw new RuntimeException("Expected non-null animation outsets"); 119 } 120 mFromLeftValue = -fromInsets.left; 121 mFromTopValue = -fromInsets.top; 122 mFromRightValue = -fromInsets.right; 123 mFromBottomValue = -fromInsets.bottom; 124 125 mToLeftValue = -toInsets.left; 126 mToTopValue = -toInsets.top; 127 mToRightValue = -toInsets.right; 128 mToBottomValue = -toInsets.bottom; 129 } 130 131 /** 132 * Constructor to use when building an ExtendAnimation from code 133 */ ExtendAnimation(int fromL, int fromT, int fromR, int fromB, int toL, int toT, int toR, int toB)134 public ExtendAnimation(int fromL, int fromT, int fromR, int fromB, 135 int toL, int toT, int toR, int toB) { 136 this(Insets.of(-fromL, -fromT, -fromR, -fromB), Insets.of(-toL, -toT, -toR, -toB)); 137 } 138 139 @Override applyTransformation(float it, Transformation tr)140 protected void applyTransformation(float it, Transformation tr) { 141 int l = mFromInsets.left + (int) ((mToInsets.left - mFromInsets.left) * it); 142 int t = mFromInsets.top + (int) ((mToInsets.top - mFromInsets.top) * it); 143 int r = mFromInsets.right + (int) ((mToInsets.right - mFromInsets.right) * it); 144 int b = mFromInsets.bottom + (int) ((mToInsets.bottom - mFromInsets.bottom) * it); 145 tr.setInsets(l, t, r, b); 146 } 147 148 @Override willChangeTransformationMatrix()149 public boolean willChangeTransformationMatrix() { 150 return false; 151 } 152 153 /** @hide */ 154 @Override 155 @WindowInsets.Side.InsetsSide getExtensionEdges()156 public int getExtensionEdges() { 157 return (mFromInsets.left < 0 || mToInsets.left < 0 ? WindowInsets.Side.LEFT : 0) 158 | (mFromInsets.right < 0 || mToInsets.right < 0 ? WindowInsets.Side.RIGHT : 0) 159 | (mFromInsets.top < 0 || mToInsets.top < 0 ? WindowInsets.Side.TOP : 0) 160 | (mFromInsets.bottom < 0 || mToInsets.bottom < 0 ? WindowInsets.Side.BOTTOM : 0); 161 } 162 163 @Override initialize(int width, int height, int parentWidth, int parentHeight)164 public void initialize(int width, int height, int parentWidth, int parentHeight) { 165 super.initialize(width, height, parentWidth, parentHeight); 166 // We remove any negative extension (i.e. positive insets) and set those to 0 167 mFromInsets = Insets.min(Insets.of( 168 -(int) resolveSize(mFromLeftType, mFromLeftValue, width, parentWidth), 169 -(int) resolveSize(mFromTopType, mFromTopValue, height, parentHeight), 170 -(int) resolveSize(mFromRightType, mFromRightValue, width, parentWidth), 171 -(int) resolveSize(mFromBottomType, mFromBottomValue, height, parentHeight) 172 ), Insets.NONE); 173 mToInsets = Insets.min(Insets.of( 174 -(int) resolveSize(mToLeftType, mToLeftValue, width, parentWidth), 175 -(int) resolveSize(mToTopType, mToTopValue, height, parentHeight), 176 -(int) resolveSize(mToRightType, mToRightValue, width, parentWidth), 177 -(int) resolveSize(mToBottomType, mToBottomValue, height, parentHeight) 178 ), Insets.NONE); 179 } 180 } 181