1 /* 2 * Copyright (C) 2016 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 androidx.transition; 18 19 import static org.hamcrest.core.Is.is; 20 import static org.hamcrest.core.IsEqual.equalTo; 21 import static org.junit.Assert.assertNotNull; 22 import static org.junit.Assert.assertThat; 23 24 import android.animation.Animator; 25 import android.animation.ObjectAnimator; 26 import android.support.test.annotation.UiThreadTest; 27 import android.support.test.filters.MediumTest; 28 import android.view.View; 29 import android.view.ViewGroup; 30 31 import androidx.annotation.NonNull; 32 import androidx.annotation.Nullable; 33 34 import org.junit.Before; 35 import org.junit.Test; 36 37 import java.util.Arrays; 38 39 @MediumTest 40 public class VisibilityTest extends BaseTest { 41 42 private View mView; 43 private ViewGroup mRoot; 44 45 @UiThreadTest 46 @Before 47 public void setUp() { 48 mRoot = rule.getActivity().getRoot(); 49 mView = new View(rule.getActivity()); 50 mRoot.addView(mView, new ViewGroup.LayoutParams(100, 100)); 51 } 52 53 @Test 54 public void testMode() { 55 final CustomVisibility visibility = new CustomVisibility(); 56 assertThat(visibility.getMode(), is(Visibility.MODE_IN | Visibility.MODE_OUT)); 57 visibility.setMode(Visibility.MODE_IN); 58 assertThat(visibility.getMode(), is(Visibility.MODE_IN)); 59 } 60 61 @Test 62 @UiThreadTest 63 public void testCustomVisibility() { 64 final CustomVisibility visibility = new CustomVisibility(); 65 assertThat(visibility.getName(), is(equalTo(CustomVisibility.class.getName()))); 66 assertNotNull(visibility.getTransitionProperties()); 67 68 // Capture start values 69 mView.setScaleX(0.5f); 70 final TransitionValues startValues = new TransitionValues(); 71 startValues.view = mView; 72 visibility.captureStartValues(startValues); 73 assertThat((float) startValues.values.get(CustomVisibility.PROPNAME_SCALE_X), is(0.5f)); 74 75 // Hide the view and capture end values 76 mView.setVisibility(View.GONE); 77 final TransitionValues endValues = new TransitionValues(); 78 endValues.view = mView; 79 visibility.captureEndValues(endValues); 80 81 // This should invoke onDisappear, not onAppear 82 ObjectAnimator animator = (ObjectAnimator) visibility 83 .createAnimator(mRoot, startValues, endValues); 84 assertNotNull(animator); 85 assertThat(animator.getPropertyName(), is(equalTo("scaleX"))); 86 87 // Jump to the end of the animation 88 animator.end(); 89 90 // This value confirms that onDisappear, not onAppear, was called 91 assertThat((float) animator.getAnimatedValue(), is(0.25f)); 92 } 93 94 @Test 95 @UiThreadTest 96 public void testCustomVisibility2() { 97 final CustomVisibility2 visibility = new CustomVisibility2(); 98 final TransitionValues startValues = new TransitionValues(); 99 startValues.view = mView; 100 visibility.captureStartValues(startValues); 101 mView.setVisibility(View.GONE); 102 final TransitionValues endValues = new TransitionValues(); 103 endValues.view = mView; 104 visibility.captureEndValues(endValues); 105 ObjectAnimator animator = (ObjectAnimator) visibility 106 .createAnimator(mRoot, startValues, endValues); 107 assertNotNull(animator); 108 109 // Jump to the end of the animation 110 animator.end(); 111 112 // This value confirms that onDisappear, not onAppear, was called 113 assertThat((float) animator.getAnimatedValue(), is(0.25f)); 114 } 115 116 /** 117 * A custom {@link Visibility} with 5-arg onAppear/Disappear 118 */ 119 public static class CustomVisibility extends Visibility { 120 121 static final String PROPNAME_SCALE_X = "customVisibility:scaleX"; 122 123 private static String[] sTransitionProperties; 124 125 @Nullable 126 @Override 127 public String[] getTransitionProperties() { 128 if (sTransitionProperties == null) { 129 String[] properties = super.getTransitionProperties(); 130 if (properties != null) { 131 sTransitionProperties = Arrays.copyOf(properties, properties.length + 1); 132 } else { 133 sTransitionProperties = new String[1]; 134 } 135 sTransitionProperties[sTransitionProperties.length - 1] = PROPNAME_SCALE_X; 136 } 137 return sTransitionProperties; 138 } 139 140 @Override 141 public void captureStartValues(@NonNull TransitionValues transitionValues) { 142 super.captureStartValues(transitionValues); 143 transitionValues.values.put(PROPNAME_SCALE_X, transitionValues.view.getScaleX()); 144 } 145 146 @Override 147 public Animator onAppear(ViewGroup sceneRoot, TransitionValues startValues, 148 int startVisibility, TransitionValues endValues, int endVisibility) { 149 if (startValues == null) { 150 return null; 151 } 152 float startScaleX = (float) startValues.values.get(PROPNAME_SCALE_X); 153 return ObjectAnimator.ofFloat(startValues.view, "scaleX", startScaleX, 0.75f); 154 } 155 156 @Override 157 public Animator onDisappear(ViewGroup sceneRoot, TransitionValues startValues, 158 int startVisibility, TransitionValues endValues, int endVisibility) { 159 if (startValues == null) { 160 return null; 161 } 162 float startScaleX = (float) startValues.values.get(PROPNAME_SCALE_X); 163 return ObjectAnimator.ofFloat(startValues.view, "scaleX", startScaleX, 0.25f); 164 } 165 166 } 167 168 /** 169 * A custom {@link Visibility} with 4-arg onAppear/Disappear 170 */ 171 public static class CustomVisibility2 extends Visibility { 172 173 static final String PROPNAME_SCALE_X = "customVisibility:scaleX"; 174 175 @Override 176 public void captureStartValues(@NonNull TransitionValues transitionValues) { 177 super.captureStartValues(transitionValues); 178 transitionValues.values.put(PROPNAME_SCALE_X, transitionValues.view.getScaleX()); 179 } 180 181 @Override 182 public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues, 183 TransitionValues endValues) { 184 float startScaleX = startValues == null ? 0.25f : 185 (float) startValues.values.get(PROPNAME_SCALE_X); 186 return ObjectAnimator.ofFloat(view, "scaleX", startScaleX, 0.75f); 187 } 188 189 @Override 190 public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues, 191 TransitionValues endValues) { 192 if (startValues == null) { 193 return null; 194 } 195 float startScaleX = (float) startValues.values.get(PROPNAME_SCALE_X); 196 return ObjectAnimator.ofFloat(view, "scaleX", startScaleX, 0.25f); 197 } 198 199 } 200 201 } 202