├── .gitignore ├── LICENSE ├── README.md ├── build.gradle ├── library(1.x) ├── CHANGELOG.md ├── build.gradle ├── gradle-mvn-push.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ ├── android │ │ └── util │ │ │ ├── FloatProperty.java │ │ │ └── IntProperty.java │ └── com │ │ └── transitionseverywhere │ │ ├── ArcMotion.java │ │ ├── AutoTransition.java │ │ ├── ChangeBounds.java │ │ ├── ChangeClipBounds.java │ │ ├── ChangeImageTransform.java │ │ ├── ChangeScroll.java │ │ ├── ChangeText.java │ │ ├── ChangeTransform.java │ │ ├── CircularPropagation.java │ │ ├── Crossfade.java │ │ ├── Explode.java │ │ ├── Fade.java │ │ ├── PathMotion.java │ │ ├── PathParser.java │ │ ├── PatternPathMotion.java │ │ ├── Recolor.java │ │ ├── Rotate.java │ │ ├── Scene.java │ │ ├── SidePropagation.java │ │ ├── Slide.java │ │ ├── Transition.java │ │ ├── TransitionInflater.java │ │ ├── TransitionManager.java │ │ ├── TransitionPropagation.java │ │ ├── TransitionSet.java │ │ ├── TransitionUtils.java │ │ ├── TransitionValues.java │ │ ├── TransitionValuesMaps.java │ │ ├── TranslationAnimationCreator.java │ │ ├── Visibility.java │ │ ├── VisibilityPropagation.java │ │ ├── extra │ │ ├── Scale.java │ │ └── TranslationTransition.java │ │ └── utils │ │ ├── AnimatorUtils.java │ │ ├── BasePointFAnimator.java │ │ ├── FloatProperty.java │ │ ├── IntProperty.java │ │ ├── MatrixUtils.java │ │ ├── PathAnimatorCompat.java │ │ ├── PointFAnimator.java │ │ ├── PointFProperty.java │ │ ├── RectEvaluator.java │ │ ├── ReflectionUtils.java │ │ ├── ViewGroupOverlayUtils.java │ │ ├── ViewGroupUtils.java │ │ ├── ViewOverlayPreJellybean.java │ │ ├── ViewOverlayUtils.java │ │ ├── ViewUtils.java │ │ ├── ViewUtilsLollipop.java │ │ └── ViewUtilsLollipopMr1.java │ └── res │ └── values │ ├── attrs.xml │ └── ids.xml ├── library ├── build.gradle ├── gradle-mvn-push.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ ├── android │ │ └── util │ │ │ ├── FloatProperty.java │ │ │ └── IntProperty.java │ └── com │ │ └── transitionseverywhere │ │ ├── ChangeText.java │ │ ├── Crossfade.java │ │ ├── Recolor.java │ │ ├── Rotate.java │ │ ├── extra │ │ ├── Scale.java │ │ └── Translation.java │ │ └── utils │ │ ├── FloatProperty.java │ │ ├── IntProperty.java │ │ └── TransitionUtils.java │ └── res │ └── values │ └── attrs.xml ├── sample ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── andkulikov │ │ └── transitionseverywhere │ │ ├── AutoTransitionSample.java │ │ ├── ChangeTextSample.java │ │ ├── CustomTransitionSample.java │ │ ├── ExplodeAndEpicenterExample.java │ │ ├── ImageTransformSample.java │ │ ├── InterpolatorDurationStartDelaySample.java │ │ ├── ListFragment.java │ │ ├── MainActivity.java │ │ ├── PathMotionSample.java │ │ ├── RecolorSample.java │ │ ├── RotateSample.java │ │ ├── ScaleSample.java │ │ ├── ScenesSample.java │ │ ├── SlideSample.java │ │ ├── TransitionNameSample.java │ │ └── VisibleToggleClickListener.java │ └── res │ ├── anim │ ├── fade_in.xml │ └── fade_out.xml │ ├── drawable-hdpi │ └── ic_add_black_48dp.png │ ├── drawable-nodpi │ └── girl.png │ ├── drawable-xhdpi │ └── ic_add_black_48dp.png │ ├── drawable-xxhdpi │ ├── ic_add_black_48dp.png │ └── ic_launcher.png │ ├── drawable-xxxhdpi │ └── ic_add_black_48dp.png │ ├── drawable │ └── oval.xml │ ├── layout │ ├── activity_main.xml │ ├── button.xml │ ├── explode_item.xml │ ├── fragment_autotransition.xml │ ├── fragment_change_text.xml │ ├── fragment_custom.xml │ ├── fragment_image_transform.xml │ ├── fragment_interpolator.xml │ ├── fragment_list.xml │ ├── fragment_names.xml │ ├── fragment_names_item.xml │ ├── fragment_path.xml │ ├── fragment_recolor.xml │ ├── fragment_rotate.xml │ ├── fragment_scale.xml │ ├── fragment_scenes.xml │ ├── fragment_slide.xml │ ├── list_item.xml │ ├── scene1.xml │ ├── scene2.xml │ ├── scene3.xml │ └── text.xml │ ├── transition │ ├── scene3_transition.xml │ └── scene3_transition_manager.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated files 2 | bin/ 3 | gen/ 4 | 5 | # Gradle files 6 | .gradle/ 7 | build/ 8 | gradle/ 9 | gradlew* 10 | 11 | # Local configuration file (sdk path, etc) 12 | *.properties 13 | *.iml 14 | 15 | # Proguard folder generated by Eclipse 16 | proguard/ 17 | 18 | # Log Files 19 | *.log 20 | 21 | # Idea Files 22 | .idea 23 | 24 | # Mac OS File 25 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Transitions Everywhere 2 | ============ 3 | Set of extra Transitions on top of [AndroidX Transitions Library][1]. 4 | 5 | About 6 | ============ 7 | [Article about transitions and library][2]
8 | Originally this library was a full backport of Android Platform's Transitions API.
9 | Then all the bug fixes from the library were ported into AndroidX Transitions (previously Support library).
10 | Now this lib has minSdk version 14 (Android 4.0 ICS) and consist of some transitions which are not a part of the official set: 11 | 1) Internal Transitions that was marked as @hide in the platform: Recolor, Rotate, ChangeText and Crossfade. 12 | 2) Two extra transitions: Scale and Translation.

13 | 14 | Quick start 15 | ============ 16 | 17 | This version should be used if you are specifying 29 (Q) as a `targetSdkVersion`: 18 | 19 | ```groovy 20 | dependencies { 21 | implementation "com.andkulikov:transitionseverywhere:2.1.0" 22 | } 23 | ``` 24 | Otherwise, if you specify 29 as `targetSdkVersion` some of the transitions will not work properly. Instead of the reflection calls this version uses the new public methods added in API Level 29. It is based on androidx.transition:transition:1.2.0. 25 | 26 | Previous version if you are not yet on 29 (Q) SDK: 27 | 28 | ```groovy 29 | dependencies { 30 | implementation "com.andkulikov:transitionseverywhere:2.0.0" 31 | } 32 | ``` 33 | This version is based on androidx.transition:transition:1.1.0. 34 | 35 | Migration from 1.x guide 36 | ============ 37 | 1) Migrate to AndroidX! Support libraries are not updating anymore, to get all the bug fixes you have to use AndroidX transitions. 38 | 2) Replace imports from com.transitionseverywhere. to androidx.transition. for all the classes which are a part of the AndroidX lib. 39 | 3) If you were using Transition.TransitionListenerAdapter class use TransitionListenerAdapter now. 40 | 4) Instead of TransitionManager.setTransitionName() use ViewCompat.setTransitionName(). 41 | 5) If you were inflating transitions via xml move your files from anim folder to transition and use android: namespace instead of app: 42 | 6) Some setters in AndroidX transitions are not following the builder pattern, please rewrite this usages with introducing a helper variable if you encounter the issue. 43 | 7) Instead of TranslationTransition use Translation. 44 | 45 | Articles about the version 1.x 46 | ============ 47 | [Article about transitions and library][2]
48 | [Russian version][3]
49 | Chinese: [version 1][5], [version 2][6]
50 | 51 | [Changelog for version 1.x][4] 52 | ============ 53 | 54 | [1]: https://developer.android.com/reference/androidx/transition/package-summary 55 | [2]: https://medium.com/@andkulikov/animate-all-the-things-transitions-in-android-914af5477d50 56 | [3]: http://habrahabr.ru/post/243363/ 57 | [4]: https://github.com/andkulikov/Transitions-Everywhere/blob/master/library(1.x)/CHANGELOG.md 58 | [5]: https://yanlu.me/animate-all-the-things-transitions-in-android/ 59 | [6]: http://www.jianshu.com/p/98f2ec280945 60 | [7]: https://medium.com/@andkulikov/support-library-for-transitions-overview-and-comparison-c41be713cf8c 61 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | jcenter() 4 | google() 5 | } 6 | dependencies { 7 | classpath 'com.android.tools.build:gradle:3.4.1' 8 | } 9 | 10 | project.ext { 11 | buildToolsVersion = "28.0.3" 12 | minSdkVersion = 14 13 | targetSdkVersion = 29 14 | 15 | versionName = "2.1.0" 16 | } 17 | } 18 | 19 | allprojects { 20 | repositories { 21 | jcenter() 22 | google() 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /library(1.x)/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Change log for 1.x versions 2 | ============ 3 | 4 | 1.8.1
5 | Bug fixes for Crossfade and Recolor transitions. Thanks to [evant][8] and [DummyCo][9] 6 | 7 | 1.8.0
8 | Provide @NonNull and @Nullable annotations for all the methods to make the library more Kotlin friendly 9 | 10 | 1.7.9
11 | Fix bug with typo in restoring paused Visibility transition when it is using an overlay 12 | 13 | 1.7.8
14 | Fix for ChangeBounds sometimes not applying the latest values. Thanks to [lukaville][7] 15 | 16 | 1.7.7
17 | Fix version resolving issue when use together with the latest suppport libs 18 | 19 | 1.7.6
20 | Fix for the case when Visibility transition is removing the view from the previous scene. [Framework bug for it][6] 21 | 22 | 1.7.4, 1.7.5
23 | Fixes for color change in ChangeText. Thanks to [droidluv][4] and [passsy][5] 24 | 25 | 1.7.3
26 | Fix for TranslationTransition, fix for Visibility transition cancelation when it is using an overlay 27 | 28 | 1.7.1, 1.7.2
29 | Npe fix, WindowId backport, update PathParser version 30 | 31 | 1.7.0
32 | Bug fix for rare NPE. Thanks to [TealOcean][3] 33 | 34 | 1.6.9
35 | Bug fix for Scenes when we pass null transition 36 | 37 | 1.6.8
38 | Bug fix for Recolor. Thanks to [twyatt][2] 39 | 40 | 1.6.7
41 | Merge with Android 7.0. Some internal improvements 42 | 43 | 1.6.5
44 | Optimizations for ChangeBounds and Fade 45 | 46 | 1.6.4
47 | Bug fix. Thanks to [raycoarana][1] 48 | 49 | 1.6.3
50 | Hidden transitions are moved in the main package. Proguard rules are removed. Some internal fixes. 51 | 52 | 1.6.2
53 | Fixed issue with incorrect disappearing when set of more than one Visibility transitions animates the same view 54 |
Added two "extra" transitions: Scale (for scaled appearing & disappearing) and TranslationTransition (animates changes of translationX and translationY) 55 | 56 | 1.6.0
57 | Merge with final Android Marshmallow SDK
58 | PathMotion aka Curved motion is backported!
59 | Bug fixes and performance optimizations. 60 | 61 | 1.5.0
62 | Merge with Android M Preview 2
63 | Migrate to new library package name and maven artifact id:
64 | Please update imports in your classes from `android.transitions.everywhere.*` to `com.transitionseverywhere`
65 | And gradle dependency from `com.github.andkulikov:transitions-everywhere` to `com.andkulikov:transitionseverywhere`
66 | 67 | 1.4.0
68 | Merge with Android M Preview sources. 69 | 70 | 1.3.1 - 1.3.2
71 | Bug fixes. 72 | 73 | 1.3.0
74 | Merge with changes from Android 5.1. 75 | 76 | 1.2.0 - 1.2.2
77 | Bug fixes. 78 | 79 | 1.1.0
80 | Port of new transitions from Android 5.0 Lollipop 81 | 82 | 1.0.0
83 | First release. This library is a backport of [Android Transitions API][10]. Animations backported to Android 4.0+. API compatible with Android 2.3+ 84 | 85 | [1]: https://github.com/raycoarana 86 | [2]: https://github.com/twyatt 87 | [3]: https://github.com/TealOcean 88 | [4]: https://github.com/droidluv 89 | [5]: https://github.com/passsy 90 | [6]: https://issuetracker.google.com/issues/65688271 91 | [7]: https://github.com/lukaville 92 | [8]: https://github.com/evant 93 | [9]: https://github.com/DummyCo 94 | [10]: http://developer.android.com/reference/android/transition/package-summary.html 95 | -------------------------------------------------------------------------------- /library(1.x)/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 28 5 | buildToolsVersion parent.ext.buildToolsVersion 6 | 7 | defaultConfig { 8 | minSdkVersion 9 9 | targetSdkVersion 28 10 | versionCode 1 11 | versionName "1.8.1" 12 | } 13 | } 14 | 15 | dependencies { 16 | implementation ('com.android.support:support-annotations:24.2.0') 17 | implementation ('com.android.support:support-compat:24.2.0') 18 | } 19 | 20 | //apply from: rootProject.file('library/gradle-mvn-push.gradle') -------------------------------------------------------------------------------- /library(1.x)/gradle-mvn-push.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'maven' 2 | apply plugin: 'signing' 3 | 4 | def isReleaseBuild() { 5 | return VERSION_NAME.contains("SNAPSHOT") == false 6 | } 7 | 8 | def getReleaseRepositoryUrl() { 9 | return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL 10 | : "https://oss.sonatype.org/service/local/staging/deploy/maven2/" 11 | } 12 | 13 | def getSnapshotRepositoryUrl() { 14 | return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL 15 | : "https://oss.sonatype.org/content/repositories/snapshots/" 16 | } 17 | 18 | def getRepositoryUsername() { 19 | return hasProperty('SONATYPE_NEXUS_USERNAME') ? SONATYPE_NEXUS_USERNAME : "" 20 | } 21 | 22 | def getRepositoryPassword() { 23 | return hasProperty('SONATYPE_NEXUS_PASSWORD') ? SONATYPE_NEXUS_PASSWORD : "" 24 | } 25 | 26 | afterEvaluate { project -> 27 | uploadArchives { 28 | repositories { 29 | mavenDeployer { 30 | beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } 31 | 32 | pom.groupId = GROUP 33 | pom.artifactId = POM_ARTIFACT_ID 34 | pom.version = VERSION_NAME 35 | 36 | repository(url: getReleaseRepositoryUrl()) { 37 | authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) 38 | } 39 | snapshotRepository(url: getSnapshotRepositoryUrl()) { 40 | authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) 41 | } 42 | 43 | pom.project { 44 | name POM_NAME 45 | packaging POM_PACKAGING 46 | description POM_DESCRIPTION 47 | url POM_URL 48 | 49 | scm { 50 | url POM_SCM_URL 51 | connection POM_SCM_CONNECTION 52 | developerConnection POM_SCM_DEV_CONNECTION 53 | } 54 | 55 | licenses { 56 | license { 57 | name POM_LICENCE_NAME 58 | url POM_LICENCE_URL 59 | distribution POM_LICENCE_DIST 60 | } 61 | } 62 | 63 | developers { 64 | developer { 65 | id POM_DEVELOPER_ID 66 | name POM_DEVELOPER_NAME 67 | } 68 | } 69 | } 70 | 71 | } 72 | } 73 | } 74 | 75 | signing { 76 | required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") } 77 | sign configurations.archives 78 | } 79 | 80 | task androidJavadocs(type: Javadoc) { 81 | source = android.sourceSets.main.java.srcDirs 82 | ext.androidJar = "${android.sdkDirectory}/platforms/${android.compileSdkVersion}/android.jar" 83 | classpath += files(ext.androidJar) 84 | } 85 | 86 | task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) { 87 | classifier = 'javadoc' 88 | from androidJavadocs.destinationDir 89 | } 90 | 91 | task androidSourcesJar(type: Jar) { 92 | classifier = 'sources' 93 | from android.sourceSets.main.java.sourceFiles 94 | } 95 | 96 | if (JavaVersion.current().isJava8Compatible()) { 97 | allprojects { 98 | tasks.withType(Javadoc) { 99 | options.addStringOption('Xdoclint:none', '-quiet') 100 | } 101 | } 102 | } 103 | 104 | artifacts { 105 | archives androidSourcesJar 106 | archives androidJavadocsJar 107 | } 108 | } -------------------------------------------------------------------------------- /library(1.x)/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /library(1.x)/src/main/java/android/util/FloatProperty.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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 | package android.util; 17 | 18 | import android.annotation.SuppressLint; 19 | import android.annotation.TargetApi; 20 | import android.os.Build; 21 | import android.support.annotation.NonNull; 22 | import android.support.annotation.Nullable; 23 | 24 | /** 25 | * Dummy class. Permits to extend same hidden class from android framework. 26 | * Actually in runtime will be used class from android framework and ObjectAnimator 27 | * optimizations for FloatProperty will be applied. 28 | * 29 | * Created by Andrey Kulikov on 18.08.15. 30 | */ 31 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 32 | public abstract class FloatProperty extends Property { 33 | 34 | public FloatProperty(@Nullable String name) { 35 | super(Float.class, name); 36 | } 37 | 38 | public abstract void setValue(@NonNull T object, float value); 39 | 40 | @SuppressLint("NewApi") 41 | @Override 42 | final public void set(@NonNull T object, @NonNull Float value) { 43 | setValue(object, value); 44 | } 45 | 46 | @Override 47 | @NonNull 48 | public abstract Float get(@NonNull T object); 49 | 50 | } 51 | -------------------------------------------------------------------------------- /library(1.x)/src/main/java/android/util/IntProperty.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Andrey Kulikov (andkulikov@gmail.com) 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 | /* 9 | * Copyright (C) 2011 The Android Open Source Project 10 | * 11 | * Licensed under the Apache License, Version 2.0 (the "License"); 12 | * you may not use this file except in compliance with the License. 13 | * You may obtain a copy of the License at 14 | * 15 | * http://www.apache.org/licenses/LICENSE-2.0 16 | * 17 | * Unless required by applicable law or agreed to in writing, software 18 | * distributed under the License is distributed on an "AS IS" BASIS, 19 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | * See the License for the specific language governing permissions and 21 | * limitations under the License. 22 | */ 23 | package android.util; 24 | 25 | import android.annotation.SuppressLint; 26 | import android.annotation.TargetApi; 27 | import android.os.Build; 28 | import android.support.annotation.NonNull; 29 | import android.support.annotation.Nullable; 30 | 31 | /** 32 | * Dummy class. Permits to extend same hidden class from android framework. 33 | * Actually in runtime will be used class from android framework and ObjectAnimator 34 | * optimizations for IntProperty will be applied. 35 | * 36 | * Created by Andrey Kulikov on 18.08.15. 37 | */ 38 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 39 | public abstract class IntProperty extends Property { 40 | 41 | public IntProperty(@Nullable String name) { 42 | super(Integer.class, name); 43 | } 44 | 45 | public abstract void setValue(@NonNull T object, int value); 46 | 47 | @SuppressLint("NewApi") 48 | @Override 49 | final public void set(@NonNull T object, @NonNull Integer value) { 50 | setValue(object, value); 51 | } 52 | 53 | @Override 54 | @NonNull 55 | public abstract Integer get(@NonNull T object); 56 | 57 | } 58 | -------------------------------------------------------------------------------- /library(1.x)/src/main/java/com/transitionseverywhere/AutoTransition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 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 com.transitionseverywhere; 18 | 19 | import android.content.Context; 20 | import android.support.annotation.NonNull; 21 | import android.util.AttributeSet; 22 | 23 | /** 24 | * Utility class for creating a default transition that automatically fades, 25 | * moves, and resizes views during a scene change. 26 | *

27 | *

An AutoTransition can be described in a resource file by using the 28 | * tag autoTransition, along with the other standard 29 | * attributes of {@link com.transitionseverywhere.R.styleable#Transition}.

30 | */ 31 | public class AutoTransition extends TransitionSet { 32 | 33 | /** 34 | * Constructs an AutoTransition object, which is a TransitionSet which 35 | * first fades out disappearing targets, then moves and resizes existing 36 | * targets, and finally fades in appearing targets. 37 | */ 38 | public AutoTransition() { 39 | init(); 40 | } 41 | 42 | public AutoTransition(@NonNull Context context, @NonNull AttributeSet attrs) { 43 | super(context, attrs); 44 | init(); 45 | } 46 | 47 | private void init() { 48 | setOrdering(ORDERING_SEQUENTIAL); 49 | addTransition(new Fade(Fade.OUT)). 50 | addTransition(new ChangeBounds()). 51 | addTransition(new Fade(Fade.IN)); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /library(1.x)/src/main/java/com/transitionseverywhere/ChangeClipBounds.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 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 | package com.transitionseverywhere; 17 | 18 | import android.animation.Animator; 19 | import android.animation.ObjectAnimator; 20 | import android.annotation.TargetApi; 21 | import android.content.Context; 22 | import android.graphics.Rect; 23 | import android.os.Build; 24 | import android.support.annotation.NonNull; 25 | import android.support.annotation.Nullable; 26 | import android.util.AttributeSet; 27 | import android.util.Property; 28 | import android.view.View; 29 | import android.view.ViewGroup; 30 | 31 | import com.transitionseverywhere.utils.RectEvaluator; 32 | import com.transitionseverywhere.utils.ViewUtils; 33 | 34 | /** 35 | * ChangeClipBounds captures the {@link android.view.View#getClipBounds()} before and after the 36 | * scene change and animates those changes during the transition. 37 | */ 38 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 39 | public class ChangeClipBounds extends Transition { 40 | 41 | private static final String TAG = "ChangeTransform"; 42 | 43 | private static final String PROPNAME_CLIP = "android:clipBounds:clip"; 44 | private static final String PROPNAME_BOUNDS = "android:clipBounds:bounds"; 45 | 46 | private static final String[] sTransitionProperties = { 47 | PROPNAME_CLIP, 48 | }; 49 | 50 | @Nullable 51 | public static final Property VIEW_CLIP_BOUNDS; 52 | 53 | static { 54 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 55 | VIEW_CLIP_BOUNDS = new Property(Rect.class, "clipBounds") { 56 | 57 | @Override 58 | public void set(@NonNull View object, Rect value) { 59 | ViewUtils.setClipBounds(object, value); 60 | } 61 | 62 | @Nullable 63 | @Override 64 | public Rect get(@NonNull View object) { 65 | return ViewUtils.getClipBounds(object); 66 | } 67 | 68 | }; 69 | } else { 70 | VIEW_CLIP_BOUNDS = null; 71 | } 72 | } 73 | 74 | public ChangeClipBounds() {} 75 | 76 | public ChangeClipBounds(@NonNull Context context, @NonNull AttributeSet attrs) { 77 | super(context, attrs); 78 | } 79 | 80 | @Nullable 81 | @Override 82 | public String[] getTransitionProperties() { 83 | return sTransitionProperties; 84 | } 85 | 86 | private void captureValues(TransitionValues values) { 87 | View view = values.view; 88 | if (view.getVisibility() == View.GONE) { 89 | return; 90 | } 91 | 92 | Rect clip = ViewUtils.getClipBounds(view); 93 | values.values.put(PROPNAME_CLIP, clip); 94 | if (clip == null) { 95 | Rect bounds = new Rect(0, 0, view.getWidth(), view.getHeight()); 96 | values.values.put(PROPNAME_BOUNDS, bounds); 97 | } 98 | } 99 | 100 | @Override 101 | public void captureStartValues(@NonNull TransitionValues transitionValues) { 102 | captureValues(transitionValues); 103 | } 104 | 105 | @Override 106 | public void captureEndValues(@NonNull TransitionValues transitionValues) { 107 | captureValues(transitionValues); 108 | } 109 | 110 | @Nullable 111 | @Override 112 | public Animator createAnimator(@NonNull final ViewGroup sceneRoot, @Nullable TransitionValues startValues, 113 | @Nullable TransitionValues endValues) { 114 | if (startValues == null || endValues == null 115 | || !startValues.values.containsKey(PROPNAME_CLIP) 116 | || !endValues.values.containsKey(PROPNAME_CLIP)) { 117 | return null; 118 | } 119 | Rect start = (Rect) startValues.values.get(PROPNAME_CLIP); 120 | Rect end = (Rect) endValues.values.get(PROPNAME_CLIP); 121 | if (start == null && end == null) { 122 | return null; // No animation required since there is no clip. 123 | } 124 | 125 | if (start == null) { 126 | start = (Rect) startValues.values.get(PROPNAME_BOUNDS); 127 | } else if (end == null) { 128 | end = (Rect) endValues.values.get(PROPNAME_BOUNDS); 129 | } 130 | if (start.equals(end)) { 131 | return null; 132 | } 133 | 134 | ViewUtils.setClipBounds(endValues.view, start); 135 | RectEvaluator evaluator = new RectEvaluator(new Rect()); 136 | return ObjectAnimator.ofObject(endValues.view, VIEW_CLIP_BOUNDS, evaluator, start, end); 137 | } 138 | 139 | } 140 | -------------------------------------------------------------------------------- /library(1.x)/src/main/java/com/transitionseverywhere/ChangeScroll.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 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 com.transitionseverywhere; 18 | 19 | import android.animation.Animator; 20 | import android.animation.ObjectAnimator; 21 | import android.annotation.TargetApi; 22 | import android.content.Context; 23 | import android.os.Build; 24 | import android.support.annotation.NonNull; 25 | import android.support.annotation.Nullable; 26 | import android.util.AttributeSet; 27 | import android.view.View; 28 | import android.view.ViewGroup; 29 | 30 | /** 31 | * This transition captures the scroll properties of targets before and after 32 | * the scene change and animates any changes. 33 | */ 34 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 35 | public class ChangeScroll extends Transition { 36 | 37 | private static final String PROPNAME_SCROLL_X = "android:changeScroll:x"; 38 | private static final String PROPNAME_SCROLL_Y = "android:changeScroll:y"; 39 | 40 | public ChangeScroll() {} 41 | 42 | public ChangeScroll(@NonNull Context context, @NonNull AttributeSet attrs) { 43 | super(context, attrs); 44 | } 45 | 46 | @Override 47 | public void captureStartValues(@NonNull TransitionValues transitionValues) { 48 | captureValues(transitionValues); 49 | } 50 | 51 | @Override 52 | public void captureEndValues(@NonNull TransitionValues transitionValues) { 53 | captureValues(transitionValues); 54 | } 55 | 56 | private void captureValues(TransitionValues transitionValues) { 57 | transitionValues.values.put(PROPNAME_SCROLL_X, transitionValues.view.getScrollX()); 58 | transitionValues.values.put(PROPNAME_SCROLL_Y, transitionValues.view.getScrollY()); 59 | } 60 | 61 | @Nullable 62 | @Override 63 | public Animator createAnimator(@NonNull ViewGroup sceneRoot, @Nullable TransitionValues startValues, 64 | @Nullable TransitionValues endValues) { 65 | if (startValues == null || endValues == null || 66 | Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 67 | return null; 68 | } 69 | final View view = endValues.view; 70 | int startX = (Integer) startValues.values.get(PROPNAME_SCROLL_X); 71 | int endX = (Integer) endValues.values.get(PROPNAME_SCROLL_X); 72 | int startY = (Integer) startValues.values.get(PROPNAME_SCROLL_Y); 73 | int endY = (Integer) endValues.values.get(PROPNAME_SCROLL_Y); 74 | Animator scrollXAnimator = null; 75 | Animator scrollYAnimator = null; 76 | if (startX != endX) { 77 | view.setScrollX(startX); 78 | scrollXAnimator = ObjectAnimator.ofInt(view, "scrollX", startX, endX); 79 | } 80 | if (startY != endY) { 81 | view.setScrollY(startY); 82 | scrollYAnimator = ObjectAnimator.ofInt(view, "scrollY", startY, endY); 83 | } 84 | return TransitionUtils.mergeAnimators(scrollXAnimator, scrollYAnimator); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /library(1.x)/src/main/java/com/transitionseverywhere/CircularPropagation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 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 | package com.transitionseverywhere; 17 | 18 | import android.annotation.TargetApi; 19 | import android.graphics.Rect; 20 | import android.os.Build; 21 | import android.support.annotation.NonNull; 22 | import android.support.annotation.Nullable; 23 | import android.view.View; 24 | import android.view.ViewGroup; 25 | 26 | /** 27 | * A propagation that varies with the distance to the epicenter of the Transition 28 | * or center of the scene if no epicenter exists. When a View is visible in the 29 | * start of the transition, Views farther from the epicenter will transition 30 | * sooner than Views closer to the epicenter. When a View is not in the start 31 | * of the transition or is not visible at the start of the transition, it will 32 | * transition sooner when closer to the epicenter and later when farther from 33 | * the epicenter. This is the default TransitionPropagation used with 34 | * {@link android.transition.Explode}. 35 | */ 36 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 37 | public class CircularPropagation extends VisibilityPropagation { 38 | private static final String TAG = "CircularPropagation"; 39 | 40 | private float mPropagationSpeed = 3.0f; 41 | 42 | /** 43 | * Sets the speed at which transition propagation happens, relative to the duration of the 44 | * Transition. A propagationSpeed of 1 means that a View centered farthest from 45 | * the epicenter and View centered at the epicenter will have a difference 46 | * in start delay of approximately the duration of the Transition. A speed of 2 means the 47 | * start delay difference will be approximately half of the duration of the transition. A 48 | * value of 0 is illegal, but negative values will invert the propagation. 49 | * 50 | * @param propagationSpeed The speed at which propagation occurs, relative to the duration 51 | * of the transition. A speed of 4 means it works 4 times as fast 52 | * as the duration of the transition. May not be 0. 53 | */ 54 | public void setPropagationSpeed(float propagationSpeed) { 55 | if (propagationSpeed == 0) { 56 | throw new IllegalArgumentException("propagationSpeed may not be 0"); 57 | } 58 | mPropagationSpeed = propagationSpeed; 59 | } 60 | 61 | @Override 62 | public long getStartDelay(@NonNull ViewGroup sceneRoot, @NonNull Transition transition, 63 | @Nullable TransitionValues startValues, @Nullable TransitionValues endValues) { 64 | if (startValues == null && endValues == null) { 65 | return 0; 66 | } 67 | int directionMultiplier = 1; 68 | TransitionValues positionValues; 69 | if (endValues == null || getViewVisibility(startValues) == View.VISIBLE) { 70 | positionValues = startValues; 71 | directionMultiplier = -1; 72 | } else { 73 | positionValues = endValues; 74 | } 75 | 76 | int viewCenterX = getViewX(positionValues); 77 | int viewCenterY = getViewY(positionValues); 78 | 79 | Rect epicenter = transition.getEpicenter(); 80 | int epicenterX; 81 | int epicenterY; 82 | if (epicenter != null) { 83 | epicenterX = epicenter.centerX(); 84 | epicenterY = epicenter.centerY(); 85 | } else { 86 | int[] loc = new int[2]; 87 | sceneRoot.getLocationOnScreen(loc); 88 | epicenterX = Math.round(loc[0] + (sceneRoot.getWidth() / 2) 89 | + sceneRoot.getTranslationX()); 90 | epicenterY = Math.round(loc[1] + (sceneRoot.getHeight() / 2) 91 | + sceneRoot.getTranslationY()); 92 | } 93 | double distance = distance(viewCenterX, viewCenterY, epicenterX, epicenterY); 94 | double maxDistance = distance(0, 0, sceneRoot.getWidth(), sceneRoot.getHeight()); 95 | double distanceFraction = distance/maxDistance; 96 | 97 | long duration = transition.getDuration(); 98 | if (duration < 0) { 99 | duration = 300; 100 | } 101 | 102 | return Math.round(duration * directionMultiplier / mPropagationSpeed * distanceFraction); 103 | } 104 | 105 | private static double distance(float x1, float y1, float x2, float y2) { 106 | double x = x2 - x1; 107 | double y = y2 - y1; 108 | return Math.hypot(x, y); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /library(1.x)/src/main/java/com/transitionseverywhere/PathMotion.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 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 | package com.transitionseverywhere; 17 | 18 | import android.content.Context; 19 | import android.graphics.Path; 20 | import android.support.annotation.NonNull; 21 | import android.util.AttributeSet; 22 | 23 | /** 24 | * This base class can be extended to provide motion along a Path to Transitions. 25 | * 26 | *

27 | * Transitions such as {@link android.transition.ChangeBounds} move Views, typically 28 | * in a straight path between the start and end positions. Applications that desire to 29 | * have these motions move in a curve can change how Views interpolate in two dimensions 30 | * by extending PathMotion and implementing {@link #getPath(float, float, float, float)}. 31 | *

32 | *

This may be used in XML as an element inside a transition.

33 | *
34 |  * {@code
35 |  * <changeBounds>
36 |  *     <pathMotion class="my.app.transition.MyPathMotion"/>
37 |  * </changeBounds>
38 |  * }
39 |  * 
40 | */ 41 | public abstract class PathMotion { 42 | 43 | public static final PathMotion STRAIGHT_PATH_MOTION = new PathMotion() { 44 | @Override 45 | @NonNull 46 | public Path getPath(float startX, float startY, float endX, float endY) { 47 | Path path = new Path(); 48 | path.moveTo(startX, startY); 49 | path.lineTo(endX, endY); 50 | return path; 51 | } 52 | }; 53 | 54 | public PathMotion() {} 55 | 56 | public PathMotion(@NonNull Context context, @NonNull AttributeSet attrs) {} 57 | 58 | /** 59 | * Provide a Path to interpolate between two points (startX, startY) and 60 | * (endX, endY). This allows controlled curved motion along two dimensions. 61 | * 62 | * @param startX The x coordinate of the starting point. 63 | * @param startY The y coordinate of the starting point. 64 | * @param endX The x coordinate of the ending point. 65 | * @param endY The y coordinate of the ending point. 66 | * @return A Path along which the points should be interpolated. The returned Path 67 | * must start at point (startX, startY), typically using 68 | * {@link android.graphics.Path#moveTo(float, float)} and end at (endX, endY). 69 | */ 70 | @NonNull 71 | public abstract Path getPath(float startX, float startY, float endX, float endY); 72 | } 73 | -------------------------------------------------------------------------------- /library(1.x)/src/main/java/com/transitionseverywhere/PatternPathMotion.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 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 | package com.transitionseverywhere; 17 | 18 | import android.content.Context; 19 | import android.content.res.TypedArray; 20 | import android.graphics.Matrix; 21 | import android.graphics.Path; 22 | import android.graphics.PathMeasure; 23 | import android.support.annotation.NonNull; 24 | import android.support.annotation.Nullable; 25 | import android.util.AttributeSet; 26 | 27 | /** 28 | * A PathMotion that takes a Path pattern and applies it to the separation between two points. 29 | * The starting point of the Path will be moved to the origin and the end point will be scaled 30 | * and rotated so that it matches with the target end point. 31 | *

This may be used in XML as an element inside a transition.

32 | *
 33 |  * {@code
 34 |  * <changeBounds>
 35 |  *     <patternPathMotion android:patternPathData="M0 0 L0 100 L100 100"/>
 36 |  * </changeBounds>}
 37 |  * 
38 | */ 39 | public class PatternPathMotion extends PathMotion { 40 | 41 | @Nullable 42 | private Path mOriginalPatternPath; 43 | 44 | @NonNull 45 | private final Path mPatternPath = new Path(); 46 | 47 | @NonNull 48 | private final Matrix mTempMatrix = new Matrix(); 49 | 50 | /** 51 | * Constructs a PatternPathMotion with a straight-line pattern. 52 | */ 53 | public PatternPathMotion() { 54 | mPatternPath.lineTo(1, 0); 55 | mOriginalPatternPath = mPatternPath; 56 | } 57 | 58 | public PatternPathMotion(@NonNull Context context, @NonNull AttributeSet attrs) { 59 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PatternPathMotion); 60 | try { 61 | String pathData = a.getString(R.styleable.PatternPathMotion_patternPathData); 62 | if (pathData == null) { 63 | throw new RuntimeException("pathData must be supplied for patternPathMotion"); 64 | } 65 | Path pattern = PathParser.createPathFromPathData(pathData); 66 | setPatternPath(pattern); 67 | } finally { 68 | a.recycle(); 69 | } 70 | 71 | } 72 | 73 | /** 74 | * Creates a PatternPathMotion with the Path defining a pattern of motion between two 75 | * coordinates. The pattern will be translated, rotated, and scaled to fit between the start 76 | * and end points. The pattern must not be empty and must have the end point differ from the 77 | * start point. 78 | * 79 | * @param patternPath A Path to be used as a pattern for two-dimensional motion. 80 | */ 81 | public PatternPathMotion(@Nullable Path patternPath) { 82 | setPatternPath(patternPath); 83 | } 84 | 85 | /** 86 | * Returns the Path defining a pattern of motion between two coordinates. 87 | * The pattern will be translated, rotated, and scaled to fit between the start and end points. 88 | * The pattern must not be empty and must have the end point differ from the start point. 89 | * 90 | * @return the Path defining a pattern of motion between two coordinates. 91 | * @attr ref android.R.styleable#PatternPathMotion_patternPathData 92 | */ 93 | @Nullable 94 | public Path getPatternPath() { 95 | return mOriginalPatternPath; 96 | } 97 | 98 | /** 99 | * Sets the Path defining a pattern of motion between two coordinates. 100 | * The pattern will be translated, rotated, and scaled to fit between the start and end points. 101 | * The pattern must not be empty and must have the end point differ from the start point. 102 | * 103 | * @param patternPath A Path to be used as a pattern for two-dimensional motion. 104 | * @attr ref android.R.styleable#PatternPathMotion_patternPathData 105 | */ 106 | public void setPatternPath(@Nullable Path patternPath) { 107 | PathMeasure pathMeasure = new PathMeasure(patternPath, false); 108 | float length = pathMeasure.getLength(); 109 | float[] pos = new float[2]; 110 | pathMeasure.getPosTan(length, pos, null); 111 | float endX = pos[0]; 112 | float endY = pos[1]; 113 | pathMeasure.getPosTan(0, pos, null); 114 | float startX = pos[0]; 115 | float startY = pos[1]; 116 | 117 | if (startX == endX && startY == endY) { 118 | throw new IllegalArgumentException("pattern must not end at the starting point"); 119 | } 120 | 121 | mTempMatrix.setTranslate(-startX, -startY); 122 | float dx = endX - startX; 123 | float dy = endY - startY; 124 | float distance = (float) Math.hypot(dx, dy); 125 | float scale = 1 / distance; 126 | mTempMatrix.postScale(scale, scale); 127 | double angle = Math.atan2(dy, dx); 128 | mTempMatrix.postRotate((float) Math.toDegrees(-angle)); 129 | if (patternPath != null) { 130 | patternPath.transform(mTempMatrix, mPatternPath); 131 | } 132 | mOriginalPatternPath = patternPath; 133 | } 134 | 135 | @Override 136 | @NonNull 137 | public Path getPath(float startX, float startY, float endX, float endY) { 138 | double dx = endX - startX; 139 | double dy = endY - startY; 140 | float length = (float) Math.hypot(dx, dy); 141 | double angle = Math.atan2(dy, dx); 142 | 143 | mTempMatrix.setScale(length, length); 144 | mTempMatrix.postRotate((float) Math.toDegrees(angle)); 145 | mTempMatrix.postTranslate(startX, startY); 146 | Path path = new Path(); 147 | mPatternPath.transform(mTempMatrix, path); 148 | return path; 149 | } 150 | 151 | } 152 | -------------------------------------------------------------------------------- /library(1.x)/src/main/java/com/transitionseverywhere/Recolor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 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 com.transitionseverywhere; 18 | 19 | import android.animation.Animator; 20 | import android.animation.ArgbEvaluator; 21 | import android.animation.ObjectAnimator; 22 | import android.annotation.TargetApi; 23 | import android.content.Context; 24 | import android.graphics.drawable.ColorDrawable; 25 | import android.graphics.drawable.Drawable; 26 | import android.os.Build; 27 | import android.support.annotation.NonNull; 28 | import android.support.annotation.Nullable; 29 | import android.util.AttributeSet; 30 | import android.util.Property; 31 | import android.view.View; 32 | import android.view.ViewGroup; 33 | import android.widget.TextView; 34 | 35 | import com.transitionseverywhere.utils.IntProperty; 36 | 37 | /** 38 | * This transition tracks changes during scene changes to the 39 | * {@link View#setBackground(android.graphics.drawable.Drawable) background} 40 | * property of its target views (when the background is a 41 | * {@link ColorDrawable}, as well as the 42 | * {@link TextView#setTextColor(android.content.res.ColorStateList) 43 | * color} of the text for target TextViews. If the color changes between 44 | * scenes, the color change is animated. 45 | */ 46 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 47 | public class Recolor extends Transition { 48 | 49 | private static final String PROPNAME_BACKGROUND = "android:recolor:background"; 50 | private static final String PROPNAME_TEXT_COLOR = "android:recolor:textColor"; 51 | 52 | @Nullable 53 | public static final Property TEXTVIEW_TEXT_COLOR; 54 | @Nullable 55 | public static final Property COLORDRAWABLE_COLOR; 56 | 57 | static { 58 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 59 | TEXTVIEW_TEXT_COLOR = new IntProperty() { 60 | 61 | @Override 62 | public void setValue(@NonNull TextView object, int value) { 63 | object.setTextColor(value); 64 | } 65 | 66 | @NonNull 67 | @Override 68 | public Integer get(TextView object) { 69 | return 0; 70 | } 71 | 72 | }.optimize(); 73 | COLORDRAWABLE_COLOR = new IntProperty() { 74 | @Override 75 | public void setValue(@NonNull ColorDrawable object, int value) { 76 | object.setColor(value); 77 | } 78 | 79 | @NonNull 80 | @Override 81 | public Integer get(@NonNull ColorDrawable object) { 82 | return object.getColor(); 83 | } 84 | }.optimize(); 85 | } else { 86 | TEXTVIEW_TEXT_COLOR = null; 87 | COLORDRAWABLE_COLOR = null; 88 | } 89 | } 90 | 91 | public Recolor() {} 92 | 93 | public Recolor(@NonNull Context context, @NonNull AttributeSet attrs) { 94 | super(context, attrs); 95 | } 96 | 97 | private void captureValues(TransitionValues transitionValues) { 98 | transitionValues.values.put(PROPNAME_BACKGROUND, transitionValues.view.getBackground()); 99 | if (transitionValues.view instanceof TextView) { 100 | transitionValues.values.put(PROPNAME_TEXT_COLOR, 101 | ((TextView) transitionValues.view).getCurrentTextColor()); 102 | } 103 | } 104 | 105 | @Override 106 | public void captureStartValues(@NonNull TransitionValues transitionValues) { 107 | captureValues(transitionValues); 108 | } 109 | 110 | @Override 111 | public void captureEndValues(@NonNull TransitionValues transitionValues) { 112 | captureValues(transitionValues); 113 | } 114 | 115 | @Nullable 116 | @Override 117 | public Animator createAnimator(@NonNull ViewGroup sceneRoot, @Nullable TransitionValues startValues, 118 | @Nullable TransitionValues endValues) { 119 | if (startValues == null || endValues == null) { 120 | return null; 121 | } 122 | final View view = endValues.view; 123 | Drawable startBackground = (Drawable) startValues.values.get(PROPNAME_BACKGROUND); 124 | Drawable endBackground = (Drawable) endValues.values.get(PROPNAME_BACKGROUND); 125 | ObjectAnimator bgAnimator = null; 126 | if (startBackground instanceof ColorDrawable && endBackground instanceof ColorDrawable) { 127 | ColorDrawable startColor = (ColorDrawable) startBackground; 128 | ColorDrawable endColor = (ColorDrawable) endBackground; 129 | if (startColor.getColor() != endColor.getColor()) { 130 | final int finalColor = endColor.getColor(); 131 | endColor = (ColorDrawable) endColor.mutate(); 132 | endColor.setColor(startColor.getColor()); 133 | bgAnimator = ObjectAnimator.ofInt(endColor, COLORDRAWABLE_COLOR, startColor.getColor(), finalColor); 134 | bgAnimator.setEvaluator(new ArgbEvaluator()); 135 | } 136 | } 137 | ObjectAnimator textColorAnimator = null; 138 | if (view instanceof TextView) { 139 | TextView textView = (TextView) view; 140 | int start = (Integer) startValues.values.get(PROPNAME_TEXT_COLOR); 141 | int end = (Integer) endValues.values.get(PROPNAME_TEXT_COLOR); 142 | if (start != end) { 143 | textView.setTextColor(end); 144 | textColorAnimator = ObjectAnimator.ofInt(textView, TEXTVIEW_TEXT_COLOR, start, end); 145 | textColorAnimator.setEvaluator(new ArgbEvaluator()); 146 | } 147 | } 148 | return TransitionUtils.mergeAnimators(bgAnimator, textColorAnimator); 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /library(1.x)/src/main/java/com/transitionseverywhere/Rotate.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 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 com.transitionseverywhere; 18 | 19 | import android.animation.Animator; 20 | import android.animation.ObjectAnimator; 21 | import android.annotation.TargetApi; 22 | import android.os.Build; 23 | import android.support.annotation.NonNull; 24 | import android.support.annotation.Nullable; 25 | import android.view.View; 26 | import android.view.ViewGroup; 27 | 28 | /** 29 | * This transition captures the rotation property of targets before and after 30 | * the scene change and animates any changes. 31 | */ 32 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 33 | public class Rotate extends Transition { 34 | 35 | private static final String PROPNAME_ROTATION = "android:rotate:rotation"; 36 | 37 | @Override 38 | public void captureStartValues(@NonNull TransitionValues transitionValues) { 39 | transitionValues.values.put(PROPNAME_ROTATION, transitionValues.view.getRotation()); 40 | } 41 | 42 | @Override 43 | public void captureEndValues(@NonNull TransitionValues transitionValues) { 44 | transitionValues.values.put(PROPNAME_ROTATION, transitionValues.view.getRotation()); 45 | } 46 | 47 | @Nullable 48 | @Override 49 | public Animator createAnimator(@NonNull ViewGroup sceneRoot, @Nullable TransitionValues startValues, 50 | @Nullable TransitionValues endValues) { 51 | if (startValues == null || endValues == null) { 52 | return null; 53 | } 54 | final View view = endValues.view; 55 | float startRotation = (Float) startValues.values.get(PROPNAME_ROTATION); 56 | float endRotation = (Float) endValues.values.get(PROPNAME_ROTATION); 57 | if (startRotation != endRotation) { 58 | view.setRotation(startRotation); 59 | return ObjectAnimator.ofFloat(view, View.ROTATION, 60 | startRotation, endRotation); 61 | } 62 | return null; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /library(1.x)/src/main/java/com/transitionseverywhere/TransitionPropagation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 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 | package com.transitionseverywhere; 17 | 18 | import android.support.annotation.NonNull; 19 | import android.support.annotation.Nullable; 20 | import android.view.ViewGroup; 21 | 22 | /** 23 | * Extend TransitionPropagation to customize start delays for Animators created 24 | * in {@link Transition#createAnimator(android.view.ViewGroup, 25 | * TransitionValues, TransitionValues)}. 26 | * A Transition such as {@link Explode} 27 | * defaults to using {@link CircularPropagation} and Views closer to the 28 | * epicenter will move out of the scene later and into the scene sooner than Views farther 29 | * from the epicenter, giving the appearance of inertia. With no TransitionPropagation, all 30 | * Views will react simultaneously to the start of the transition. 31 | * 32 | * @see Transition#setPropagation(TransitionPropagation) 33 | * @see Transition#getEpicenter() 34 | */ 35 | public abstract class TransitionPropagation { 36 | /** 37 | * Called by Transition to alter the Animator start delay. All start delays will be adjusted 38 | * such that the minimum becomes zero. 39 | * 40 | * @param sceneRoot The root of the View hierarchy running the transition. 41 | * @param transition The transition that created the Animator 42 | * @param startValues The values for a specific target in the start scene. 43 | * @param endValues The values for the target in the end scene. 44 | * @return A start delay to use with the Animator created by transition. The 45 | * delay will be offset by the minimum delay of all TransitionPropagations 46 | * used in the Transition so that the smallest delay will be 0. Returned values may be 47 | * negative. 48 | */ 49 | public abstract long getStartDelay(@NonNull ViewGroup sceneRoot, @NonNull Transition transition, 50 | @Nullable TransitionValues startValues, @Nullable TransitionValues endValues); 51 | 52 | /** 53 | * Captures the values in the start or end scene for the properties that this 54 | * transition propagation monitors. These values are then passed as the startValues 55 | * or endValues structure in a later call to 56 | * {@link #getStartDelay(ViewGroup, Transition, 57 | * TransitionValues, TransitionValues)}. 58 | * The main concern for an implementation is what the 59 | * properties are that the transition cares about and what the values are 60 | * for all of those properties. The start and end values will be compared 61 | * later during the 62 | * {@link #getStartDelay(ViewGroup, Transition, 63 | * TransitionValues, TransitionValues)}. 64 | * method to determine the start delay. 65 | *

66 | *

Subclasses must implement this method. The method should only be called by the 67 | * transition system; it is not intended to be called from external classes.

68 | * 69 | * @param transitionValues The holder for any values that the Transition 70 | * wishes to store. Values are stored in the values field 71 | * of this TransitionValues object and are keyed from 72 | * a String value. For example, to store a view's rotation value, 73 | * a transition might call 74 | * transitionValues.values.put("appname:transitionname:rotation", 75 | * view.getRotation()). The target view will already be stored in 76 | * the transitionValues structure when this method is called. 77 | */ 78 | public abstract void captureValues(@NonNull TransitionValues transitionValues); 79 | 80 | /** 81 | * Returns the set of property names stored in the {@link TransitionValues} 82 | * object passed into {@link #captureValues(TransitionValues)} that 83 | * this transition propagation cares about for the purposes of preventing 84 | * duplicate capturing of property values. 85 | *

86 | *

A TransitionPropagation must override this method to prevent 87 | * duplicate capturing of values and must contain at least one

88 | * 89 | * @return An array of property names as described in the class documentation for 90 | * {@link TransitionValues}. 91 | */ 92 | @NonNull 93 | public abstract String[] getPropagationProperties(); 94 | } 95 | -------------------------------------------------------------------------------- /library(1.x)/src/main/java/com/transitionseverywhere/TransitionValues.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 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 com.transitionseverywhere; 18 | 19 | import android.support.annotation.NonNull; 20 | import android.support.v4.util.ArrayMap; 21 | import android.view.View; 22 | import android.view.ViewGroup; 23 | 24 | import java.util.ArrayList; 25 | import java.util.Map; 26 | 27 | /** 28 | * Data structure which holds cached values for the transition. 29 | * The view field is the target which all of the values pertain to. 30 | * The values field is a map which holds information for fields 31 | * according to names selected by the transitions. These names should 32 | * be unique to avoid clobbering values stored by other transitions, 33 | * such as the convention project:transition_name:property_name. For 34 | * example, the platform might store a property "alpha" in a transition 35 | * "Fader" as "android:fader:alpha". 36 | *

37 | *

These values are cached during the 38 | * {@link Transition#captureStartValues(TransitionValues)} 39 | * capture} phases of a scene change, once when the start values are captured 40 | * and again when the end values are captured. These start/end values are then 41 | * passed into the transitions via the 42 | * for {@link Transition#createAnimator(ViewGroup, TransitionValues, TransitionValues)} 43 | * method.

44 | */ 45 | public class TransitionValues { 46 | 47 | public TransitionValues(@NonNull View view) { 48 | this.view = view; 49 | } 50 | 51 | /** 52 | * The View with these values 53 | */ 54 | @NonNull 55 | public final View view; 56 | 57 | /** 58 | * The set of values tracked by transitions for this scene 59 | */ 60 | @NonNull 61 | public final Map values = new ArrayMap(); 62 | /** 63 | * The Transitions that targeted this view. 64 | */ 65 | @NonNull 66 | final ArrayList targetedTransitions = new ArrayList(); 67 | 68 | @Override 69 | public boolean equals(Object other) { 70 | if (other instanceof TransitionValues) { 71 | if (view == ((TransitionValues) other).view) { 72 | if (values.equals(((TransitionValues) other).values)) { 73 | return true; 74 | } 75 | } 76 | } 77 | return false; 78 | } 79 | 80 | @Override 81 | public int hashCode() { 82 | return 31 * view.hashCode() + values.hashCode(); 83 | } 84 | 85 | @NonNull 86 | @Override 87 | public String toString() { 88 | String returnValue = "TransitionValues@" + Integer.toHexString(hashCode()) + ":\n"; 89 | returnValue += " view = " + view + "\n"; 90 | returnValue += " values:"; 91 | for (String s : values.keySet()) { 92 | returnValue += " " + s + ": " + values.get(s) + "\n"; 93 | } 94 | return returnValue; 95 | } 96 | } -------------------------------------------------------------------------------- /library(1.x)/src/main/java/com/transitionseverywhere/TransitionValuesMaps.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 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 com.transitionseverywhere; 18 | 19 | import android.support.annotation.NonNull; 20 | import android.support.v4.util.ArrayMap; 21 | import android.support.v4.util.LongSparseArray; 22 | import android.util.SparseArray; 23 | import android.view.View; 24 | 25 | class TransitionValuesMaps { 26 | @NonNull 27 | ArrayMap viewValues = 28 | new ArrayMap(); 29 | @NonNull 30 | SparseArray idValues = new SparseArray(); 31 | @NonNull 32 | LongSparseArray itemIdValues = new LongSparseArray(); 33 | @NonNull 34 | ArrayMap nameValues = new ArrayMap(); 35 | } 36 | -------------------------------------------------------------------------------- /library(1.x)/src/main/java/com/transitionseverywhere/VisibilityPropagation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 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 | package com.transitionseverywhere; 17 | 18 | import android.annotation.TargetApi; 19 | import android.os.Build; 20 | import android.support.annotation.NonNull; 21 | import android.support.annotation.Nullable; 22 | import android.view.View; 23 | 24 | /** 25 | * Base class for TransitionPropagations that care about 26 | * View Visibility and the center position of the View. 27 | */ 28 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 29 | public abstract class VisibilityPropagation extends TransitionPropagation { 30 | 31 | /** 32 | * The property key used for {@link android.view.View#getVisibility()}. 33 | */ 34 | private static final String PROPNAME_VISIBILITY = "android:visibilityPropagation:visibility"; 35 | 36 | /** 37 | * The property key used for the center of the View in screen coordinates. This is an 38 | * int[2] with the index 0 taking the x coordinate and index 1 taking the y coordinate. 39 | */ 40 | private static final String PROPNAME_VIEW_CENTER = "android:visibilityPropagation:center"; 41 | 42 | private static final String[] VISIBILITY_PROPAGATION_VALUES = { 43 | PROPNAME_VISIBILITY, 44 | PROPNAME_VIEW_CENTER, 45 | }; 46 | 47 | @Override 48 | public void captureValues(@NonNull TransitionValues values) { 49 | View view = values.view; 50 | Integer visibility = (Integer) values.values.get(Visibility.PROPNAME_VISIBILITY); 51 | if (visibility == null) { 52 | visibility = view.getVisibility(); 53 | } 54 | values.values.put(PROPNAME_VISIBILITY, visibility); 55 | int[] loc = new int[2]; 56 | view.getLocationOnScreen(loc); 57 | loc[0] += Math.round(view.getTranslationX()); 58 | loc[0] += view.getWidth() / 2; 59 | loc[1] += Math.round(view.getTranslationY()); 60 | loc[1] += view.getHeight() / 2; 61 | values.values.put(PROPNAME_VIEW_CENTER, loc); 62 | } 63 | 64 | @NonNull 65 | @Override 66 | public String[] getPropagationProperties() { 67 | return VISIBILITY_PROPAGATION_VALUES; 68 | } 69 | 70 | /** 71 | * Returns {@link android.view.View#getVisibility()} for the View at the time the values 72 | * were captured. 73 | * @param values The TransitionValues captured at the start or end of the Transition. 74 | * @return {@link android.view.View#getVisibility()} for the View at the time the values 75 | * were captured. 76 | */ 77 | public int getViewVisibility(@Nullable TransitionValues values) { 78 | if (values == null) { 79 | return View.GONE; 80 | } 81 | Integer visibility = (Integer) values.values.get(PROPNAME_VISIBILITY); 82 | if (visibility == null) { 83 | return View.GONE; 84 | } 85 | return visibility; 86 | } 87 | 88 | /** 89 | * Returns the View's center x coordinate, relative to the screen, at the time the values 90 | * were captured. 91 | * @param values The TransitionValues captured at the start or end of the Transition. 92 | * @return the View's center x coordinate, relative to the screen, at the time the values 93 | * were captured. 94 | */ 95 | public int getViewX(TransitionValues values) { 96 | return getViewCoordinate(values, 0); 97 | } 98 | 99 | /** 100 | * Returns the View's center y coordinate, relative to the screen, at the time the values 101 | * were captured. 102 | * @param values The TransitionValues captured at the start or end of the Transition. 103 | * @return the View's center y coordinate, relative to the screen, at the time the values 104 | * were captured. 105 | */ 106 | public int getViewY(TransitionValues values) { 107 | return getViewCoordinate(values, 1); 108 | } 109 | 110 | private static int getViewCoordinate(@Nullable TransitionValues values, int coordinateIndex) { 111 | if (values == null) { 112 | return -1; 113 | } 114 | 115 | int[] coordinates = (int[]) values.values.get(PROPNAME_VIEW_CENTER); 116 | if (coordinates == null) { 117 | return -1; 118 | } 119 | 120 | return coordinates[coordinateIndex]; 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /library(1.x)/src/main/java/com/transitionseverywhere/extra/TranslationTransition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Andrey Kulikov (andkulikov@gmail.com) 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 | package com.transitionseverywhere.extra; 17 | 18 | import android.animation.Animator; 19 | import android.annotation.TargetApi; 20 | import android.content.Context; 21 | import android.graphics.PointF; 22 | import android.os.Build; 23 | import android.support.annotation.NonNull; 24 | import android.support.annotation.Nullable; 25 | import android.util.AttributeSet; 26 | import android.view.View; 27 | import android.view.ViewGroup; 28 | 29 | import com.transitionseverywhere.Transition; 30 | import com.transitionseverywhere.TransitionValues; 31 | import com.transitionseverywhere.utils.AnimatorUtils; 32 | import com.transitionseverywhere.utils.PointFProperty; 33 | 34 | /** 35 | * This transition tracks changes to the translationX and translationY of 36 | * target views in the start and end scenes and animates change. 37 | *

38 | * Created by Andrey Kulikov on 13/03/16. 39 | */ 40 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 41 | public class TranslationTransition extends Transition { 42 | 43 | private static final String TRANSLATION_X = "TranslationTransition:translationX"; 44 | private static final String TRANSLATION_Y = "TranslationTransition:translationY"; 45 | 46 | @Nullable 47 | private static final PointFProperty TRANSLATION_PROPERTY; 48 | 49 | static { 50 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 51 | TRANSLATION_PROPERTY = new PointFProperty() { 52 | 53 | @Override 54 | public void set(@NonNull View object, @NonNull PointF value) { 55 | object.setTranslationX(value.x); 56 | object.setTranslationY(value.y); 57 | } 58 | 59 | @Override 60 | public PointF get(@NonNull View object) { 61 | return new PointF(object.getTranslationX(), object.getTranslationY()); 62 | } 63 | }; 64 | } else { 65 | TRANSLATION_PROPERTY = null; 66 | } 67 | } 68 | 69 | public TranslationTransition() { 70 | } 71 | 72 | public TranslationTransition(@NonNull Context context, @NonNull AttributeSet attrs) { 73 | super(context, attrs); 74 | } 75 | 76 | private void captureValues(@NonNull TransitionValues transitionValues) { 77 | transitionValues.values.put(TRANSLATION_X, transitionValues.view.getTranslationX()); 78 | transitionValues.values.put(TRANSLATION_Y, transitionValues.view.getTranslationY()); 79 | } 80 | 81 | @Override 82 | public void captureStartValues(@NonNull TransitionValues transitionValues) { 83 | captureValues(transitionValues); 84 | } 85 | 86 | @Override 87 | public void captureEndValues(@NonNull TransitionValues transitionValues) { 88 | captureValues(transitionValues); 89 | } 90 | 91 | @Nullable 92 | @Override 93 | public Animator createAnimator(@NonNull ViewGroup sceneRoot, @Nullable TransitionValues startValues, 94 | @Nullable TransitionValues endValues) { 95 | if (startValues != null && endValues != null && TRANSLATION_PROPERTY != null) { 96 | float startX = (float) startValues.values.get(TRANSLATION_X); 97 | float startY = (float) startValues.values.get(TRANSLATION_Y); 98 | float endX = (float) endValues.values.get(TRANSLATION_X); 99 | float endY = (float) endValues.values.get(TRANSLATION_Y); 100 | endValues.view.setTranslationX(startX); 101 | endValues.view.setTranslationY(startY); 102 | return AnimatorUtils.ofPointF(endValues.view, TRANSLATION_PROPERTY, getPathMotion(), startX, startY, endX, endY); 103 | } else { 104 | return null; 105 | } 106 | } 107 | 108 | } -------------------------------------------------------------------------------- /library(1.x)/src/main/java/com/transitionseverywhere/utils/BasePointFAnimator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Andrey Kulikov (andkulikov@gmail.com) 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 | package com.transitionseverywhere.utils; 17 | 18 | import android.animation.ValueAnimator; 19 | import android.annotation.TargetApi; 20 | import android.graphics.PointF; 21 | import android.os.Build; 22 | import android.support.annotation.NonNull; 23 | 24 | import java.lang.ref.WeakReference; 25 | 26 | /** 27 | * Created by Andrey Kulikov on 17.08.15. 28 | */ 29 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 30 | public abstract class BasePointFAnimator extends ValueAnimator implements ValueAnimator.AnimatorUpdateListener { 31 | 32 | /** 33 | * A weak reference to the mTarget object on which the property exists, set 34 | * in the constructor. We'll cancel the animation if this goes away. 35 | */ 36 | @NonNull 37 | private final WeakReference mTarget; 38 | 39 | @NonNull 40 | private final PointFProperty mPointFProperty; 41 | 42 | @NonNull 43 | private final PointF mTempPointF = new PointF(); 44 | 45 | protected BasePointFAnimator(@NonNull Object target, @NonNull PointFProperty pointFProperty) { 46 | mTarget = new WeakReference<>(target); 47 | mPointFProperty = pointFProperty; 48 | setFloatValues(0f, 1f); 49 | addUpdateListener(this); 50 | } 51 | 52 | protected abstract void applyAnimatedFraction(@NonNull PointF holder, float fraction); 53 | 54 | @Override 55 | public void onAnimationUpdate(@NonNull ValueAnimator animation) { 56 | Object target = mTarget.get(); 57 | if (target == null) { 58 | // We lost the target reference, cancel. 59 | cancel(); 60 | return; 61 | } 62 | applyAnimatedFraction(mTempPointF, animation.getAnimatedFraction()); 63 | mPointFProperty.set(target, mTempPointF); 64 | } 65 | } -------------------------------------------------------------------------------- /library(1.x)/src/main/java/com/transitionseverywhere/utils/FloatProperty.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Andrey Kulikov (andkulikov@gmail.com) 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 | package com.transitionseverywhere.utils; 17 | 18 | import android.annotation.SuppressLint; 19 | import android.support.annotation.NonNull; 20 | 21 | /** 22 | * It's great idea to extend it for any properties that works with float fields 23 | * because ObjectAnimator have optimizations for FloatProperty to avoid autoboxing. 24 | * 25 | * Created by Andrey Kulikov on 17/04/16. 26 | */ 27 | @SuppressLint("NewApi, Override") 28 | public abstract class FloatProperty extends android.util.FloatProperty { 29 | 30 | public FloatProperty() { 31 | super(null); 32 | // null instead of name here because it's used only for calling setter 33 | // and getter via reflection. but we have our own overridden set and get. 34 | } 35 | 36 | /** 37 | * Just default realisation. Some of properties can have no getter. Override for real getter 38 | */ 39 | @Override 40 | @NonNull 41 | public Float get(@NonNull T object) { 42 | return 0f; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /library(1.x)/src/main/java/com/transitionseverywhere/utils/IntProperty.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Andrey Kulikov (andkulikov@gmail.com) 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 | package com.transitionseverywhere.utils; 17 | 18 | import android.annotation.SuppressLint; 19 | import android.annotation.TargetApi; 20 | import android.os.Build; 21 | import android.support.annotation.NonNull; 22 | import android.util.Property; 23 | 24 | /** 25 | * Helper class for properties with int values. 26 | * Unfortunately we can't just extend android.util.IntProperty here, 27 | * because of a bug that was fixed only in 4.2.2: 28 | * https://android.googlesource.com/platform/frameworks/base/+/c5d43f76fd7c3ccb91f1b75618a9c9e8f202505b 29 | *

30 | * To apply internal optimizations to avoid autoboxing use object that will be 31 | * returned by method {@link #optimize()} 32 | *

33 | * Created by Andrey Kulikov on 17/04/16. 34 | */ 35 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 36 | public abstract class IntProperty extends Property { 37 | 38 | public IntProperty() { 39 | super(Integer.class, null); 40 | } 41 | 42 | public abstract void setValue(@NonNull T object, int value); 43 | 44 | @Override 45 | final public void set(@NonNull T object, @NonNull Integer value) { 46 | setValue(object, value); 47 | } 48 | 49 | /** 50 | * Just default realisation. Some of properties can have no getter. Override for real getter 51 | */ 52 | @Override 53 | @NonNull 54 | public Integer get(T object) { 55 | return 0; 56 | } 57 | 58 | @SuppressLint("NewApi") 59 | @NonNull 60 | public Property optimize() { 61 | if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2) { 62 | return new android.util.IntProperty(null) { 63 | @Override 64 | public void setValue(@NonNull T object, int value) { 65 | IntProperty.this.setValue(object, value); 66 | } 67 | 68 | @Override 69 | @NonNull 70 | public Integer get(@NonNull T object) { 71 | return IntProperty.this.get(object); 72 | } 73 | }; 74 | } else { 75 | return this; 76 | } 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /library(1.x)/src/main/java/com/transitionseverywhere/utils/PathAnimatorCompat.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Andrey Kulikov (andkulikov@gmail.com) 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 | package com.transitionseverywhere.utils; 17 | 18 | import android.annotation.TargetApi; 19 | import android.graphics.Path; 20 | import android.graphics.PathMeasure; 21 | import android.graphics.PointF; 22 | import android.os.Build; 23 | import android.support.annotation.NonNull; 24 | import android.support.annotation.Nullable; 25 | 26 | /** 27 | * Created by Andrey Kulikov on 17.08.15. 28 | */ 29 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 30 | public class PathAnimatorCompat extends BasePointFAnimator { 31 | 32 | private PathMeasure mPathMeasure; 33 | private float mPathLength; 34 | 35 | @NonNull 36 | private float[] mTempArray = new float[2]; 37 | 38 | private PathAnimatorCompat(@NonNull Object target, @NonNull PointFProperty pointFProperty) { 39 | super(target, pointFProperty); 40 | } 41 | 42 | @Nullable 43 | public static PathAnimatorCompat ofPointF(@Nullable T target, @Nullable PointFProperty property, @Nullable Path path) { 44 | PathAnimatorCompat animator = null; 45 | if (target != null && property != null && path != null) { 46 | animator = new PathAnimatorCompat(target, property); 47 | animator.mPathMeasure = new PathMeasure(path, false); 48 | animator.mPathLength = animator.mPathMeasure.getLength(); 49 | } 50 | return animator; 51 | } 52 | 53 | @Override 54 | protected void applyAnimatedFraction(@NonNull PointF holder, float fraction) { 55 | if (fraction < 0) { 56 | fraction = 0; 57 | } 58 | if (fraction > 1) { 59 | fraction = 1; 60 | } 61 | mPathMeasure.getPosTan(fraction * mPathLength, mTempArray, null); 62 | holder.set(mTempArray[0], mTempArray[1]); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /library(1.x)/src/main/java/com/transitionseverywhere/utils/PointFAnimator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Andrey Kulikov (andkulikov@gmail.com) 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 | package com.transitionseverywhere.utils; 17 | 18 | import android.annotation.TargetApi; 19 | import android.graphics.PointF; 20 | import android.os.Build; 21 | import android.support.annotation.NonNull; 22 | import android.support.annotation.Nullable; 23 | 24 | /** 25 | * Created by Andrey Kulikov on 17.08.15. 26 | */ 27 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 28 | public class PointFAnimator extends BasePointFAnimator { 29 | 30 | private float mStartTop, mStartLeft, mEndTop, mEndLeft; 31 | 32 | protected PointFAnimator(@NonNull Object target, @NonNull PointFProperty pointFProperty) { 33 | super(target, pointFProperty); 34 | } 35 | 36 | @Nullable 37 | public static PointFAnimator ofPointF(@Nullable T target, @Nullable PointFProperty property, float startLeft, 38 | float startTop, float endLeft, float endTop) { 39 | PointFAnimator animator = null; 40 | if (target != null && property != null) { 41 | animator = new PointFAnimator(target, property); 42 | animator.mStartLeft = startLeft; 43 | animator.mStartTop = startTop; 44 | animator.mEndLeft = endLeft; 45 | animator.mEndTop = endTop; 46 | } 47 | return animator; 48 | } 49 | 50 | protected void applyAnimatedFraction(@NonNull PointF holder, float fraction) { 51 | holder.x = interpolate(fraction, mStartLeft, mEndLeft); 52 | holder.y = interpolate(fraction, mStartTop, mEndTop); 53 | } 54 | 55 | protected static float interpolate(float fraction, float startValue, float endValue) { 56 | float diff = endValue - startValue; 57 | return startValue + (diff * fraction); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /library(1.x)/src/main/java/com/transitionseverywhere/utils/PointFProperty.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Andrey Kulikov (andkulikov@gmail.com) 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 | package com.transitionseverywhere.utils; 17 | 18 | import android.annotation.TargetApi; 19 | import android.graphics.PointF; 20 | import android.os.Build; 21 | import android.support.annotation.NonNull; 22 | import android.support.annotation.Nullable; 23 | import android.util.Property; 24 | 25 | /** 26 | * Created by Andrey Kulikov on 15.08.15. 27 | */ 28 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 29 | public abstract class PointFProperty extends Property { 30 | 31 | public PointFProperty() { 32 | super(PointF.class, null); 33 | // null instead of name here because it's used only for calling setter 34 | // and getter via reflection. but we have our own overridden set and get. 35 | } 36 | 37 | /** 38 | * Just default realisation. Some of properties can have no getter. Override for real getter 39 | */ 40 | @Override 41 | @Nullable 42 | public PointF get(@NonNull T object) { 43 | return null; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /library(1.x)/src/main/java/com/transitionseverywhere/utils/RectEvaluator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 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 | package com.transitionseverywhere.utils; 17 | 18 | import android.animation.TypeEvaluator; 19 | import android.annotation.TargetApi; 20 | import android.graphics.Rect; 21 | import android.os.Build; 22 | import android.support.annotation.NonNull; 23 | import android.support.annotation.Nullable; 24 | 25 | /** 26 | * This evaluator can be used to perform type interpolation between Rect values. 27 | */ 28 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 29 | public class RectEvaluator implements TypeEvaluator { 30 | 31 | /** 32 | * When null, a new Rect is returned on every evaluate call. When non-null, 33 | * mRect will be modified and returned on every evaluate. 34 | */ 35 | @Nullable 36 | private Rect mRect; 37 | 38 | /** 39 | * Construct a RectEvaluator that returns a new Rect on every evaluate call. 40 | * To avoid creating an object for each evaluate call, 41 | * {@link RectEvaluator#RectEvaluator(android.graphics.Rect)} should be used 42 | * whenever possible. 43 | */ 44 | public RectEvaluator() { 45 | } 46 | 47 | /** 48 | * Constructs a RectEvaluator that modifies and returns reuseRect 49 | * in {@link #evaluate(float, android.graphics.Rect, android.graphics.Rect)} calls. 50 | * The value returned from 51 | * {@link #evaluate(float, android.graphics.Rect, android.graphics.Rect)} should 52 | * not be cached because it will change over time as the object is reused on each 53 | * call. 54 | * 55 | * @param reuseRect A Rect to be modified and returned by evaluate. 56 | */ 57 | public RectEvaluator(@Nullable Rect reuseRect) { 58 | mRect = reuseRect; 59 | } 60 | 61 | /** 62 | * This function returns the result of linearly interpolating the start and 63 | * end Rect values, with fraction representing the proportion 64 | * between the start and end values. The calculation is a simple parametric 65 | * calculation on each of the separate components in the Rect objects 66 | * (left, top, right, and bottom). 67 | * 68 | *

If {@link #RectEvaluator(android.graphics.Rect)} was used to construct 69 | * this RectEvaluator, the object returned will be the reuseRect 70 | * passed into the constructor.

71 | * 72 | * @param fraction The fraction from the starting to the ending values 73 | * @param startValue The start Rect 74 | * @param endValue The end Rect 75 | * @return A linear interpolation between the start and end values, given the 76 | * fraction parameter. 77 | */ 78 | @Override 79 | @NonNull 80 | public Rect evaluate(float fraction, @NonNull Rect startValue, @NonNull Rect endValue) { 81 | int left = startValue.left + (int) ((endValue.left - startValue.left) * fraction); 82 | int top = startValue.top + (int) ((endValue.top - startValue.top) * fraction); 83 | int right = startValue.right + (int) ((endValue.right - startValue.right) * fraction); 84 | int bottom = startValue.bottom + (int) ((endValue.bottom - startValue.bottom) * fraction); 85 | if (mRect == null) { 86 | return new Rect(left, top, right, bottom); 87 | } else { 88 | mRect.set(left, top, right, bottom); 89 | return mRect; 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /library(1.x)/src/main/java/com/transitionseverywhere/utils/ViewGroupUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Andrey Kulikov (andkulikov@gmail.com) 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 | package com.transitionseverywhere.utils; 17 | 18 | import android.animation.LayoutTransition; 19 | import android.annotation.TargetApi; 20 | import android.os.Build; 21 | import android.os.Build.VERSION_CODES; 22 | import android.support.annotation.NonNull; 23 | import android.support.annotation.Nullable; 24 | import android.view.ViewGroup; 25 | 26 | import com.transitionseverywhere.R; 27 | 28 | import java.lang.reflect.Field; 29 | import java.lang.reflect.Method; 30 | 31 | @TargetApi(VERSION_CODES.ICE_CREAM_SANDWICH) 32 | public class ViewGroupUtils { 33 | 34 | @TargetApi(VERSION_CODES.JELLY_BEAN) 35 | static class BaseViewGroupUtils { 36 | 37 | private static final int LAYOUT_TRANSITION_CHANGING = 4; 38 | 39 | @Nullable 40 | private static Field sFieldLayoutSuppressed; 41 | private static LayoutTransition sEmptyLayoutTransition; 42 | @Nullable 43 | private static Method sMethodLayoutTransitionCancel; 44 | 45 | public void suppressLayout(final @NonNull ViewGroup group, boolean suppress) { 46 | if (sEmptyLayoutTransition == null) { 47 | sEmptyLayoutTransition = new LayoutTransition() { 48 | @Override 49 | public boolean isChangingLayout() { 50 | return true; 51 | } 52 | }; 53 | sEmptyLayoutTransition.setAnimator(LayoutTransition.APPEARING, null); 54 | sEmptyLayoutTransition.setAnimator(LayoutTransition.CHANGE_APPEARING, null); 55 | sEmptyLayoutTransition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, null); 56 | sEmptyLayoutTransition.setAnimator(LayoutTransition.DISAPPEARING, null); 57 | sEmptyLayoutTransition.setAnimator(LAYOUT_TRANSITION_CHANGING, null); 58 | } 59 | if (suppress) { 60 | cancelLayoutTransition(group); 61 | LayoutTransition layoutTransition = group.getLayoutTransition(); 62 | if (layoutTransition != null && layoutTransition != sEmptyLayoutTransition) { 63 | group.setTag(R.id.group_layouttransition_backup, group.getLayoutTransition()); 64 | } 65 | group.setLayoutTransition(sEmptyLayoutTransition); 66 | } else { 67 | group.setLayoutTransition(null); 68 | if (sFieldLayoutSuppressed == null) { 69 | sFieldLayoutSuppressed = ReflectionUtils.getPrivateField(ViewGroup.class, 70 | "mLayoutSuppressed"); 71 | } 72 | Boolean suppressed = (Boolean) ReflectionUtils.getFieldValue(group, 73 | Boolean.FALSE, sFieldLayoutSuppressed); 74 | if (!Boolean.FALSE.equals(suppressed)) { 75 | ReflectionUtils.setFieldValue(group, sFieldLayoutSuppressed, false); 76 | group.requestLayout(); 77 | } 78 | final LayoutTransition layoutTransition = (LayoutTransition) 79 | group.getTag(R.id.group_layouttransition_backup); 80 | if (layoutTransition != null) { 81 | group.setTag(R.id.group_layouttransition_backup, null); 82 | group.setLayoutTransition(layoutTransition); 83 | } 84 | } 85 | } 86 | 87 | public boolean cancelLayoutTransition(@NonNull ViewGroup group) { 88 | final LayoutTransition layoutTransition = group.getLayoutTransition(); 89 | if (layoutTransition != null && layoutTransition.isRunning()) { 90 | if (sMethodLayoutTransitionCancel == null) { 91 | sMethodLayoutTransitionCancel = ReflectionUtils.getPrivateMethod(LayoutTransition.class, "cancel"); 92 | } 93 | ReflectionUtils.invoke(group.getLayoutTransition(), null, sMethodLayoutTransitionCancel); 94 | return true; 95 | } 96 | return false; 97 | } 98 | } 99 | 100 | @TargetApi(VERSION_CODES.JELLY_BEAN_MR2) 101 | static class JellyBeanMr2ViewGroupUtils extends BaseViewGroupUtils { 102 | 103 | @Nullable 104 | private static Method sMethodSuppressLayout; 105 | 106 | @Override 107 | public void suppressLayout(@NonNull ViewGroup group, boolean suppress) { 108 | if (sMethodSuppressLayout == null) { 109 | sMethodSuppressLayout = ReflectionUtils.getMethod(ViewGroup.class, "suppressLayout", boolean.class); 110 | } 111 | ReflectionUtils.invoke(group, null, sMethodSuppressLayout, suppress); 112 | } 113 | } 114 | 115 | @NonNull 116 | private static final BaseViewGroupUtils IMPL; 117 | 118 | static { 119 | if (Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR2) { 120 | IMPL = new JellyBeanMr2ViewGroupUtils(); 121 | } else { 122 | IMPL = new BaseViewGroupUtils(); 123 | } 124 | } 125 | 126 | public static void suppressLayout(@Nullable ViewGroup group, boolean suppress) { 127 | if (group != null) { 128 | IMPL.suppressLayout(group, suppress); 129 | } 130 | } 131 | 132 | /** 133 | * @return is cancel performed 134 | */ 135 | public static boolean cancelLayoutTransition(@Nullable ViewGroup group) { 136 | if (group != null) { 137 | return IMPL.cancelLayoutTransition(group); 138 | } else { 139 | return true; 140 | } 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /library(1.x)/src/main/java/com/transitionseverywhere/utils/ViewOverlayUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Andrey Kulikov (andkulikov@gmail.com) 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 com.transitionseverywhere.utils; 18 | 19 | import android.annotation.TargetApi; 20 | import android.graphics.drawable.Drawable; 21 | import android.os.Build; 22 | import android.support.annotation.NonNull; 23 | import android.view.ViewGroup; 24 | 25 | public class ViewOverlayUtils { 26 | 27 | static class BaseViewOverlayUtils { 28 | 29 | public void addOverlay(@NonNull ViewGroup sceneRoot, @NonNull Drawable drawable) { 30 | ViewOverlayPreJellybean viewOverlay = ViewOverlayPreJellybean.getOverlay(sceneRoot); 31 | viewOverlay.addDrawable(drawable); 32 | } 33 | 34 | public void removeOverlay(@NonNull ViewGroup sceneRoot, @NonNull Drawable drawable) { 35 | ViewOverlayPreJellybean viewOverlay = ViewOverlayPreJellybean.getOverlay(sceneRoot); 36 | viewOverlay.removeDrawable(drawable); 37 | } 38 | 39 | } 40 | 41 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) 42 | static class JellyBeanMR2ViewUtils extends BaseViewOverlayUtils { 43 | @Override 44 | public void addOverlay(@NonNull ViewGroup sceneRoot, @NonNull Drawable drawable) { 45 | sceneRoot.getOverlay().add(drawable); 46 | } 47 | 48 | @Override 49 | public void removeOverlay(@NonNull ViewGroup sceneRoot, @NonNull Drawable drawable) { 50 | sceneRoot.getOverlay().remove(drawable); 51 | } 52 | } 53 | 54 | @NonNull 55 | private static final BaseViewOverlayUtils IMPL; 56 | 57 | static { 58 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { 59 | IMPL = new JellyBeanMR2ViewUtils(); 60 | } else { 61 | IMPL = new BaseViewOverlayUtils(); 62 | } 63 | } 64 | 65 | public static void addOverlay(@NonNull ViewGroup sceneRoot, @NonNull Drawable drawable) { 66 | IMPL.addOverlay(sceneRoot, drawable); 67 | } 68 | 69 | public static void removeOverlay(@NonNull ViewGroup sceneRoot, @NonNull Drawable drawable) { 70 | IMPL.removeOverlay(sceneRoot, drawable); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /library(1.x)/src/main/java/com/transitionseverywhere/utils/ViewUtilsLollipop.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Andrey Kulikov (andkulikov@gmail.com) 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 com.transitionseverywhere.utils; 18 | 19 | import android.annotation.TargetApi; 20 | import android.graphics.Matrix; 21 | import android.os.Build; 22 | import android.support.annotation.NonNull; 23 | import android.support.annotation.Nullable; 24 | import android.view.View; 25 | import android.view.ViewGroup; 26 | 27 | import java.lang.reflect.Method; 28 | 29 | /** 30 | * Created by Andrey Kulikov on 20.10.14. 31 | */ 32 | @TargetApi(Build.VERSION_CODES.LOLLIPOP) 33 | class ViewUtilsLollipop extends ViewUtils.ViewUtilsKitKat { 34 | 35 | @Nullable 36 | private static final Class CLASS_GhostView = ReflectionUtils.getClass("android.view.GhostView"); 37 | @Nullable 38 | private static final Method METHOD_addGhost = ReflectionUtils.getMethod(CLASS_GhostView, 39 | "addGhost", View.class, ViewGroup.class, Matrix.class); 40 | @Nullable 41 | private static final Method METHOD_removeGhost = ReflectionUtils.getMethod(CLASS_GhostView, 42 | "removeGhost", View.class); 43 | @Nullable 44 | private static final Method METHOD_transformMatrixToGlobal = 45 | ReflectionUtils.getMethod(View.class, "transformMatrixToGlobal", Matrix.class); 46 | @Nullable 47 | private static final Method METHOD_transformMatrixToLocal = 48 | ReflectionUtils.getMethod(View.class, "transformMatrixToLocal", Matrix.class); 49 | @Nullable 50 | private static final Method METHOD_setAnimationMatrix = 51 | ReflectionUtils.getMethod(View.class, "setAnimationMatrix", Matrix.class); 52 | 53 | @Override 54 | public void transformMatrixToGlobal(@NonNull View view, @NonNull Matrix matrix) { 55 | ReflectionUtils.invoke(view, null, METHOD_transformMatrixToGlobal, matrix); 56 | } 57 | 58 | @Override 59 | public void transformMatrixToLocal(@NonNull View view, @NonNull Matrix matrix) { 60 | ReflectionUtils.invoke(view, null, METHOD_transformMatrixToLocal, matrix); 61 | } 62 | 63 | @Override 64 | public void setAnimationMatrix(@NonNull View view, @Nullable Matrix matrix) { 65 | ReflectionUtils.invoke(view, null, METHOD_setAnimationMatrix, matrix); 66 | } 67 | 68 | @Override 69 | @Nullable 70 | public View addGhostView(@NonNull View view, @NonNull ViewGroup viewGroup, @Nullable Matrix matrix) { 71 | return (View) ReflectionUtils.invoke(null, null, METHOD_addGhost, view, viewGroup, matrix); 72 | } 73 | 74 | @Override 75 | public void removeGhostView(@NonNull View view) { 76 | ReflectionUtils.invoke(view, null, METHOD_removeGhost, view); 77 | } 78 | 79 | @Override 80 | public void setTransitionName(@NonNull View v, @Nullable String name) { 81 | v.setTransitionName(name); 82 | } 83 | 84 | @Override 85 | @Nullable 86 | public String getTransitionName(@NonNull View v) { 87 | return v.getTransitionName(); 88 | } 89 | 90 | @Override 91 | public float getTranslationZ(@NonNull View view) { 92 | return view.getTranslationZ(); 93 | } 94 | 95 | @Override 96 | public void setTranslationZ(@NonNull View view, float z) { 97 | view.setTranslationZ(z); 98 | } 99 | } 100 | 101 | -------------------------------------------------------------------------------- /library(1.x)/src/main/java/com/transitionseverywhere/utils/ViewUtilsLollipopMr1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Andrey Kulikov (andkulikov@gmail.com) 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 com.transitionseverywhere.utils; 18 | 19 | import android.annotation.TargetApi; 20 | import android.graphics.PointF; 21 | import android.os.Build; 22 | import android.support.annotation.NonNull; 23 | import android.support.annotation.Nullable; 24 | import android.util.Property; 25 | import android.view.View; 26 | 27 | /** 28 | * Created by Andrey Kulikov on 10.07.16. 29 | */ 30 | @TargetApi(Build.VERSION_CODES.LOLLIPOP_MR1) 31 | class ViewUtilsLollipopMr1 extends ViewUtilsLollipop { 32 | 33 | @Nullable 34 | private static final Property POSITION_PROPERTY, BOTTOM_RIGHT_PROPERTY; 35 | private static final PointF TEMP_POINT_F = new PointF(); 36 | 37 | static { 38 | POSITION_PROPERTY = getChangeBoundsProperty("POSITION_PROPERTY"); 39 | BOTTOM_RIGHT_PROPERTY = getChangeBoundsProperty("BOTTOM_RIGHT_ONLY_PROPERTY"); 40 | } 41 | 42 | @SuppressWarnings("unchecked") 43 | private static Property getChangeBoundsProperty(String fieldName) { 44 | Object fieldValue = ReflectionUtils.getFieldValue(null, null, 45 | ReflectionUtils.getPrivateField(android.transition.ChangeBounds.class, fieldName)); 46 | if (fieldValue instanceof Property) { 47 | Property property = (Property) fieldValue; 48 | try { 49 | property.set(null, new PointF()); 50 | } catch (NullPointerException e) { 51 | // casted properly. NullPointerException because we've passed null View 52 | } catch (Exception e) { 53 | // something wrong with the property. we shouldn't use it. 54 | property = null; 55 | } 56 | return property; 57 | } else { 58 | return null; 59 | } 60 | } 61 | 62 | @Override 63 | public void setLeftTopRightBottom(@NonNull View v, int left, int top, int right, int bottom) { 64 | if (POSITION_PROPERTY != null && BOTTOM_RIGHT_PROPERTY != null) { 65 | TEMP_POINT_F.set(left, top); 66 | POSITION_PROPERTY.set(v, TEMP_POINT_F); 67 | TEMP_POINT_F.set(right, bottom); 68 | BOTTOM_RIGHT_PROPERTY.set(v, TEMP_POINT_F); 69 | } else { 70 | super.setLeftTopRightBottom(v, left, top, right, bottom); 71 | } 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /library(1.x)/src/main/res/values/ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /library/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion parent.ext.targetSdkVersion 5 | buildToolsVersion parent.ext.buildToolsVersion 6 | 7 | defaultConfig { 8 | minSdkVersion parent.ext.minSdkVersion 9 | targetSdkVersion parent.ext.targetSdkVersion 10 | versionCode 1 11 | versionName parent.ext.versionName 12 | } 13 | } 14 | 15 | dependencies { 16 | api ('androidx.annotation:annotation:1.1.0') 17 | api ('androidx.transition:transition:1.2.0') 18 | } 19 | 20 | //apply from: rootProject.file('library/gradle-mvn-push.gradle') -------------------------------------------------------------------------------- /library/gradle-mvn-push.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'maven' 2 | apply plugin: 'signing' 3 | 4 | def isReleaseBuild() { 5 | return VERSION_NAME.contains("SNAPSHOT") == false 6 | } 7 | 8 | def getReleaseRepositoryUrl() { 9 | return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL 10 | : "https://oss.sonatype.org/service/local/staging/deploy/maven2/" 11 | } 12 | 13 | def getSnapshotRepositoryUrl() { 14 | return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL 15 | : "https://oss.sonatype.org/content/repositories/snapshots/" 16 | } 17 | 18 | def getRepositoryUsername() { 19 | return hasProperty('SONATYPE_NEXUS_USERNAME') ? SONATYPE_NEXUS_USERNAME : "" 20 | } 21 | 22 | def getRepositoryPassword() { 23 | return hasProperty('SONATYPE_NEXUS_PASSWORD') ? SONATYPE_NEXUS_PASSWORD : "" 24 | } 25 | 26 | afterEvaluate { project -> 27 | uploadArchives { 28 | repositories { 29 | mavenDeployer { 30 | beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } 31 | 32 | pom.groupId = GROUP 33 | pom.artifactId = POM_ARTIFACT_ID 34 | pom.version = VERSION_NAME 35 | 36 | repository(url: getReleaseRepositoryUrl()) { 37 | authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) 38 | } 39 | snapshotRepository(url: getSnapshotRepositoryUrl()) { 40 | authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) 41 | } 42 | 43 | pom.project { 44 | name POM_NAME 45 | packaging POM_PACKAGING 46 | description POM_DESCRIPTION 47 | url POM_URL 48 | 49 | scm { 50 | url POM_SCM_URL 51 | connection POM_SCM_CONNECTION 52 | developerConnection POM_SCM_DEV_CONNECTION 53 | } 54 | 55 | licenses { 56 | license { 57 | name POM_LICENCE_NAME 58 | url POM_LICENCE_URL 59 | distribution POM_LICENCE_DIST 60 | } 61 | } 62 | 63 | developers { 64 | developer { 65 | id POM_DEVELOPER_ID 66 | name POM_DEVELOPER_NAME 67 | } 68 | } 69 | } 70 | 71 | } 72 | } 73 | } 74 | 75 | signing { 76 | required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") } 77 | sign configurations.archives 78 | } 79 | 80 | task androidJavadocs(type: Javadoc) { 81 | source = android.sourceSets.main.java.srcDirs 82 | ext.androidJar = "${android.sdkDirectory}/platforms/${android.compileSdkVersion}/android.jar" 83 | classpath += files(ext.androidJar) 84 | } 85 | 86 | android.libraryVariants.all { variant -> 87 | tasks.androidJavadocs.doFirst { 88 | classpath += files(variant.javaCompile.classpath.files) 89 | } 90 | } 91 | 92 | task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) { 93 | classifier = 'javadoc' 94 | from androidJavadocs.destinationDir 95 | } 96 | 97 | task androidSourcesJar(type: Jar) { 98 | classifier = 'sources' 99 | from android.sourceSets.main.java.sourceFiles 100 | } 101 | 102 | if (JavaVersion.current().isJava8Compatible()) { 103 | allprojects { 104 | tasks.withType(Javadoc) { 105 | options.addStringOption('Xdoclint:none', '-quiet') 106 | } 107 | } 108 | } 109 | 110 | artifacts { 111 | archives androidSourcesJar 112 | archives androidJavadocsJar 113 | } 114 | } -------------------------------------------------------------------------------- /library/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /library/src/main/java/android/util/FloatProperty.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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 | package android.util; 17 | 18 | import android.annotation.SuppressLint; 19 | 20 | import androidx.annotation.NonNull; 21 | import androidx.annotation.Nullable; 22 | 23 | /** 24 | * Dummy class. Permits to extend same hidden class from android framework. 25 | * Actually in runtime will be used class from android framework and ObjectAnimator 26 | * optimizations for FloatProperty will be applied. 27 | * 28 | * Created by Andrey Kulikov on 18.08.15. 29 | */ 30 | public abstract class FloatProperty extends Property { 31 | 32 | public FloatProperty(@Nullable String name) { 33 | super(Float.class, name); 34 | } 35 | 36 | public abstract void setValue(@NonNull T object, float value); 37 | 38 | @SuppressLint("NewApi") 39 | @Override 40 | final public void set(@NonNull T object, @NonNull Float value) { 41 | setValue(object, value); 42 | } 43 | 44 | @Override 45 | @NonNull 46 | public abstract Float get(@NonNull T object); 47 | 48 | } 49 | -------------------------------------------------------------------------------- /library/src/main/java/android/util/IntProperty.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Andrey Kulikov (andkulikov@gmail.com) 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 | /* 9 | * Copyright (C) 2011 The Android Open Source Project 10 | * 11 | * Licensed under the Apache License, Version 2.0 (the "License"); 12 | * you may not use this file except in compliance with the License. 13 | * You may obtain a copy of the License at 14 | * 15 | * http://www.apache.org/licenses/LICENSE-2.0 16 | * 17 | * Unless required by applicable law or agreed to in writing, software 18 | * distributed under the License is distributed on an "AS IS" BASIS, 19 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | * See the License for the specific language governing permissions and 21 | * limitations under the License. 22 | */ 23 | package android.util; 24 | 25 | import android.annotation.SuppressLint; 26 | 27 | import androidx.annotation.NonNull; 28 | import androidx.annotation.Nullable; 29 | 30 | /** 31 | * Dummy class. Permits to extend same hidden class from android framework. 32 | * Actually in runtime will be used class from android framework and ObjectAnimator 33 | * optimizations for IntProperty will be applied. 34 | * 35 | * Created by Andrey Kulikov on 18.08.15. 36 | */ 37 | public abstract class IntProperty extends Property { 38 | 39 | public IntProperty(@Nullable String name) { 40 | super(Integer.class, name); 41 | } 42 | 43 | public abstract void setValue(@NonNull T object, int value); 44 | 45 | @SuppressLint("NewApi") 46 | @Override 47 | final public void set(@NonNull T object, @NonNull Integer value) { 48 | setValue(object, value); 49 | } 50 | 51 | @Override 52 | @NonNull 53 | public abstract Integer get(@NonNull T object); 54 | 55 | } 56 | -------------------------------------------------------------------------------- /library/src/main/java/com/transitionseverywhere/Recolor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 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 com.transitionseverywhere; 18 | 19 | import android.animation.Animator; 20 | import android.animation.ArgbEvaluator; 21 | import android.animation.ObjectAnimator; 22 | import android.content.Context; 23 | import android.graphics.drawable.ColorDrawable; 24 | import android.graphics.drawable.Drawable; 25 | import android.util.AttributeSet; 26 | import android.util.Property; 27 | import android.view.View; 28 | import android.view.ViewGroup; 29 | import android.widget.TextView; 30 | 31 | import androidx.annotation.NonNull; 32 | import androidx.annotation.Nullable; 33 | import androidx.transition.Transition; 34 | import androidx.transition.TransitionValues; 35 | 36 | import com.transitionseverywhere.utils.IntProperty; 37 | import com.transitionseverywhere.utils.TransitionUtils; 38 | 39 | /** 40 | * This transition tracks changes during scene changes to the 41 | * {@link View#setBackground(android.graphics.drawable.Drawable) background} 42 | * property of its target views (when the background is a 43 | * {@link ColorDrawable}, as well as the 44 | * {@link TextView#setTextColor(android.content.res.ColorStateList) 45 | * color} of the text for target TextViews. If the color changes between 46 | * scenes, the color change is animated. 47 | */ 48 | public class Recolor extends Transition { 49 | 50 | private static final String PROPNAME_BACKGROUND = "android:recolor:background"; 51 | private static final String PROPNAME_TEXT_COLOR = "android:recolor:textColor"; 52 | private static final String[] sTransitionProperties = { 53 | PROPNAME_BACKGROUND, 54 | PROPNAME_TEXT_COLOR 55 | }; 56 | 57 | @NonNull 58 | public static final Property TEXTVIEW_TEXT_COLOR; 59 | @NonNull 60 | public static final Property COLORDRAWABLE_COLOR; 61 | 62 | static { 63 | TEXTVIEW_TEXT_COLOR = new IntProperty() { 64 | 65 | @Override 66 | public void setValue(@NonNull TextView object, int value) { 67 | object.setTextColor(value); 68 | } 69 | 70 | @NonNull 71 | @Override 72 | public Integer get(TextView object) { 73 | return 0; 74 | } 75 | 76 | }.optimize(); 77 | COLORDRAWABLE_COLOR = new IntProperty() { 78 | @Override 79 | public void setValue(@NonNull ColorDrawable object, int value) { 80 | object.setColor(value); 81 | } 82 | 83 | @NonNull 84 | @Override 85 | public Integer get(@NonNull ColorDrawable object) { 86 | return object.getColor(); 87 | } 88 | }.optimize(); 89 | } 90 | 91 | public Recolor() {} 92 | 93 | public Recolor(@NonNull Context context, @NonNull AttributeSet attrs) { 94 | super(context, attrs); 95 | } 96 | 97 | @Nullable 98 | @Override 99 | public String[] getTransitionProperties() { 100 | return sTransitionProperties; 101 | } 102 | 103 | private void captureValues(TransitionValues transitionValues) { 104 | transitionValues.values.put(PROPNAME_BACKGROUND, transitionValues.view.getBackground()); 105 | if (transitionValues.view instanceof TextView) { 106 | transitionValues.values.put(PROPNAME_TEXT_COLOR, 107 | ((TextView) transitionValues.view).getCurrentTextColor()); 108 | } 109 | } 110 | 111 | @Override 112 | public void captureStartValues(@NonNull TransitionValues transitionValues) { 113 | captureValues(transitionValues); 114 | } 115 | 116 | @Override 117 | public void captureEndValues(@NonNull TransitionValues transitionValues) { 118 | captureValues(transitionValues); 119 | } 120 | 121 | @Nullable 122 | @Override 123 | public Animator createAnimator(@NonNull ViewGroup sceneRoot, @Nullable TransitionValues startValues, 124 | @Nullable TransitionValues endValues) { 125 | if (startValues == null || endValues == null) { 126 | return null; 127 | } 128 | final View view = endValues.view; 129 | Drawable startBackground = (Drawable) startValues.values.get(PROPNAME_BACKGROUND); 130 | Drawable endBackground = (Drawable) endValues.values.get(PROPNAME_BACKGROUND); 131 | ObjectAnimator bgAnimator = null; 132 | if (startBackground instanceof ColorDrawable && endBackground instanceof ColorDrawable) { 133 | ColorDrawable startColor = (ColorDrawable) startBackground; 134 | ColorDrawable endColor = (ColorDrawable) endBackground; 135 | if (startColor.getColor() != endColor.getColor()) { 136 | final int finalColor = endColor.getColor(); 137 | endColor = (ColorDrawable) endColor.mutate(); 138 | endColor.setColor(startColor.getColor()); 139 | bgAnimator = ObjectAnimator.ofInt(endColor, COLORDRAWABLE_COLOR, startColor.getColor(), finalColor); 140 | bgAnimator.setEvaluator(new ArgbEvaluator()); 141 | } 142 | } 143 | ObjectAnimator textColorAnimator = null; 144 | if (view instanceof TextView) { 145 | TextView textView = (TextView) view; 146 | int start = (Integer) startValues.values.get(PROPNAME_TEXT_COLOR); 147 | int end = (Integer) endValues.values.get(PROPNAME_TEXT_COLOR); 148 | if (start != end) { 149 | textView.setTextColor(end); 150 | textColorAnimator = ObjectAnimator.ofInt(textView, TEXTVIEW_TEXT_COLOR, start, end); 151 | textColorAnimator.setEvaluator(new ArgbEvaluator()); 152 | } 153 | } 154 | return TransitionUtils.mergeAnimators(bgAnimator, textColorAnimator); 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /library/src/main/java/com/transitionseverywhere/Rotate.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 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 com.transitionseverywhere; 18 | 19 | import android.animation.Animator; 20 | import android.animation.ObjectAnimator; 21 | import android.view.View; 22 | import android.view.ViewGroup; 23 | 24 | import androidx.annotation.NonNull; 25 | import androidx.annotation.Nullable; 26 | import androidx.transition.Transition; 27 | import androidx.transition.TransitionValues; 28 | 29 | /** 30 | * This transition captures the rotation property of targets before and after 31 | * the scene change and animates any changes. 32 | */ 33 | public class Rotate extends Transition { 34 | 35 | private static final String PROPNAME_ROTATION = "android:rotate:rotation"; 36 | private static final String[] sTransitionProperties = { 37 | PROPNAME_ROTATION 38 | }; 39 | 40 | @Nullable 41 | @Override 42 | public String[] getTransitionProperties() { 43 | return sTransitionProperties; 44 | } 45 | 46 | @Override 47 | public void captureStartValues(@NonNull TransitionValues transitionValues) { 48 | transitionValues.values.put(PROPNAME_ROTATION, transitionValues.view.getRotation()); 49 | } 50 | 51 | @Override 52 | public void captureEndValues(@NonNull TransitionValues transitionValues) { 53 | transitionValues.values.put(PROPNAME_ROTATION, transitionValues.view.getRotation()); 54 | } 55 | 56 | @Nullable 57 | @Override 58 | public Animator createAnimator(@NonNull ViewGroup sceneRoot, @Nullable TransitionValues startValues, 59 | @Nullable TransitionValues endValues) { 60 | if (startValues == null || endValues == null) { 61 | return null; 62 | } 63 | final View view = endValues.view; 64 | float startRotation = (Float) startValues.values.get(PROPNAME_ROTATION); 65 | float endRotation = (Float) endValues.values.get(PROPNAME_ROTATION); 66 | if (startRotation != endRotation) { 67 | view.setRotation(startRotation); 68 | return ObjectAnimator.ofFloat(view, View.ROTATION, 69 | startRotation, endRotation); 70 | } 71 | return null; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /library/src/main/java/com/transitionseverywhere/extra/Scale.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Andrey Kulikov (andkulikov@gmail.com) 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 | package com.transitionseverywhere.extra; 17 | 18 | import android.animation.Animator; 19 | import android.animation.ObjectAnimator; 20 | import android.content.Context; 21 | import android.content.res.TypedArray; 22 | import android.util.AttributeSet; 23 | import android.view.View; 24 | import android.view.ViewGroup; 25 | 26 | import com.transitionseverywhere.R; 27 | import com.transitionseverywhere.utils.TransitionUtils; 28 | 29 | import androidx.annotation.NonNull; 30 | import androidx.annotation.Nullable; 31 | import androidx.transition.Transition; 32 | import androidx.transition.TransitionListenerAdapter; 33 | import androidx.transition.TransitionValues; 34 | import androidx.transition.Visibility; 35 | 36 | /** 37 | * This transition tracks changes to the visibility of target views in the 38 | * start and end scenes and scales views up or down. Visibility is determined by both the 39 | * {@link View#setVisibility(int)} state of the view as well as whether it 40 | * is parented in the current view hierarchy. Disappearing Views are 41 | * limited as described in {@link Visibility#onDisappear(android.view.ViewGroup, 42 | * TransitionValues, int, TransitionValues, int)}. 43 | *

44 | * Created by Andrey Kulikov on 13/03/16. 45 | */ 46 | public class Scale extends Visibility { 47 | 48 | static final String PROPNAME_SCALE_X = "scale:scaleX"; 49 | static final String PROPNAME_SCALE_Y = "scale:scaleY"; 50 | 51 | private float mDisappearedScale = 0f; 52 | 53 | public Scale() { 54 | } 55 | 56 | /** 57 | * @param disappearedScale Value of scale on start of appearing or in finish of disappearing. 58 | * Default value is 0. Can be useful for mixing some Visibility 59 | * transitions, for example Scale and Fade 60 | */ 61 | public Scale(float disappearedScale) { 62 | setDisappearedScale(disappearedScale); 63 | } 64 | 65 | @Override 66 | public void captureStartValues(@NonNull TransitionValues transitionValues) { 67 | super.captureStartValues(transitionValues); 68 | transitionValues.values.put(PROPNAME_SCALE_X, transitionValues.view.getScaleX()); 69 | transitionValues.values.put(PROPNAME_SCALE_Y, transitionValues.view.getScaleY()); 70 | } 71 | 72 | /** 73 | * @param disappearedScale Value of scale on start of appearing or in finish of disappearing. 74 | * Default value is 0. Can be useful for mixing some Visibility 75 | * transitions, for example Scale and Fade 76 | * @return This Scale object. 77 | */ 78 | @NonNull 79 | public Scale setDisappearedScale(float disappearedScale) { 80 | if (disappearedScale < 0f) { 81 | throw new IllegalArgumentException("disappearedScale cannot be negative!"); 82 | } 83 | mDisappearedScale = disappearedScale; 84 | return this; 85 | } 86 | 87 | public Scale(@NonNull Context context, @NonNull AttributeSet attrs) { 88 | super(context, attrs); 89 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Scale); 90 | setDisappearedScale(a.getFloat(R.styleable.Scale_disappearedScale, mDisappearedScale)); 91 | a.recycle(); 92 | } 93 | 94 | @Nullable 95 | private Animator createAnimation(@NonNull final View view, float startScale, float endScale, @Nullable TransitionValues values) { 96 | final float initialScaleX = view.getScaleX(); 97 | final float initialScaleY = view.getScaleY(); 98 | float startScaleX = initialScaleX * startScale; 99 | float endScaleX = initialScaleX * endScale; 100 | float startScaleY = initialScaleY * startScale; 101 | float endScaleY = initialScaleY * endScale; 102 | 103 | if (values != null) { 104 | Float savedScaleX = (Float) values.values.get(PROPNAME_SCALE_X); 105 | Float savedScaleY = (Float) values.values.get(PROPNAME_SCALE_Y); 106 | // if saved value is not equal initial value it means that previous 107 | // transition was interrupted and in the onTransitionEnd 108 | // we've applied endScale. we should apply proper value to 109 | // continue animation from the interrupted state 110 | if (savedScaleX != null && savedScaleX != initialScaleX) { 111 | startScaleX = savedScaleX; 112 | } 113 | if (savedScaleY != null && savedScaleY != initialScaleY) { 114 | startScaleY = savedScaleY; 115 | } 116 | } 117 | 118 | view.setScaleX(startScaleX); 119 | view.setScaleY(startScaleY); 120 | 121 | Animator animator = TransitionUtils.mergeAnimators( 122 | ObjectAnimator.ofFloat(view, View.SCALE_X, startScaleX, endScaleX), 123 | ObjectAnimator.ofFloat(view, View.SCALE_Y, startScaleY, endScaleY)); 124 | addListener(new TransitionListenerAdapter() { 125 | @Override 126 | public void onTransitionEnd(@NonNull Transition transition) { 127 | view.setScaleX(initialScaleX); 128 | view.setScaleY(initialScaleY); 129 | transition.removeListener(this); 130 | } 131 | }); 132 | return animator; 133 | } 134 | 135 | @Nullable 136 | @Override 137 | public Animator onAppear(@NonNull ViewGroup sceneRoot, @NonNull final View view, @Nullable TransitionValues startValues, 138 | @Nullable TransitionValues endValues) { 139 | return createAnimation(view, mDisappearedScale, 1f, startValues); 140 | } 141 | 142 | @Override 143 | public Animator onDisappear(@NonNull ViewGroup sceneRoot, @NonNull final View view, @Nullable TransitionValues startValues, 144 | @Nullable TransitionValues endValues) { 145 | return createAnimation(view, 1f, mDisappearedScale, startValues); 146 | } 147 | 148 | } 149 | -------------------------------------------------------------------------------- /library/src/main/java/com/transitionseverywhere/extra/Translation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Andrey Kulikov (andkulikov@gmail.com) 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 | package com.transitionseverywhere.extra; 17 | 18 | import android.animation.Animator; 19 | import android.animation.ObjectAnimator; 20 | import android.annotation.TargetApi; 21 | import android.content.Context; 22 | import android.graphics.Path; 23 | import android.graphics.PointF; 24 | import android.os.Build; 25 | import android.util.AttributeSet; 26 | import android.util.Property; 27 | import android.view.View; 28 | import android.view.ViewGroup; 29 | 30 | import androidx.annotation.NonNull; 31 | import androidx.annotation.Nullable; 32 | import androidx.transition.Transition; 33 | import androidx.transition.TransitionValues; 34 | 35 | import com.transitionseverywhere.utils.TransitionUtils; 36 | 37 | /** 38 | * This transition tracks changes to the translationX and translationY of 39 | * target views in the start and end scenes and animates change. 40 | *

41 | * Created by Andrey Kulikov on 13/03/16. 42 | */ 43 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 44 | public class Translation extends Transition { 45 | 46 | private static final String TRANSLATION_X = "Translation:translationX"; 47 | private static final String TRANSLATION_Y = "Translation:translationY"; 48 | private static final String[] sTransitionProperties = { 49 | TRANSLATION_X, 50 | TRANSLATION_Y 51 | }; 52 | 53 | @Nullable 54 | private static final Property TRANSLATION_PROPERTY; 55 | 56 | static { 57 | if (Build.VERSION.SDK_INT >= 21) { 58 | TRANSLATION_PROPERTY = new Property(PointF.class, "translation") { 59 | 60 | @Override 61 | public void set(@NonNull View object, @NonNull PointF value) { 62 | object.setTranslationX(value.x); 63 | object.setTranslationY(value.y); 64 | } 65 | 66 | @Override 67 | public PointF get(@NonNull View object) { 68 | return new PointF(object.getTranslationX(), object.getTranslationY()); 69 | } 70 | }; 71 | } else { 72 | TRANSLATION_PROPERTY = null; 73 | } 74 | } 75 | 76 | public Translation() { 77 | } 78 | 79 | public Translation(@NonNull Context context, @NonNull AttributeSet attrs) { 80 | super(context, attrs); 81 | } 82 | 83 | @Nullable 84 | @Override 85 | public String[] getTransitionProperties() { 86 | return sTransitionProperties; 87 | } 88 | 89 | private void captureValues(@NonNull TransitionValues transitionValues) { 90 | transitionValues.values.put(TRANSLATION_X, transitionValues.view.getTranslationX()); 91 | transitionValues.values.put(TRANSLATION_Y, transitionValues.view.getTranslationY()); 92 | } 93 | 94 | @Override 95 | public void captureStartValues(@NonNull TransitionValues transitionValues) { 96 | captureValues(transitionValues); 97 | } 98 | 99 | @Override 100 | public void captureEndValues(@NonNull TransitionValues transitionValues) { 101 | captureValues(transitionValues); 102 | } 103 | 104 | @Nullable 105 | @Override 106 | public Animator createAnimator(@NonNull ViewGroup sceneRoot, @Nullable TransitionValues startValues, 107 | @Nullable TransitionValues endValues) { 108 | if (startValues != null && endValues != null) { 109 | float startX = (float) startValues.values.get(TRANSLATION_X); 110 | float startY = (float) startValues.values.get(TRANSLATION_Y); 111 | float endX = (float) endValues.values.get(TRANSLATION_X); 112 | float endY = (float) endValues.values.get(TRANSLATION_Y); 113 | endValues.view.setTranslationX(startX); 114 | endValues.view.setTranslationY(startY); 115 | if (Build.VERSION.SDK_INT >= 21 && TRANSLATION_PROPERTY != null) { 116 | Path path = getPathMotion().getPath(startX, startY, endX, endY); 117 | return ObjectAnimator.ofObject(endValues.view, TRANSLATION_PROPERTY, null, path); 118 | } else { 119 | Animator x = (startX == endX) ? null : 120 | ObjectAnimator.ofFloat(endValues.view, View.TRANSLATION_X, startX, endX); 121 | Animator y = (startY == endY) ? null : 122 | ObjectAnimator.ofFloat(endValues.view, View.TRANSLATION_Y, startY, endY); 123 | return TransitionUtils.mergeAnimators(x, y); 124 | } 125 | } else { 126 | return null; 127 | } 128 | } 129 | 130 | } -------------------------------------------------------------------------------- /library/src/main/java/com/transitionseverywhere/utils/FloatProperty.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Andrey Kulikov (andkulikov@gmail.com) 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 | package com.transitionseverywhere.utils; 17 | 18 | import android.annotation.SuppressLint; 19 | 20 | import androidx.annotation.NonNull; 21 | 22 | /** 23 | * It's great idea to extend it for any properties that works with float fields 24 | * because ObjectAnimator have optimizations for FloatProperty to avoid autoboxing. 25 | * 26 | * Created by Andrey Kulikov on 17/04/16. 27 | */ 28 | @SuppressLint("NewApi, Override") 29 | public abstract class FloatProperty extends android.util.FloatProperty { 30 | 31 | public FloatProperty() { 32 | super(null); 33 | // null instead of name here because it's used only for calling setter 34 | // and getter via reflection. but we have our own overridden set and get. 35 | } 36 | 37 | /** 38 | * Just default implementation. Some of properties can have no getter. Override for real getter 39 | */ 40 | @Override 41 | @NonNull 42 | public Float get(@NonNull T object) { 43 | return 0f; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /library/src/main/java/com/transitionseverywhere/utils/IntProperty.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Andrey Kulikov (andkulikov@gmail.com) 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 | package com.transitionseverywhere.utils; 17 | 18 | import android.annotation.SuppressLint; 19 | import android.annotation.TargetApi; 20 | import android.os.Build; 21 | import android.util.Property; 22 | 23 | import androidx.annotation.NonNull; 24 | 25 | /** 26 | * Helper class for properties with int values. 27 | * Unfortunately we can't just extend android.util.IntProperty here, 28 | * because of a bug that was fixed only in 4.2.2: 29 | * https://android.googlesource.com/platform/frameworks/base/+/c5d43f76fd7c3ccb91f1b75618a9c9e8f202505b 30 | *

31 | * To apply internal optimizations to avoid autoboxing use object that will be 32 | * returned by method {@link #optimize()} 33 | *

34 | * Created by Andrey Kulikov on 17/04/16. 35 | */ 36 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 37 | public abstract class IntProperty extends Property { 38 | 39 | public IntProperty() { 40 | super(Integer.class, null); 41 | } 42 | 43 | public abstract void setValue(@NonNull T object, int value); 44 | 45 | @Override 46 | final public void set(@NonNull T object, @NonNull Integer value) { 47 | setValue(object, value); 48 | } 49 | 50 | /** 51 | * Just default implementation. Some of properties can have no getter. Override for real getter 52 | */ 53 | @Override 54 | @NonNull 55 | public Integer get(T object) { 56 | return 0; 57 | } 58 | 59 | @SuppressLint("NewApi") 60 | @NonNull 61 | public Property optimize() { 62 | if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2) { 63 | return new android.util.IntProperty(null) { 64 | @Override 65 | public void setValue(@NonNull T object, int value) { 66 | IntProperty.this.setValue(object, value); 67 | } 68 | 69 | @Override 70 | @NonNull 71 | public Integer get(@NonNull T object) { 72 | return IntProperty.this.get(object); 73 | } 74 | }; 75 | } else { 76 | return this; 77 | } 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /library/src/main/java/com/transitionseverywhere/utils/TransitionUtils.java: -------------------------------------------------------------------------------- 1 | package com.transitionseverywhere.utils; 2 | 3 | import android.animation.Animator; 4 | import android.animation.AnimatorSet; 5 | import android.annotation.TargetApi; 6 | import android.os.Build; 7 | 8 | import androidx.annotation.Nullable; 9 | 10 | /** 11 | * Static utility methods for Transitions. 12 | */ 13 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 14 | public class TransitionUtils { 15 | 16 | @Nullable 17 | public static Animator mergeAnimators(@Nullable Animator animator1, @Nullable Animator animator2) { 18 | if (animator1 == null) { 19 | return animator2; 20 | } else if (animator2 == null) { 21 | return animator1; 22 | } else { 23 | AnimatorSet animatorSet = new AnimatorSet(); 24 | animatorSet.playTogether(animator1, animator2); 25 | return animatorSet; 26 | } 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /library/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /sample/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | dependencies { 4 | implementation project(':library') 5 | implementation 'androidx.appcompat:appcompat:1.0.2' 6 | implementation 'androidx.recyclerview:recyclerview:1.0.0' 7 | } 8 | 9 | android { 10 | compileSdkVersion parent.ext.targetSdkVersion 11 | buildToolsVersion parent.ext.buildToolsVersion 12 | 13 | defaultConfig { 14 | minSdkVersion 14 15 | targetSdkVersion parent.ext.targetSdkVersion 16 | versionCode 1 17 | versionName parent.ext.versionName 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /sample/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /sample/src/main/java/com/andkulikov/transitionseverywhere/AutoTransitionSample.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Andrey Kulikov (andkulikov@gmail.com) 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 | package com.andkulikov.transitionseverywhere; 17 | 18 | import android.os.Bundle; 19 | import android.view.LayoutInflater; 20 | import android.view.View; 21 | import android.view.ViewGroup; 22 | import android.widget.TextView; 23 | 24 | import androidx.annotation.Nullable; 25 | import androidx.fragment.app.Fragment; 26 | import androidx.transition.TransitionManager; 27 | 28 | /** 29 | * Created by Andrey Kulikov on 20/03/16. 30 | */ 31 | public class AutoTransitionSample extends Fragment { 32 | 33 | @Nullable 34 | @Override 35 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 36 | View view = inflater.inflate(R.layout.fragment_autotransition, container, false); 37 | 38 | final ViewGroup transitionsContainer = view.findViewById(R.id.transitions_container); 39 | final TextView text = transitionsContainer.findViewById(R.id.text); 40 | 41 | transitionsContainer.findViewById(R.id.button).setOnClickListener(new VisibleToggleClickListener() { 42 | 43 | @Override 44 | protected void changeVisibility(boolean visible) { 45 | TransitionManager.beginDelayedTransition(transitionsContainer); 46 | // it is the same as 47 | // TransitionManager.beginDelayedTransition(transitionsContainer, new AutoTransition()); 48 | // where AutoTransition is the set of Fade and ChangeBounds transitions 49 | text.setVisibility(visible ? View.VISIBLE : View.GONE); 50 | } 51 | 52 | }); 53 | 54 | return view; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /sample/src/main/java/com/andkulikov/transitionseverywhere/ChangeTextSample.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Andrey Kulikov (andkulikov@gmail.com) 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 | package com.andkulikov.transitionseverywhere; 17 | 18 | import android.os.Bundle; 19 | import android.view.LayoutInflater; 20 | import android.view.View; 21 | import android.view.ViewGroup; 22 | import android.widget.TextView; 23 | 24 | import com.transitionseverywhere.ChangeText; 25 | 26 | import androidx.annotation.Nullable; 27 | import androidx.fragment.app.Fragment; 28 | import androidx.transition.TransitionManager; 29 | 30 | /** 31 | * Created by Andrey Kulikov on 17/04/16. 32 | */ 33 | public class ChangeTextSample extends Fragment { 34 | 35 | public static final String TEXT_1 = "Hi, i am text. Tap on me!"; 36 | public static final String TEXT_2 = "Thanks! Another tap?"; 37 | 38 | @Nullable 39 | @Override 40 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 41 | View view = inflater.inflate(R.layout.fragment_change_text, container, false); 42 | 43 | final ViewGroup transitionsContainer = view.findViewById(R.id.transitions_container); 44 | final TextView textView = transitionsContainer.findViewById(R.id.text1); 45 | 46 | textView.setText(TEXT_1); 47 | textView.setOnClickListener(new View.OnClickListener() { 48 | 49 | boolean mSecondText; 50 | 51 | @Override 52 | public void onClick(View v) { 53 | mSecondText = !mSecondText; 54 | TransitionManager.beginDelayedTransition(transitionsContainer, 55 | new ChangeText().setChangeBehavior(ChangeText.CHANGE_BEHAVIOR_OUT_IN)); 56 | textView.setText(mSecondText ? TEXT_2 : TEXT_1); 57 | } 58 | 59 | }); 60 | 61 | return view; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /sample/src/main/java/com/andkulikov/transitionseverywhere/CustomTransitionSample.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Andrey Kulikov (andkulikov@gmail.com) 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 | package com.andkulikov.transitionseverywhere; 17 | 18 | import android.animation.Animator; 19 | import android.animation.ObjectAnimator; 20 | import android.os.Bundle; 21 | import android.util.Property; 22 | import android.view.LayoutInflater; 23 | import android.view.View; 24 | import android.view.ViewGroup; 25 | import android.widget.ProgressBar; 26 | 27 | import com.transitionseverywhere.utils.IntProperty; 28 | 29 | import androidx.annotation.Nullable; 30 | import androidx.fragment.app.Fragment; 31 | import androidx.transition.Transition; 32 | import androidx.transition.TransitionManager; 33 | import androidx.transition.TransitionValues; 34 | 35 | /** 36 | * Created by Andrey Kulikov on 17/04/16. 37 | */ 38 | public class CustomTransitionSample extends Fragment { 39 | 40 | private ViewGroup mTransitionsContainer; 41 | private ProgressBar mProgressBar; 42 | 43 | @Nullable 44 | @Override 45 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 46 | View view = inflater.inflate(R.layout.fragment_custom, container, false); 47 | 48 | mTransitionsContainer = view.findViewById(R.id.transitions_container); 49 | mProgressBar = view.findViewById(R.id.progress_bar); 50 | 51 | view.findViewById(R.id.button1).setOnClickListener(new View.OnClickListener() { 52 | @Override 53 | public void onClick(View v) { 54 | setProgress(mProgressBar.getProgress() - 20); 55 | } 56 | }); 57 | view.findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() { 58 | @Override 59 | public void onClick(View v) { 60 | setProgress(mProgressBar.getProgress() + 30); 61 | } 62 | }); 63 | 64 | return view; 65 | } 66 | 67 | private void setProgress(int value) { 68 | TransitionManager.beginDelayedTransition(mTransitionsContainer, new ProgressTransition()); 69 | value = Math.max(0, Math.min(100, value)); 70 | mProgressBar.setProgress(value); 71 | } 72 | 73 | private static class ProgressTransition extends Transition { 74 | 75 | /** 76 | * Property is like a helper that contain setter and getter in one place 77 | */ 78 | private static final Property PROGRESS_PROPERTY = new IntProperty() { 79 | 80 | @Override 81 | public void setValue(ProgressBar progressBar, int value) { 82 | progressBar.setProgress(value); 83 | } 84 | 85 | @Override 86 | public Integer get(ProgressBar progressBar) { 87 | return progressBar.getProgress(); 88 | } 89 | }.optimize(); 90 | 91 | /** 92 | * Internal name of property. Like a bundles for intent 93 | */ 94 | private static final String PROPNAME_PROGRESS = "ProgressTransition:progress"; 95 | 96 | @Override 97 | public void captureStartValues(TransitionValues transitionValues) { 98 | captureValues(transitionValues); 99 | } 100 | 101 | @Override 102 | public void captureEndValues(TransitionValues transitionValues) { 103 | captureValues(transitionValues); 104 | } 105 | 106 | private void captureValues(TransitionValues transitionValues) { 107 | if (transitionValues.view instanceof ProgressBar) { 108 | // save current progress in the values map 109 | ProgressBar progressBar = ((ProgressBar) transitionValues.view); 110 | transitionValues.values.put(PROPNAME_PROGRESS, progressBar.getProgress()); 111 | } 112 | } 113 | 114 | @Override 115 | public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues, TransitionValues endValues) { 116 | if (startValues != null && endValues != null && endValues.view instanceof ProgressBar) { 117 | ProgressBar progressBar = (ProgressBar) endValues.view; 118 | int start = (Integer) startValues.values.get(PROPNAME_PROGRESS); 119 | int end = (Integer) endValues.values.get(PROPNAME_PROGRESS); 120 | if (start != end) { 121 | // first of all we need to return the start value, because right now 122 | // the view is have the end value 123 | progressBar.setProgress(start); 124 | // create animator with our progressBar, property and end value 125 | return ObjectAnimator.ofInt(progressBar, PROGRESS_PROPERTY, end); 126 | } 127 | } 128 | return null; 129 | } 130 | } 131 | 132 | } 133 | -------------------------------------------------------------------------------- /sample/src/main/java/com/andkulikov/transitionseverywhere/ExplodeAndEpicenterExample.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Andrey Kulikov (andkulikov@gmail.com) 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 | package com.andkulikov.transitionseverywhere; 17 | 18 | import android.graphics.Rect; 19 | import android.os.Bundle; 20 | import android.view.LayoutInflater; 21 | import android.view.View; 22 | import android.view.ViewGroup; 23 | 24 | import androidx.annotation.Nullable; 25 | import androidx.fragment.app.Fragment; 26 | import androidx.recyclerview.widget.GridLayoutManager; 27 | import androidx.recyclerview.widget.RecyclerView; 28 | import androidx.transition.Explode; 29 | import androidx.transition.Fade; 30 | import androidx.transition.Transition; 31 | import androidx.transition.TransitionListenerAdapter; 32 | import androidx.transition.TransitionManager; 33 | import androidx.transition.TransitionSet; 34 | 35 | /** 36 | * Created by Andrey Kulikov on 25/03/16. 37 | */ 38 | public class ExplodeAndEpicenterExample extends Fragment { 39 | 40 | private RecyclerView mRecyclerView; 41 | 42 | @Nullable 43 | @Override 44 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 45 | mRecyclerView = new RecyclerView(container.getContext()); 46 | mRecyclerView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 47 | ViewGroup.LayoutParams.MATCH_PARENT)); 48 | mRecyclerView.setLayoutManager(new GridLayoutManager(container.getContext(), 4)); 49 | mRecyclerView.setAdapter(new Adapter()); 50 | return mRecyclerView; 51 | } 52 | 53 | private void letsExplodeIt(View clickedView) { 54 | // save rect of view in screen coordinated 55 | final Rect viewRect = new Rect(); 56 | clickedView.getGlobalVisibleRect(viewRect); 57 | 58 | final Explode explode = new Explode(); 59 | explode.setEpicenterCallback(new Transition.EpicenterCallback() { 60 | @Override 61 | public Rect onGetEpicenter(Transition transition) { 62 | return viewRect; 63 | } 64 | }); 65 | explode.excludeTarget(clickedView, true); 66 | TransitionSet set = new TransitionSet() 67 | .addTransition(explode) 68 | .addTransition(new Fade().addTarget(clickedView)) 69 | .addListener(new TransitionListenerAdapter() { 70 | @Override 71 | public void onTransitionEnd(Transition transition) { 72 | transition.removeListener(this); 73 | getActivity().onBackPressed(); 74 | } 75 | }); 76 | TransitionManager.beginDelayedTransition(mRecyclerView, set); 77 | 78 | // remove all views from Recycler View 79 | mRecyclerView.setAdapter(null); 80 | } 81 | 82 | private class Adapter extends RecyclerView.Adapter { 83 | 84 | @Override 85 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 86 | return new ViewHolder( 87 | LayoutInflater.from(parent.getContext()) 88 | .inflate(R.layout.explode_item, parent, false)); 89 | } 90 | 91 | @Override 92 | public void onBindViewHolder(ViewHolder holder, final int position) { 93 | holder.itemView.setOnClickListener(new View.OnClickListener() { 94 | @Override 95 | public void onClick(View clickedView) { 96 | letsExplodeIt(clickedView); 97 | } 98 | }); 99 | } 100 | 101 | @Override 102 | public int getItemCount() { 103 | return 32; 104 | } 105 | } 106 | 107 | private class ViewHolder extends RecyclerView.ViewHolder { 108 | 109 | public ViewHolder(View view) { 110 | super(view); 111 | } 112 | 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /sample/src/main/java/com/andkulikov/transitionseverywhere/ImageTransformSample.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Andrey Kulikov (andkulikov@gmail.com) 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 | package com.andkulikov.transitionseverywhere; 17 | 18 | import android.os.Bundle; 19 | import android.view.LayoutInflater; 20 | import android.view.View; 21 | import android.view.ViewGroup; 22 | import android.widget.ImageView; 23 | 24 | import androidx.annotation.Nullable; 25 | import androidx.fragment.app.Fragment; 26 | import androidx.transition.ChangeBounds; 27 | import androidx.transition.ChangeImageTransform; 28 | import androidx.transition.TransitionManager; 29 | import androidx.transition.TransitionSet; 30 | 31 | /** 32 | * Created by Andrey Kulikov on 20/03/16. 33 | */ 34 | public class ImageTransformSample extends Fragment { 35 | 36 | @Nullable 37 | @Override 38 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 39 | View view = inflater.inflate(R.layout.fragment_image_transform, container, false); 40 | 41 | final ViewGroup transitionsContainer = view.findViewById(R.id.transitions_container); 42 | final ImageView imageView = transitionsContainer.findViewById(R.id.image); 43 | 44 | imageView.setOnClickListener(new View.OnClickListener() { 45 | 46 | boolean mExpanded; 47 | 48 | @Override 49 | public void onClick(View v) { 50 | mExpanded = !mExpanded; 51 | 52 | TransitionManager.beginDelayedTransition(transitionsContainer, new TransitionSet() 53 | .addTransition(new ChangeBounds()) 54 | .addTransition(new ChangeImageTransform())); 55 | 56 | ViewGroup.LayoutParams params = imageView.getLayoutParams(); 57 | params.height = mExpanded ? ViewGroup.LayoutParams.MATCH_PARENT : ViewGroup.LayoutParams.WRAP_CONTENT; 58 | imageView.setLayoutParams(params); 59 | 60 | imageView.setScaleType(mExpanded ? ImageView.ScaleType.CENTER_CROP : ImageView.ScaleType.FIT_CENTER); 61 | } 62 | }); 63 | 64 | return view; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /sample/src/main/java/com/andkulikov/transitionseverywhere/InterpolatorDurationStartDelaySample.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Andrey Kulikov (andkulikov@gmail.com) 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 | package com.andkulikov.transitionseverywhere; 17 | 18 | import android.annotation.TargetApi; 19 | import android.os.Build; 20 | import android.os.Bundle; 21 | import android.view.Gravity; 22 | import android.view.LayoutInflater; 23 | import android.view.View; 24 | import android.view.ViewGroup; 25 | import android.view.animation.AccelerateInterpolator; 26 | import android.widget.FrameLayout; 27 | 28 | import androidx.annotation.Nullable; 29 | import androidx.fragment.app.Fragment; 30 | import androidx.interpolator.view.animation.FastOutSlowInInterpolator; 31 | import androidx.transition.ChangeBounds; 32 | import androidx.transition.Transition; 33 | import androidx.transition.TransitionManager; 34 | 35 | /** 36 | * Created by Andrey Kulikov on 17/04/16. 37 | */ 38 | @TargetApi(Build.VERSION_CODES.HONEYCOMB) 39 | public class InterpolatorDurationStartDelaySample extends Fragment { 40 | 41 | @Nullable 42 | @Override 43 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 44 | View view = inflater.inflate(R.layout.fragment_interpolator, container, false); 45 | 46 | final ViewGroup transitionsContainer = view.findViewById(R.id.transitions_container); 47 | final View button = transitionsContainer.findViewById(R.id.button); 48 | 49 | button.setOnClickListener(new View.OnClickListener() { 50 | 51 | boolean mToRightAnimation; 52 | 53 | @Override 54 | public void onClick(View v) { 55 | mToRightAnimation = !mToRightAnimation; 56 | 57 | Transition transition = new ChangeBounds(); 58 | transition.setDuration(mToRightAnimation ? 700 : 300); 59 | transition.setInterpolator(mToRightAnimation ? new FastOutSlowInInterpolator() : new AccelerateInterpolator()); 60 | transition.setStartDelay(mToRightAnimation ? 0 : 500); 61 | TransitionManager.beginDelayedTransition(transitionsContainer, transition); 62 | 63 | FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) button.getLayoutParams(); 64 | params.gravity = mToRightAnimation ? (Gravity.RIGHT | Gravity.TOP) : (Gravity.LEFT | Gravity.TOP); 65 | button.setLayoutParams(params); 66 | } 67 | 68 | }); 69 | 70 | return view; 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /sample/src/main/java/com/andkulikov/transitionseverywhere/ListFragment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Andrey Kulikov (andkulikov@gmail.com) 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 | package com.andkulikov.transitionseverywhere; 17 | 18 | import android.os.Bundle; 19 | import android.view.LayoutInflater; 20 | import android.view.View; 21 | import android.view.ViewGroup; 22 | import android.widget.TextView; 23 | 24 | import androidx.annotation.Nullable; 25 | import androidx.fragment.app.Fragment; 26 | import androidx.recyclerview.widget.LinearLayoutManager; 27 | import androidx.recyclerview.widget.RecyclerView; 28 | 29 | /** 30 | * Created by Andrey Kulikov on 20/03/16. 31 | */ 32 | public class ListFragment extends Fragment { 33 | 34 | private SampleListProvider mSampleProvider; 35 | 36 | @Nullable 37 | @Override 38 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 39 | RecyclerView view = (RecyclerView) inflater.inflate(R.layout.fragment_list, container, false); 40 | view.setLayoutManager(new LinearLayoutManager(container.getContext())); 41 | view.setAdapter(new Adapter()); 42 | return view; 43 | } 44 | 45 | public void setSampleListListener(SampleListProvider sampleSelectedListener) { 46 | mSampleProvider = sampleSelectedListener; 47 | } 48 | 49 | private class Adapter extends RecyclerView.Adapter { 50 | 51 | @Override 52 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 53 | return new ViewHolder( 54 | (TextView) LayoutInflater.from(parent.getContext()) 55 | .inflate(R.layout.list_item, parent, false)); 56 | } 57 | 58 | @Override 59 | public void onBindViewHolder(ViewHolder holder, final int position) { 60 | holder.getTitle().setText(mSampleProvider.getTitleForPosition(position)); 61 | holder.getTitle().setOnClickListener(new View.OnClickListener() { 62 | @Override 63 | public void onClick(View v) { 64 | mSampleProvider.onSampleSelected(position); 65 | } 66 | }); 67 | } 68 | 69 | @Override 70 | public int getItemCount() { 71 | return mSampleProvider == null ? 0 : mSampleProvider.getSampleCount(); 72 | } 73 | } 74 | 75 | private class ViewHolder extends RecyclerView.ViewHolder { 76 | 77 | public ViewHolder(TextView textView) { 78 | super(textView); 79 | } 80 | 81 | public TextView getTitle() { 82 | return (TextView) itemView; 83 | } 84 | } 85 | 86 | public interface SampleListProvider { 87 | void onSampleSelected(int index); 88 | 89 | String getTitleForPosition(int index); 90 | 91 | int getSampleCount(); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /sample/src/main/java/com/andkulikov/transitionseverywhere/MainActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Andrey Kulikov (andkulikov@gmail.com) 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 | package com.andkulikov.transitionseverywhere; 17 | 18 | import android.os.Bundle; 19 | 20 | import androidx.appcompat.app.AppCompatActivity; 21 | import androidx.fragment.app.Fragment; 22 | 23 | public class MainActivity extends AppCompatActivity implements ListFragment.SampleListProvider { 24 | 25 | @Override 26 | protected void onCreate(Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | setContentView(R.layout.activity_main); 29 | ListFragment listFragment = new ListFragment(); 30 | listFragment.setSampleListListener(this); 31 | getSupportFragmentManager() 32 | .beginTransaction() 33 | .replace(R.id.container, listFragment) 34 | .commit(); 35 | } 36 | 37 | @Override 38 | public void onSampleSelected(int index) { 39 | getSupportFragmentManager() 40 | .beginTransaction() 41 | .setCustomAnimations(R.anim.fade_in, R.anim.fade_out, 42 | R.anim.fade_in, R.anim.fade_out) 43 | .replace(R.id.container, createFragmentForPosition(index)) 44 | .addToBackStack(String.valueOf(index)) 45 | .commit(); 46 | } 47 | 48 | @Override 49 | public int getSampleCount() { 50 | return 13; 51 | } 52 | 53 | @Override 54 | public String getTitleForPosition(int index) { 55 | switch (index) { 56 | case 0: return "Simple animations with AutoTransition"; 57 | case 1: return "Interpolator, duration, start delay"; 58 | case 2: return "Path motion"; 59 | case 3: return "Slide transition"; 60 | case 4: return "Scale transition"; 61 | case 5: return "Explode transition and epicenter"; 62 | case 6: return "Transition names"; 63 | case 7: return "ChangeImageTransform transition"; 64 | case 8: return "Recolor transition"; 65 | case 9: return "Rotate transition"; 66 | case 10: return "Change text transition"; 67 | case 11: return "Custom transition"; 68 | case 12: return "Scene to scene transitions"; 69 | } 70 | return null; 71 | } 72 | 73 | private Fragment createFragmentForPosition(int index) { 74 | switch (index) { 75 | case 0: return new AutoTransitionSample(); 76 | case 1: return new InterpolatorDurationStartDelaySample(); 77 | case 2: return new PathMotionSample(); 78 | case 3: return new SlideSample(); 79 | case 4: return new ScaleSample(); 80 | case 5: return new ExplodeAndEpicenterExample(); 81 | case 6: return new TransitionNameSample(); 82 | case 7: return new ImageTransformSample(); 83 | case 8: return new RecolorSample(); 84 | case 9: return new RotateSample(); 85 | case 10: return new ChangeTextSample(); 86 | case 11: return new CustomTransitionSample(); 87 | case 12: return new ScenesSample(); 88 | } 89 | return null; 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /sample/src/main/java/com/andkulikov/transitionseverywhere/PathMotionSample.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Andrey Kulikov (andkulikov@gmail.com) 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 | package com.andkulikov.transitionseverywhere; 17 | 18 | import android.os.Bundle; 19 | import android.view.Gravity; 20 | import android.view.LayoutInflater; 21 | import android.view.View; 22 | import android.view.ViewGroup; 23 | import android.widget.FrameLayout; 24 | 25 | import androidx.annotation.Nullable; 26 | import androidx.fragment.app.Fragment; 27 | import androidx.transition.ArcMotion; 28 | import androidx.transition.ChangeBounds; 29 | import androidx.transition.TransitionManager; 30 | 31 | /** 32 | * Created by Andrey Kulikov on 24/03/16. 33 | */ 34 | public class PathMotionSample extends Fragment { 35 | 36 | @Nullable 37 | @Override 38 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 39 | View view = inflater.inflate(R.layout.fragment_path, container, false); 40 | 41 | final ViewGroup transitionsContainer = view.findViewById(R.id.transitions_container); 42 | final View button = transitionsContainer.findViewById(R.id.button); 43 | 44 | button.setOnClickListener(new View.OnClickListener() { 45 | 46 | boolean mToRightAnimation; 47 | 48 | @Override 49 | public void onClick(View v) { 50 | final ChangeBounds changeBounds = new ChangeBounds(); 51 | changeBounds.setPathMotion(new ArcMotion()); 52 | changeBounds.setDuration(500); 53 | TransitionManager.beginDelayedTransition(transitionsContainer, changeBounds); 54 | 55 | mToRightAnimation = !mToRightAnimation; 56 | FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) button.getLayoutParams(); 57 | params.gravity = mToRightAnimation ? (Gravity.RIGHT | Gravity.BOTTOM) : 58 | (Gravity.LEFT | Gravity.TOP); 59 | button.setLayoutParams(params); 60 | } 61 | 62 | }); 63 | 64 | return view; 65 | } 66 | 67 | 68 | } 69 | -------------------------------------------------------------------------------- /sample/src/main/java/com/andkulikov/transitionseverywhere/RecolorSample.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Andrey Kulikov (andkulikov@gmail.com) 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 | package com.andkulikov.transitionseverywhere; 17 | 18 | import android.graphics.drawable.ColorDrawable; 19 | import android.os.Bundle; 20 | import android.view.LayoutInflater; 21 | import android.view.View; 22 | import android.view.ViewGroup; 23 | import android.widget.Button; 24 | 25 | import com.transitionseverywhere.Recolor; 26 | 27 | import androidx.annotation.Nullable; 28 | import androidx.fragment.app.Fragment; 29 | import androidx.transition.TransitionManager; 30 | 31 | /** 32 | * Created by Andrey Kulikov on 17/04/16. 33 | */ 34 | public class RecolorSample extends Fragment { 35 | 36 | @Nullable 37 | @Override 38 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 39 | View view = inflater.inflate(R.layout.fragment_recolor, container, false); 40 | 41 | final ViewGroup transitionsContainer = view.findViewById(R.id.transitions_container); 42 | final Button button = transitionsContainer.findViewById(R.id.button1); 43 | 44 | button.setOnClickListener(new View.OnClickListener() { 45 | 46 | boolean mColorsInverted; 47 | 48 | @Override 49 | public void onClick(View v) { 50 | TransitionManager.beginDelayedTransition(transitionsContainer, new Recolor()); 51 | 52 | mColorsInverted = !mColorsInverted; 53 | button.setTextColor(getResources().getColor(!mColorsInverted ? R.color.second_accent : R.color.accent)); 54 | button.setBackgroundDrawable( 55 | new ColorDrawable(getResources().getColor(!mColorsInverted ? R.color.accent : R.color.second_accent))); 56 | } 57 | 58 | }); 59 | 60 | return view; 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /sample/src/main/java/com/andkulikov/transitionseverywhere/RotateSample.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Andrey Kulikov (andkulikov@gmail.com) 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 | package com.andkulikov.transitionseverywhere; 17 | 18 | import android.os.Bundle; 19 | import android.view.LayoutInflater; 20 | import android.view.View; 21 | import android.view.ViewGroup; 22 | 23 | import com.transitionseverywhere.Rotate; 24 | 25 | import androidx.annotation.Nullable; 26 | import androidx.fragment.app.Fragment; 27 | import androidx.transition.TransitionManager; 28 | 29 | /** 30 | * Created by Andrey Kulikov on 17/04/16. 31 | */ 32 | public class RotateSample extends Fragment { 33 | 34 | @Nullable 35 | @Override 36 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 37 | View view = inflater.inflate(R.layout.fragment_rotate, container, false); 38 | 39 | final ViewGroup transitionsContainer = view.findViewById(R.id.transitions_container); 40 | final View icon = transitionsContainer.findViewById(R.id.icon); 41 | 42 | icon.setOnClickListener(new View.OnClickListener() { 43 | 44 | boolean mRotated; 45 | 46 | @Override 47 | public void onClick(View v) { 48 | TransitionManager.beginDelayedTransition(transitionsContainer, new Rotate()); 49 | 50 | mRotated = !mRotated; 51 | icon.setRotation(mRotated ? 135 : 0); 52 | } 53 | 54 | }); 55 | 56 | return view; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /sample/src/main/java/com/andkulikov/transitionseverywhere/ScaleSample.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Andrey Kulikov (andkulikov@gmail.com) 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 | package com.andkulikov.transitionseverywhere; 17 | 18 | import android.os.Bundle; 19 | import android.view.LayoutInflater; 20 | import android.view.View; 21 | import android.view.ViewGroup; 22 | import android.widget.TextView; 23 | 24 | import com.transitionseverywhere.extra.Scale; 25 | 26 | import androidx.annotation.Nullable; 27 | import androidx.fragment.app.Fragment; 28 | import androidx.interpolator.view.animation.FastOutLinearInInterpolator; 29 | import androidx.interpolator.view.animation.LinearOutSlowInInterpolator; 30 | import androidx.transition.Fade; 31 | import androidx.transition.TransitionManager; 32 | import androidx.transition.TransitionSet; 33 | 34 | /** 35 | * Created by Andrey Kulikov on 24/03/16. 36 | */ 37 | public class ScaleSample extends Fragment { 38 | 39 | @Nullable 40 | @Override 41 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 42 | View view = inflater.inflate(R.layout.fragment_scale, container, false); 43 | 44 | final ViewGroup transitionsContainer = view.findViewById(R.id.transitions_container); 45 | final TextView text1 = transitionsContainer.findViewById(R.id.text1); 46 | 47 | transitionsContainer.findViewById(R.id.button1).setOnClickListener(new VisibleToggleClickListener() { 48 | 49 | @Override 50 | protected void changeVisibility(boolean visible) { 51 | TransitionManager.beginDelayedTransition(transitionsContainer, new Scale()); 52 | text1.setVisibility(visible ? View.VISIBLE : View.INVISIBLE); 53 | } 54 | 55 | }); 56 | 57 | final TextView text2 = transitionsContainer.findViewById(R.id.text2); 58 | 59 | transitionsContainer.findViewById(R.id.button2).setOnClickListener(new VisibleToggleClickListener() { 60 | 61 | @Override 62 | protected void changeVisibility(boolean visible) { 63 | TransitionSet set = new TransitionSet() 64 | .addTransition(new Scale(0.7f)) 65 | .addTransition(new Fade()) 66 | .setInterpolator(visible ? new LinearOutSlowInInterpolator() : new FastOutLinearInInterpolator()); 67 | TransitionManager.beginDelayedTransition(transitionsContainer, set); 68 | text2.setVisibility(visible ? View.VISIBLE : View.INVISIBLE); 69 | } 70 | 71 | }); 72 | 73 | return view; 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /sample/src/main/java/com/andkulikov/transitionseverywhere/ScenesSample.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Andrey Kulikov (andkulikov@gmail.com) 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 | package com.andkulikov.transitionseverywhere; 17 | 18 | import android.os.Bundle; 19 | import android.view.Gravity; 20 | import android.view.LayoutInflater; 21 | import android.view.View; 22 | import android.view.ViewGroup; 23 | import android.widget.RadioGroup; 24 | 25 | import androidx.annotation.Nullable; 26 | import androidx.fragment.app.Fragment; 27 | import androidx.transition.ChangeBounds; 28 | import androidx.transition.Scene; 29 | import androidx.transition.Slide; 30 | import androidx.transition.TransitionInflater; 31 | import androidx.transition.TransitionManager; 32 | import androidx.transition.TransitionSet; 33 | 34 | /** 35 | * Created by Andrey Kulikov on 20/03/16. 36 | */ 37 | public class ScenesSample extends Fragment implements RadioGroup.OnCheckedChangeListener { 38 | 39 | // We transition between these Scenes 40 | private Scene mScene1; 41 | private Scene mScene2; 42 | private Scene mScene3; 43 | 44 | /** 45 | * A custom TransitionManager 46 | */ 47 | private TransitionManager mTransitionManagerForScene3; 48 | 49 | /** 50 | * Transitions take place in this ViewGroup. We retain this for the dynamic transition on scene 4. 51 | */ 52 | private ViewGroup mSceneRoot; 53 | 54 | 55 | @Nullable 56 | @Override 57 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 58 | View view = inflater.inflate(R.layout.fragment_scenes, container, false); 59 | 60 | RadioGroup radioGroup = (RadioGroup) view.findViewById(R.id.select_scene); 61 | radioGroup.setOnCheckedChangeListener(this); 62 | mSceneRoot = (ViewGroup) view.findViewById(R.id.scene_root); 63 | 64 | // A Scene can be instantiated from a live view hierarchy. 65 | mScene1 = new Scene(mSceneRoot, mSceneRoot.findViewById(R.id.container)); 66 | 67 | // You can also inflate a generate a Scene from a layout resource file. 68 | mScene2 = Scene.getSceneForLayout(mSceneRoot, R.layout.scene2, getContext()); 69 | 70 | // Another scene from a layout resource file. 71 | mScene3 = Scene.getSceneForLayout(mSceneRoot, R.layout.scene3, getContext()); 72 | 73 | // We create a custom TransitionManager for Scene 3, in which ChangeBounds, Fade and 74 | // ChangeImageTransform take place at the same time. 75 | mTransitionManagerForScene3 = TransitionInflater.from(getContext()) 76 | .inflateTransitionManager(R.transition.scene3_transition_manager, mSceneRoot); 77 | 78 | return view; 79 | } 80 | 81 | @Override 82 | public void onCheckedChanged(final RadioGroup group, int checkedId) { 83 | switch (checkedId) { 84 | case R.id.select_scene_1: { 85 | // You can start an automatic transition with TransitionManager.go(). 86 | TransitionManager.go(mScene1); 87 | break; 88 | } 89 | case R.id.select_scene_2: { 90 | TransitionSet set = new TransitionSet(); 91 | Slide slide = new Slide(Gravity.LEFT); 92 | slide.addTarget(R.id.transition_title); 93 | set.addTransition(slide); 94 | set.addTransition(new ChangeBounds()); 95 | set.setOrdering(TransitionSet.ORDERING_TOGETHER); 96 | set.setDuration(350); 97 | TransitionManager.go(mScene2, set); 98 | break; 99 | } 100 | case R.id.select_scene_3: { 101 | // You can also start a transition with a custom TransitionManager. 102 | mTransitionManagerForScene3.transitionTo(mScene3); 103 | break; 104 | } 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /sample/src/main/java/com/andkulikov/transitionseverywhere/SlideSample.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Andrey Kulikov (andkulikov@gmail.com) 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 | package com.andkulikov.transitionseverywhere; 17 | 18 | import android.os.Bundle; 19 | import android.view.Gravity; 20 | import android.view.LayoutInflater; 21 | import android.view.View; 22 | import android.view.ViewGroup; 23 | import android.widget.TextView; 24 | 25 | import androidx.annotation.Nullable; 26 | import androidx.fragment.app.Fragment; 27 | import androidx.transition.Slide; 28 | import androidx.transition.TransitionManager; 29 | 30 | /** 31 | * Created by Andrey Kulikov on 20/03/16. 32 | */ 33 | public class SlideSample extends Fragment { 34 | 35 | @Nullable 36 | @Override 37 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 38 | View view = inflater.inflate(R.layout.fragment_slide, container, false); 39 | 40 | final ViewGroup transitionsContainer = view.findViewById(R.id.transitions_container); 41 | final TextView text = transitionsContainer.findViewById(R.id.text); 42 | 43 | transitionsContainer.findViewById(R.id.button).setOnClickListener(new VisibleToggleClickListener() { 44 | @Override 45 | protected void changeVisibility(boolean visible) { 46 | TransitionManager.beginDelayedTransition(transitionsContainer, new Slide(Gravity.RIGHT)); 47 | text.setVisibility(visible ? View.VISIBLE : View.GONE); 48 | } 49 | }); 50 | 51 | return view; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /sample/src/main/java/com/andkulikov/transitionseverywhere/TransitionNameSample.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Andrey Kulikov (andkulikov@gmail.com) 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 | package com.andkulikov.transitionseverywhere; 17 | 18 | import android.annotation.SuppressLint; 19 | import android.os.Bundle; 20 | import android.view.LayoutInflater; 21 | import android.view.View; 22 | import android.view.ViewGroup; 23 | import android.widget.Button; 24 | import android.widget.TextView; 25 | 26 | import java.util.ArrayList; 27 | import java.util.Collections; 28 | import java.util.List; 29 | 30 | import androidx.annotation.Nullable; 31 | import androidx.core.view.ViewCompat; 32 | import androidx.fragment.app.Fragment; 33 | import androidx.transition.ChangeBounds; 34 | import androidx.transition.TransitionManager; 35 | 36 | /** 37 | * Created by Andrey Kulikov on 12/05/16. 38 | */ 39 | public class TransitionNameSample extends Fragment { 40 | 41 | @Nullable 42 | @Override 43 | @SuppressLint("DefaultLocale") 44 | public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 45 | View view = inflater.inflate(R.layout.fragment_names, container, false); 46 | 47 | final ViewGroup layout = view.findViewById(R.id.transitions_container); 48 | final Button button = view.findViewById(R.id.button1); 49 | 50 | final List titles = new ArrayList<>(); 51 | for (int i = 0; i < 5; i++) { 52 | titles.add(String.format("Item %d", i + 1)); 53 | } 54 | 55 | createViews(inflater, layout, titles); 56 | button.setOnClickListener(new View.OnClickListener() { 57 | 58 | @Override 59 | public void onClick(View v) { 60 | TransitionManager.beginDelayedTransition(layout, new ChangeBounds()); 61 | Collections.shuffle(titles); 62 | createViews(inflater, layout, titles); 63 | } 64 | 65 | }); 66 | 67 | return view; 68 | } 69 | 70 | private static void createViews(LayoutInflater inflater, ViewGroup layout, List titles) { 71 | layout.removeAllViews(); 72 | for (String title : titles) { 73 | TextView textView = (TextView) inflater.inflate(R.layout.fragment_names_item, layout, false); 74 | textView.setText(title); 75 | ViewCompat.setTransitionName(textView, title); 76 | layout.addView(textView); 77 | } 78 | } 79 | 80 | 81 | } 82 | -------------------------------------------------------------------------------- /sample/src/main/java/com/andkulikov/transitionseverywhere/VisibleToggleClickListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Andrey Kulikov (andkulikov@gmail.com) 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 | package com.andkulikov.transitionseverywhere; 17 | 18 | import android.view.View; 19 | 20 | /** 21 | * Created by Andrey Kulikov on 24/03/16. 22 | */ 23 | public abstract class VisibleToggleClickListener implements View.OnClickListener { 24 | 25 | private boolean mVisible; 26 | 27 | @Override 28 | public void onClick(View v) { 29 | mVisible = !mVisible; 30 | changeVisibility(mVisible); 31 | } 32 | 33 | protected abstract void changeVisibility(boolean visible); 34 | 35 | } 36 | -------------------------------------------------------------------------------- /sample/src/main/res/anim/fade_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 20 | 21 | 26 | -------------------------------------------------------------------------------- /sample/src/main/res/anim/fade_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 20 | 21 | 26 | -------------------------------------------------------------------------------- /sample/src/main/res/drawable-hdpi/ic_add_black_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andkulikov/Transitions-Everywhere/226eb81be7f3e1487886594812f56a289ea3d72a/sample/src/main/res/drawable-hdpi/ic_add_black_48dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-nodpi/girl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andkulikov/Transitions-Everywhere/226eb81be7f3e1487886594812f56a289ea3d72a/sample/src/main/res/drawable-nodpi/girl.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_add_black_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andkulikov/Transitions-Everywhere/226eb81be7f3e1487886594812f56a289ea3d72a/sample/src/main/res/drawable-xhdpi/ic_add_black_48dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xxhdpi/ic_add_black_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andkulikov/Transitions-Everywhere/226eb81be7f3e1487886594812f56a289ea3d72a/sample/src/main/res/drawable-xxhdpi/ic_add_black_48dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andkulikov/Transitions-Everywhere/226eb81be7f3e1487886594812f56a289ea3d72a/sample/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xxxhdpi/ic_add_black_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andkulikov/Transitions-Everywhere/226eb81be7f3e1487886594812f56a289ea3d72a/sample/src/main/res/drawable-xxxhdpi/ic_add_black_48dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable/oval.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/button.xml: -------------------------------------------------------------------------------- 1 | 2 |