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 17e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Arakipackage android.support.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; 26e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Arakiimport static org.junit.Assert.assertThat; 27928ae3c90e1410c734136bb39d55517efc79714fYuichi Arakiimport static org.mockito.Matchers.any; 28928ae3c90e1410c734136bb39d55517efc79714fYuichi Arakiimport static org.mockito.Mockito.mock; 29928ae3c90e1410c734136bb39d55517efc79714fYuichi Arakiimport static org.mockito.Mockito.timeout; 30928ae3c90e1410c734136bb39d55517efc79714fYuichi Arakiimport static org.mockito.Mockito.verify; 31e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki 32e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Arakiimport android.animation.Animator; 33928ae3c90e1410c734136bb39d55517efc79714fYuichi Arakiimport android.animation.ObjectAnimator; 34928ae3c90e1410c734136bb39d55517efc79714fYuichi Arakiimport android.animation.ValueAnimator; 35928ae3c90e1410c734136bb39d55517efc79714fYuichi Arakiimport android.os.Build; 36928ae3c90e1410c734136bb39d55517efc79714fYuichi Arakiimport android.support.annotation.NonNull; 37928ae3c90e1410c734136bb39d55517efc79714fYuichi Arakiimport android.support.annotation.Nullable; 38928ae3c90e1410c734136bb39d55517efc79714fYuichi Arakiimport android.support.test.InstrumentationRegistry; 39e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Arakiimport android.support.test.annotation.UiThreadTest; 40754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport android.support.test.filters.MediumTest; 41e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Arakiimport android.view.View; 42e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Arakiimport android.view.ViewGroup; 43e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki 44e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Arakiimport org.junit.Before; 45e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Arakiimport org.junit.Test; 46e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki 4724797374d6c3370ab857f254e8e58248c41c3dd9Aurimas Liutikas@MediumTest 48e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Arakipublic class FadeTest extends BaseTest { 49e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki 50e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki private View mView; 51e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki private ViewGroup mRoot; 52e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki 5342e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas @UiThreadTest 54e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki @Before 55e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki public void setUp() { 5642e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas mRoot = rule.getActivity().getRoot(); 5742e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas mView = new View(rule.getActivity()); 5842e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas mRoot.addView(mView, new ViewGroup.LayoutParams(100, 100)); 59e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki } 60e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki 61e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki @Test 62a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki public void testMode() { 63a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki assertThat(Fade.IN, is(Visibility.MODE_IN)); 64a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki assertThat(Fade.OUT, is(Visibility.MODE_OUT)); 65a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki final Fade fade = new Fade(); 66a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki assertThat(fade.getMode(), is(Visibility.MODE_IN | Visibility.MODE_OUT)); 67a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki fade.setMode(Visibility.MODE_IN); 68a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki assertThat(fade.getMode(), is(Visibility.MODE_IN)); 69a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki } 70a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki 71a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki @Test 72e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki @UiThreadTest 73e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki public void testDisappear() { 74e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki final Fade fade = new Fade(); 75e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki final TransitionValues startValues = new TransitionValues(); 76e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki startValues.view = mView; 77e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki fade.captureStartValues(startValues); 78e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki mView.setVisibility(View.INVISIBLE); 79e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki final TransitionValues endValues = new TransitionValues(); 80e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki endValues.view = mView; 81e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki fade.captureEndValues(endValues); 82e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki Animator animator = fade.createAnimator(mRoot, startValues, endValues); 83e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki assertThat(animator, is(notNullValue())); 84e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki } 85e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki 86e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki @Test 87e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki @UiThreadTest 88e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki public void testAppear() { 89e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki mView.setVisibility(View.INVISIBLE); 90e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki final Fade fade = new Fade(); 91e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki final TransitionValues startValues = new TransitionValues(); 92e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki startValues.view = mView; 93e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki fade.captureStartValues(startValues); 94e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki mView.setVisibility(View.VISIBLE); 95e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki final TransitionValues endValues = new TransitionValues(); 96e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki endValues.view = mView; 97e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki fade.captureEndValues(endValues); 98e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki Animator animator = fade.createAnimator(mRoot, startValues, endValues); 99e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki assertThat(animator, is(notNullValue())); 100e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki } 101e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki 102e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki @Test 103e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki @UiThreadTest 104e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki public void testNoChange() { 105e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki final Fade fade = new Fade(); 106e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki final TransitionValues startValues = new TransitionValues(); 107e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki startValues.view = mView; 108e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki fade.captureStartValues(startValues); 109e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki final TransitionValues endValues = new TransitionValues(); 110e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki endValues.view = mView; 111e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki fade.captureEndValues(endValues); 112e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki Animator animator = fade.createAnimator(mRoot, startValues, endValues); 113e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki // No visibility change; no animation should happen 114e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki assertThat(animator, is(nullValue())); 115e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki } 116e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki 117928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki @Test 118928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki public void testFadeOutThenIn() throws Throwable { 119928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki // Fade out 120928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki final Runnable interrupt = mock(Runnable.class); 121928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki float[] valuesOut = new float[2]; 122928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki final InterruptibleFade fadeOut = new InterruptibleFade(Fade.MODE_OUT, interrupt, 123928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki valuesOut); 124928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki final Transition.TransitionListener listenerOut = mock(Transition.TransitionListener.class); 125928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki fadeOut.addListener(listenerOut); 126928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki changeVisibility(fadeOut, mRoot, mView, View.INVISIBLE); 127928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki verify(listenerOut, timeout(3000)).onTransitionStart(any(Transition.class)); 128928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 129928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki // The view is in the middle of fading out 130928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki verify(interrupt, timeout(3000)).run(); 131928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 132928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki // Fade in 133928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki float[] valuesIn = new float[2]; 134928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki final InterruptibleFade fadeIn = new InterruptibleFade(Fade.MODE_IN, null, valuesIn); 135928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki final Transition.TransitionListener listenerIn = mock(Transition.TransitionListener.class); 136928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki fadeIn.addListener(listenerIn); 137928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki changeVisibility(fadeIn, mRoot, mView, View.VISIBLE); 138928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki verify(listenerOut, timeout(3000)).onTransitionPause(any(Transition.class)); 139928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki verify(listenerIn, timeout(3000)).onTransitionStart(any(Transition.class)); 140928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki assertThat(valuesOut[1], allOf(greaterThan(0f), lessThan(1f))); 141928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki if (Build.VERSION.SDK_INT >= 19) { 142928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki // These won't match on API levels 18 and below due to lack of Animator pause. 143928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki assertEquals(valuesOut[1], valuesIn[0], 0.01f); 144928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 145928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 146928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki verify(listenerIn, timeout(3000)).onTransitionEnd(any(Transition.class)); 147928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki assertThat(mView.getVisibility(), is(View.VISIBLE)); 148928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki assertEquals(valuesIn[1], 1.f, 0.01f); 149928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 150928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 151928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki @Test 152928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki public void testFadeInThenOut() throws Throwable { 153928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki changeVisibility(null, mRoot, mView, View.INVISIBLE); 154928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki InstrumentationRegistry.getInstrumentation().waitForIdleSync(); 155928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 156928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki // Fade in 157928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki final Runnable interrupt = mock(Runnable.class); 158928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki float[] valuesIn = new float[2]; 159928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki final InterruptibleFade fadeIn = new InterruptibleFade(Fade.MODE_IN, interrupt, valuesIn); 160928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki final Transition.TransitionListener listenerIn = mock(Transition.TransitionListener.class); 161928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki fadeIn.addListener(listenerIn); 162928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki changeVisibility(fadeIn, mRoot, mView, View.VISIBLE); 163928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki verify(listenerIn, timeout(3000)).onTransitionStart(any(Transition.class)); 164928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 165928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki // The view is in the middle of fading in 166928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki verify(interrupt, timeout(3000)).run(); 167928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 168928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki // Fade out 169928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki float[] valuesOut = new float[2]; 170928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki final InterruptibleFade fadeOut = new InterruptibleFade(Fade.MODE_OUT, null, valuesOut); 171928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki final Transition.TransitionListener listenerOut = mock(Transition.TransitionListener.class); 172928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki fadeOut.addListener(listenerOut); 173928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki changeVisibility(fadeOut, mRoot, mView, View.INVISIBLE); 174928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki verify(listenerIn, timeout(3000)).onTransitionPause(any(Transition.class)); 175928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki verify(listenerOut, timeout(3000)).onTransitionStart(any(Transition.class)); 176928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki assertThat(valuesIn[1], allOf(greaterThan(0f), lessThan(1f))); 177928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki if (Build.VERSION.SDK_INT >= 19) { 178928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki // These won't match on API levels 18 and below due to lack of Animator pause. 179928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki assertEquals(valuesIn[1], valuesOut[0], 0.01f); 180928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 181928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 182928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki verify(listenerOut, timeout(3000)).onTransitionEnd(any(Transition.class)); 183928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki assertThat(mView.getVisibility(), is(View.INVISIBLE)); 184928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 185928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 186db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki @Test 187db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki public void testFadeWithAlpha() throws Throwable { 188db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki // Set the view alpha to 0.5 189db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki rule.runOnUiThread(new Runnable() { 190db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki @Override 191db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki public void run() { 192db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki mView.setAlpha(0.5f); 193db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki } 194db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki }); 195db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki // Fade out 196db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki final Fade fadeOut = new Fade(Fade.OUT); 197db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki final Transition.TransitionListener listenerOut = mock(Transition.TransitionListener.class); 198db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki fadeOut.addListener(listenerOut); 199db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki changeVisibility(fadeOut, mRoot, mView, View.INVISIBLE); 200db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki verify(listenerOut, timeout(3000)).onTransitionStart(any(Transition.class)); 201db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki verify(listenerOut, timeout(3000)).onTransitionEnd(any(Transition.class)); 202db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki // Fade in 203db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki final Fade fadeIn = new Fade(Fade.IN); 204db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki final Transition.TransitionListener listenerIn = mock(Transition.TransitionListener.class); 205db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki fadeIn.addListener(listenerIn); 206db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki changeVisibility(fadeIn, mRoot, mView, View.VISIBLE); 207db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki verify(listenerIn, timeout(3000)).onTransitionStart(any(Transition.class)); 208db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki verify(listenerIn, timeout(3000)).onTransitionEnd(any(Transition.class)); 209db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki // Confirm that the view still has the original alpha value 210db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki assertThat(mView.getVisibility(), is(View.VISIBLE)); 211db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki assertEquals(0.5f, mView.getAlpha(), 0.01f); 212db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki } 213db860514bf4c9aa50169d2c9964d83aec53dabecYuichi Araki 214928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki private void changeVisibility(final Fade fade, final ViewGroup container, final View target, 215928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki final int visibility) throws Throwable { 216928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki rule.runOnUiThread(new Runnable() { 217928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki @Override 218928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki public void run() { 219928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki if (fade != null) { 220928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki TransitionManager.beginDelayedTransition(container, fade); 221928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 222928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki target.setVisibility(visibility); 223928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 224928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki }); 225928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 226928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 227928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki /** 228928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki * A special version of {@link Fade} that runs a specified {@link Runnable} soon after the 229928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki * target starts fading in or out. 230928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki */ 231928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki private static class InterruptibleFade extends Fade { 232928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 233928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki static final float ALPHA_THRESHOLD = 0.2f; 234928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 235928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki float mInitialAlpha = -1; 236928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki Runnable mMiddle; 237928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki final float[] mAlphaValues; 238928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 239928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki InterruptibleFade(int mode, Runnable middle, float[] alphaValues) { 240928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki super(mode); 241928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki mMiddle = middle; 242928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki mAlphaValues = alphaValues; 243928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 244928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 245928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki @Nullable 246928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki @Override 247928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki public Animator createAnimator(@NonNull ViewGroup sceneRoot, 248928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki @Nullable final TransitionValues startValues, 249928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki @Nullable final TransitionValues endValues) { 250928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki final Animator animator = super.createAnimator(sceneRoot, startValues, endValues); 251928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki if (animator instanceof ObjectAnimator) { 252928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki ((ObjectAnimator) animator).addUpdateListener( 253928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki new ValueAnimator.AnimatorUpdateListener() { 254928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki @Override 255928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki public void onAnimationUpdate(ValueAnimator animation) { 256928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki final float alpha = (float) animation.getAnimatedValue(); 257928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki mAlphaValues[1] = alpha; 258928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki if (mInitialAlpha < 0) { 259928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki mInitialAlpha = alpha; 260928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki mAlphaValues[0] = mInitialAlpha; 261928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } else if (Math.abs(alpha - mInitialAlpha) > ALPHA_THRESHOLD) { 262928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki if (mMiddle != null) { 263928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki mMiddle.run(); 264928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki mMiddle = null; 265928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 266928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 267928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 268928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki }); 269928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 270928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki return animator; 271928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 272928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 273928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 274928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 275e73fed4be4cf678ea3828e20805ddffe73ae7ad0Yuichi Araki} 276