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