1e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki/* 2e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki * Copyright (C) 2016 The Android Open Source Project 3e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki * 4e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki * Licensed under the Apache License, Version 2.0 (the "License"); 5e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki * you may not use this file except in compliance with the License. 6e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki * You may obtain a copy of the License at 7e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki * 8e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki * http://www.apache.org/licenses/LICENSE-2.0 9e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki * 10e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki * Unless required by applicable law or agreed to in writing, software 11e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki * distributed under the License is distributed on an "AS IS" BASIS, 12e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki * See the License for the specific language governing permissions and 14e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki * limitations under the License. 15e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki */ 16e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki 17ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.transition; 18e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki 19928ae3c90e1410c734136bb39d55517efc79714fYuichi Arakiimport static org.hamcrest.CoreMatchers.allOf; 20e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Arakiimport static org.hamcrest.CoreMatchers.is; 21e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Arakiimport static org.hamcrest.CoreMatchers.notNullValue; 22e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Arakiimport static org.hamcrest.CoreMatchers.nullValue; 23928ae3c90e1410c734136bb39d55517efc79714fYuichi Arakiimport static org.hamcrest.Matchers.greaterThan; 24928ae3c90e1410c734136bb39d55517efc79714fYuichi Arakiimport static org.hamcrest.Matchers.lessThan; 25928ae3c90e1410c734136bb39d55517efc79714fYuichi Arakiimport static org.junit.Assert.assertEquals; 2612e03825887438734f86bb11cafe4939cc645236George Mountimport static org.junit.Assert.assertNotNull; 27e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Arakiimport static org.junit.Assert.assertThat; 28928ae3c90e1410c734136bb39d55517efc79714fYuichi Arakiimport static org.mockito.Matchers.any; 29928ae3c90e1410c734136bb39d55517efc79714fYuichi Arakiimport static org.mockito.Mockito.mock; 30928ae3c90e1410c734136bb39d55517efc79714fYuichi Arakiimport static org.mockito.Mockito.timeout; 31928ae3c90e1410c734136bb39d55517efc79714fYuichi Arakiimport static org.mockito.Mockito.verify; 32e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki 33e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Arakiimport android.animation.Animator; 34928ae3c90e1410c734136bb39d55517efc79714fYuichi Arakiimport android.animation.ObjectAnimator; 35928ae3c90e1410c734136bb39d55517efc79714fYuichi Arakiimport android.animation.ValueAnimator; 36928ae3c90e1410c734136bb39d55517efc79714fYuichi Arakiimport android.os.Build; 37928ae3c90e1410c734136bb39d55517efc79714fYuichi Arakiimport android.support.test.InstrumentationRegistry; 38e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Arakiimport android.support.test.annotation.UiThreadTest; 39754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport android.support.test.filters.MediumTest; 40e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Arakiimport android.view.View; 41e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Arakiimport android.view.ViewGroup; 42e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki 434d1d6a17310a57807dabb3f404715cfe43a90ed0Aurimas Liutikasimport androidx.annotation.NonNull; 444d1d6a17310a57807dabb3f404715cfe43a90ed0Aurimas Liutikasimport androidx.annotation.Nullable; 4512e03825887438734f86bb11cafe4939cc645236George Mountimport androidx.transition.test.R; 464d1d6a17310a57807dabb3f404715cfe43a90ed0Aurimas Liutikas 47e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Arakiimport org.junit.Before; 48e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Arakiimport org.junit.Test; 49e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki 5012e03825887438734f86bb11cafe4939cc645236George Mount 5124797374d6c3370ab857f254e8e58248c41c3dd9Aurimas Liutikas@MediumTest 52e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Arakipublic class FadeTest extends BaseTest { 53e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki 54e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki private View mView; 55e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki private ViewGroup mRoot; 56e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki 5742e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas @UiThreadTest 58e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki @Before 59e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki public void setUp() { 6042e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas mRoot = rule.getActivity().getRoot(); 6142e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas mView = new View(rule.getActivity()); 6242e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas mRoot.addView(mView, new ViewGroup.LayoutParams(100, 100)); 63e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki } 64e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki 65e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki @Test 66a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki public void testMode() { 67a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki assertThat(Fade.IN, is(Visibility.MODE_IN)); 68a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki assertThat(Fade.OUT, is(Visibility.MODE_OUT)); 69a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki final Fade fade = new Fade(); 70a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki assertThat(fade.getMode(), is(Visibility.MODE_IN | Visibility.MODE_OUT)); 71a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki fade.setMode(Visibility.MODE_IN); 72a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki assertThat(fade.getMode(), is(Visibility.MODE_IN)); 73a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki } 74a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki 75a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki @Test 76e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki @UiThreadTest 77e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki public void testDisappear() { 78e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki final Fade fade = new Fade(); 79e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki final TransitionValues startValues = new TransitionValues(); 80e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki startValues.view = mView; 81e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki fade.captureStartValues(startValues); 82e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki mView.setVisibility(View.INVISIBLE); 83e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki final TransitionValues endValues = new TransitionValues(); 84e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki endValues.view = mView; 85e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki fade.captureEndValues(endValues); 86e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki Animator animator = fade.createAnimator(mRoot, startValues, endValues); 87e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki assertThat(animator, is(notNullValue())); 88e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki } 89e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki 90e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki @Test 91e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki @UiThreadTest 92e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki public void testAppear() { 93e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki mView.setVisibility(View.INVISIBLE); 94e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki final Fade fade = new Fade(); 95e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki final TransitionValues startValues = new TransitionValues(); 96e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki startValues.view = mView; 97e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki fade.captureStartValues(startValues); 98e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki mView.setVisibility(View.VISIBLE); 99e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki final TransitionValues endValues = new TransitionValues(); 100e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki endValues.view = mView; 101e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki fade.captureEndValues(endValues); 102e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki Animator animator = fade.createAnimator(mRoot, startValues, endValues); 103e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki assertThat(animator, is(notNullValue())); 104e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki } 105e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki 106e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki @Test 107e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki @UiThreadTest 108e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki public void testNoChange() { 109e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki final Fade fade = new Fade(); 110e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki final TransitionValues startValues = new TransitionValues(); 111e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki startValues.view = mView; 112e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki fade.captureStartValues(startValues); 113e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki final TransitionValues endValues = new TransitionValues(); 114e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki endValues.view = mView; 115e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki fade.captureEndValues(endValues); 116e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki Animator animator = fade.createAnimator(mRoot, startValues, endValues); 117e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki // No visibility change; no animation should happen 118e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki assertThat(animator, is(nullValue())); 119e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki } 120e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki 121928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki @Test 122928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki public void testFadeOutThenIn() throws Throwable { 123928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki // Fade out 124928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki final Runnable interrupt = mock(Runnable.class); 125928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki float[] valuesOut = new float[2]; 126928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki final InterruptibleFade fadeOut = new InterruptibleFade(Fade.MODE_OUT, interrupt, 127928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki valuesOut); 128928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki final Transition.TransitionListener listenerOut = mock(Transition.TransitionListener.class); 129928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki fadeOut.addListener(listenerOut); 130928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki changeVisibility(fadeOut, mRoot, mView, View.INVISIBLE); 131928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki verify(listenerOut, timeout(3000)).onTransitionStart(any(Transition.class)); 132928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 133928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki // The view is in the middle of fading out 134928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki verify(interrupt, timeout(3000)).run(); 135928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 136928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki // Fade in 137928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki float[] valuesIn = new float[2]; 138928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki final InterruptibleFade fadeIn = new InterruptibleFade(Fade.MODE_IN, null, valuesIn); 139928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki final Transition.TransitionListener listenerIn = mock(Transition.TransitionListener.class); 140928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki fadeIn.addListener(listenerIn); 141928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki changeVisibility(fadeIn, mRoot, mView, View.VISIBLE); 142928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki verify(listenerOut, timeout(3000)).onTransitionPause(any(Transition.class)); 143928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki verify(listenerIn, timeout(3000)).onTransitionStart(any(Transition.class)); 144928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki assertThat(valuesOut[1], allOf(greaterThan(0f), lessThan(1f))); 14563f708a9f9b852d5aadafd9c9001634fc746b2c8Yuichi Araki if (Build.VERSION.SDK_INT >= 19 && fadeOut.mInitialAlpha >= 0) { 146928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki // These won't match on API levels 18 and below due to lack of Animator pause. 147928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki assertEquals(valuesOut[1], valuesIn[0], 0.01f); 148928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 149928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 150928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki verify(listenerIn, timeout(3000)).onTransitionEnd(any(Transition.class)); 151928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki assertThat(mView.getVisibility(), is(View.VISIBLE)); 152928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki assertEquals(valuesIn[1], 1.f, 0.01f); 153928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 154928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 155928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki @Test 156928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki public void testFadeInThenOut() throws Throwable { 157928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki changeVisibility(null, mRoot, mView, View.INVISIBLE); 158928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki InstrumentationRegistry.getInstrumentation().waitForIdleSync(); 159928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 160928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki // Fade in 161928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki final Runnable interrupt = mock(Runnable.class); 162928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki float[] valuesIn = new float[2]; 163928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki final InterruptibleFade fadeIn = new InterruptibleFade(Fade.MODE_IN, interrupt, valuesIn); 164928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki final Transition.TransitionListener listenerIn = mock(Transition.TransitionListener.class); 165928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki fadeIn.addListener(listenerIn); 166928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki changeVisibility(fadeIn, mRoot, mView, View.VISIBLE); 167928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki verify(listenerIn, timeout(3000)).onTransitionStart(any(Transition.class)); 168928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 169928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki // The view is in the middle of fading in 170928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki verify(interrupt, timeout(3000)).run(); 171928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 172928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki // Fade out 173928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki float[] valuesOut = new float[2]; 174928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki final InterruptibleFade fadeOut = new InterruptibleFade(Fade.MODE_OUT, null, valuesOut); 175928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki final Transition.TransitionListener listenerOut = mock(Transition.TransitionListener.class); 176928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki fadeOut.addListener(listenerOut); 177928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki changeVisibility(fadeOut, mRoot, mView, View.INVISIBLE); 178928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki verify(listenerIn, timeout(3000)).onTransitionPause(any(Transition.class)); 179928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki verify(listenerOut, timeout(3000)).onTransitionStart(any(Transition.class)); 180928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki assertThat(valuesIn[1], allOf(greaterThan(0f), lessThan(1f))); 18163f708a9f9b852d5aadafd9c9001634fc746b2c8Yuichi Araki if (Build.VERSION.SDK_INT >= 19 && fadeIn.mInitialAlpha >= 0) { 182928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki // These won't match on API levels 18 and below due to lack of Animator pause. 183928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki assertEquals(valuesIn[1], valuesOut[0], 0.01f); 184928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 185928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 186928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki verify(listenerOut, timeout(3000)).onTransitionEnd(any(Transition.class)); 187928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki assertThat(mView.getVisibility(), is(View.INVISIBLE)); 188928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 189928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 190db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki @Test 191db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki public void testFadeWithAlpha() throws Throwable { 192db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki // Set the view alpha to 0.5 193db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki rule.runOnUiThread(new Runnable() { 194db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki @Override 195db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki public void run() { 196db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki mView.setAlpha(0.5f); 197db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki } 198db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki }); 199db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki // Fade out 200db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki final Fade fadeOut = new Fade(Fade.OUT); 201db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki final Transition.TransitionListener listenerOut = mock(Transition.TransitionListener.class); 202db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki fadeOut.addListener(listenerOut); 203db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki changeVisibility(fadeOut, mRoot, mView, View.INVISIBLE); 204db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki verify(listenerOut, timeout(3000)).onTransitionStart(any(Transition.class)); 205db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki verify(listenerOut, timeout(3000)).onTransitionEnd(any(Transition.class)); 206db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki // Fade in 207db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki final Fade fadeIn = new Fade(Fade.IN); 208db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki final Transition.TransitionListener listenerIn = mock(Transition.TransitionListener.class); 209db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki fadeIn.addListener(listenerIn); 210db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki changeVisibility(fadeIn, mRoot, mView, View.VISIBLE); 211db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki verify(listenerIn, timeout(3000)).onTransitionStart(any(Transition.class)); 212db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki verify(listenerIn, timeout(3000)).onTransitionEnd(any(Transition.class)); 213db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki // Confirm that the view still has the original alpha value 214db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki assertThat(mView.getVisibility(), is(View.VISIBLE)); 215db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki assertEquals(0.5f, mView.getAlpha(), 0.01f); 216db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki } 217db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki 21812e03825887438734f86bb11cafe4939cc645236George Mount // After a transition, a transitioned view as part of a scene should not be removed 21912e03825887438734f86bb11cafe4939cc645236George Mount @Test 22012e03825887438734f86bb11cafe4939cc645236George Mount public void endVisibilityIsCorrect() throws Throwable { 22112e03825887438734f86bb11cafe4939cc645236George Mount final TransitionActivity activity = rule.getActivity(); 22212e03825887438734f86bb11cafe4939cc645236George Mount final Scene[] scenes = new Scene[2]; 22312e03825887438734f86bb11cafe4939cc645236George Mount rule.runOnUiThread(new Runnable() { 22412e03825887438734f86bb11cafe4939cc645236George Mount @Override 22512e03825887438734f86bb11cafe4939cc645236George Mount public void run() { 22612e03825887438734f86bb11cafe4939cc645236George Mount View view = activity.getLayoutInflater().inflate(R.layout.scene11, mRoot, false); 22712e03825887438734f86bb11cafe4939cc645236George Mount 22812e03825887438734f86bb11cafe4939cc645236George Mount scenes[0] = new Scene(mRoot, view); 22912e03825887438734f86bb11cafe4939cc645236George Mount scenes[0].enter(); 23012e03825887438734f86bb11cafe4939cc645236George Mount scenes[1] = Scene.getSceneForLayout(mRoot, R.layout.scene12, activity); 23112e03825887438734f86bb11cafe4939cc645236George Mount } 23212e03825887438734f86bb11cafe4939cc645236George Mount }); 23312e03825887438734f86bb11cafe4939cc645236George Mount 23412e03825887438734f86bb11cafe4939cc645236George Mount assertNotNull(activity.findViewById(R.id.redSquare)); 23512e03825887438734f86bb11cafe4939cc645236George Mount 23612e03825887438734f86bb11cafe4939cc645236George Mount // We don't really care how short the duration is, so let's make it really short 23712e03825887438734f86bb11cafe4939cc645236George Mount final Fade fade = new Fade(); 23812e03825887438734f86bb11cafe4939cc645236George Mount fade.setDuration(1); 23912e03825887438734f86bb11cafe4939cc645236George Mount Transition.TransitionListener listener = mock(Transition.TransitionListener.class); 24012e03825887438734f86bb11cafe4939cc645236George Mount fade.addListener(listener); 24112e03825887438734f86bb11cafe4939cc645236George Mount 24212e03825887438734f86bb11cafe4939cc645236George Mount rule.runOnUiThread(new Runnable() { 24312e03825887438734f86bb11cafe4939cc645236George Mount @Override 24412e03825887438734f86bb11cafe4939cc645236George Mount public void run() { 24512e03825887438734f86bb11cafe4939cc645236George Mount TransitionManager.go(scenes[1], fade); 24612e03825887438734f86bb11cafe4939cc645236George Mount } 24712e03825887438734f86bb11cafe4939cc645236George Mount }); 24812e03825887438734f86bb11cafe4939cc645236George Mount // should be much shorter than 1 second, but why worry about it? 24912e03825887438734f86bb11cafe4939cc645236George Mount verify(listener, timeout(1000)).onTransitionEnd(any(Transition.class)); 25012e03825887438734f86bb11cafe4939cc645236George Mount 25112e03825887438734f86bb11cafe4939cc645236George Mount assertNotNull(activity.findViewById(R.id.redSquare)); 25212e03825887438734f86bb11cafe4939cc645236George Mount 25312e03825887438734f86bb11cafe4939cc645236George Mount rule.runOnUiThread(new Runnable() { 25412e03825887438734f86bb11cafe4939cc645236George Mount @Override 25512e03825887438734f86bb11cafe4939cc645236George Mount public void run() { 25612e03825887438734f86bb11cafe4939cc645236George Mount TransitionManager.go(scenes[0], fade); 25712e03825887438734f86bb11cafe4939cc645236George Mount } 25812e03825887438734f86bb11cafe4939cc645236George Mount }); 25912e03825887438734f86bb11cafe4939cc645236George Mount verify(listener, timeout(1000)).onTransitionStart(any(Transition.class)); 26012e03825887438734f86bb11cafe4939cc645236George Mount assertNotNull(activity.findViewById(R.id.redSquare)); 26112e03825887438734f86bb11cafe4939cc645236George Mount } 26212e03825887438734f86bb11cafe4939cc645236George Mount 263928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki private void changeVisibility(final Fade fade, final ViewGroup container, final View target, 264928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki final int visibility) throws Throwable { 265928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki rule.runOnUiThread(new Runnable() { 266928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki @Override 267928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki public void run() { 268928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki if (fade != null) { 269928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki TransitionManager.beginDelayedTransition(container, fade); 270928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 271928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki target.setVisibility(visibility); 272928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 273928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki }); 274928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 275928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 276928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki /** 277928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki * A special version of {@link Fade} that runs a specified {@link Runnable} soon after the 278928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki * target starts fading in or out. 279928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki */ 280928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki private static class InterruptibleFade extends Fade { 281928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 282928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki static final float ALPHA_THRESHOLD = 0.2f; 283928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 284928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki float mInitialAlpha = -1; 285928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki Runnable mMiddle; 286928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki final float[] mAlphaValues; 287928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 288928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki InterruptibleFade(int mode, Runnable middle, float[] alphaValues) { 289928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki super(mode); 290928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki mMiddle = middle; 291928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki mAlphaValues = alphaValues; 292928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 293928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 294928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki @Nullable 295928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki @Override 296928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki public Animator createAnimator(@NonNull ViewGroup sceneRoot, 297928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki @Nullable final TransitionValues startValues, 298928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki @Nullable final TransitionValues endValues) { 299928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki final Animator animator = super.createAnimator(sceneRoot, startValues, endValues); 300928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki if (animator instanceof ObjectAnimator) { 301928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki ((ObjectAnimator) animator).addUpdateListener( 302928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki new ValueAnimator.AnimatorUpdateListener() { 303928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki @Override 304928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki public void onAnimationUpdate(ValueAnimator animation) { 305928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki final float alpha = (float) animation.getAnimatedValue(); 306928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki mAlphaValues[1] = alpha; 307928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki if (mInitialAlpha < 0) { 308928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki mInitialAlpha = alpha; 309928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki mAlphaValues[0] = mInitialAlpha; 310928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } else if (Math.abs(alpha - mInitialAlpha) > ALPHA_THRESHOLD) { 311928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki if (mMiddle != null) { 312928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki mMiddle.run(); 313928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki mMiddle = null; 314928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 315928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 316928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 317928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki }); 318928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 319928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki return animator; 320928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 321928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 322928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 323928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 324e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki} 325