Let's say I'm using a view-based approach to develop an Android application like for example described in the following article: http://corner.squareup.com/2014/10/advocating-against-android-fragments.html
So now I have two full screen views. One is visible and contains a grid of images. The other is hidden and is a detail view of the to-be-clicked image. Without transitions on clicking an image in the grid the grid view will be hidden and the detail view will be shown. Now what if I want to have something akin to a shared element transition between the small image in the grid view and the larger image in the detail view. Is something like this possible?
Yes, transitions allow this.
In your example, you have both the grid and detail views already in your hierarchy. To use transitions, it will work better if the detail view does not start in the View hierarchy. You need to exchange the two views.
There are two (similar) ways to do it. The first is to have the grid view in a scene. Then use TransitionManager.go(detailScene, transition).
The second way is to use TransitionManager.beginDelayedTransition and then swap the detailed layout for the grid layout.
It is important to have the shared views have something in common. Typically it is a View ID or transitionName. This linking will tell the transition system that even though the views are different instances.
The transition that you'll want to use is #android:transition/move. It combines ChangBounds, ChangeTransform, ChangeImageTransform, and ChangeClipBounds. You'll have to target this at the shared element views. It looks like you will need another transition (Fade?) for the entering and /or exiting views.
Something like this:
TransitionSet shared = ...
shared.addTarget("sharedName");
gridElement.setTransitionName("sharedName");
Fade fade = new Fade();
fade.excludeTarget("sharedName", true);
TransitionSet set = new TransitionSet();
set.addTransition(shared)
.addTransition(fade);
TransitionManager.go(detailScene, set);
Related
I draw a View that is not attached to any parent.
It's a decoration for a RecyclerView. The view sticks to the bottom and disappears when its counter part comes up in the list.
All this works fine but:
When i leave the activity the View doesn't fade with the rest of the
views in the activity's transition.
It stays until the end of the animation and then disappears
immediately.
( see large green view in the demo )
How do i include this unattached View in the activity's exit transition?
I've create a minimal Android Studio Project to replicate the issue:
https://github.com/Ostkontentitan/transition-issue-demo
(To better see the issue possibly set your phones animation scale to >= 5)
Here is a demo:
Add transitionName to xml layout for the RecyclerView.
The transition animation you see is because of ActivityOptions.makeSceneTransitionAnimation(this#ItemListActivity) and if you add transitionName to the view, it works fine.
Not-too-educated guess
(because I haven't tried and I haven't used Transition Framework in a few months)
The way TF (Transition Framework) works is by computing the start/end values of the transition and performing the animations needed to achieve this.
RecyclerView decorations are not "views" that are part of the layout, so TF has no idea that thing exists. It does know about your RecyclerView of course, because it's contained in the ViewGroup that is animated.
You may have already know this, but in any case, what I think I'd try to do here, is create a custom transition framework transition (they are not hard to do, you can even check TransitionEverywhere and look at how that library implements some missing transitions in the framework); in your CustomTransition, you can then try to interpolate the animation values so the recycler view can redecorate as the animation progresses (like an alpha value that is animated, your custom decorator would "paint" using said alpha).
Now... in truth, I've had to do something similar once, where a custom transition was "driving" a few external views (for reasons at the time) :) but... it was not a RecyclerView item decoration, mine were just "views", so I'm not sure if you can do this this way w/a decoration.
I think it's worth trying.
I'm working in an app that is similar to Google Calendar...
There are events and when a user click one, the event grows and
transforms into the detail view.
The shared views (the events) are inside a ScrollView, so at some
point those views may be partially visible.
The problem is that when one partially visible View is selected, the full View
appears above all and then the animation runs.
Here is a capture of the problem:
What can I do to make the Transition take only the visible part of the View to animate it?
This is my transition:
<changeBounds xmlns:android="http://schemas.android.com/apk/res/android">
<arcMotion android:minimumHorizontalAngle="15"
android:minimumVerticalAngle="0"
android:maximumAngle="90"/>
</changeBounds>
Shared elements are drawn on top of the entire view hierarchy. You can disable this by setting Window#setSharedElementsUseOverlay(false) in your Activities, but this will result in undesired effects. More details here and on YouTube.
The better solution is to use shared elements transition between Fragments. More details here.
I'm curious how android handles the children of hero views in the shared element transition one can see in Google Keep:
In the standard shared elements transition, on the enter animation, the hero views in the calling activity are instantaneously overlaid with the destination view (at the starting dimensions) before the transition animates changes in the destination view's dimensions to get to their new location.
However, on the return animation, the returning activity's views remain on top of the overlay, and they are the views that are displayed until the animation ends, at which point the destination (calling activity's) hero views snap into place.
This creates a pretty jarring effect if there's any differences in the content of the two hero views -- for example, a textview where the lines wrap differently, or different child views altogether.
Meanwhile, in Google Keep, the shared element transition seems to fade the content views back and forth each way, so this jarring effect is considerably less noticeable. Consequently differences in things like padding or line wrapping are much less problematic.
What's the best way for me to implement this in my own app?
Here is a example:
My answer is long. And it provides only the general framework to recreate what I saw in your animated image, so you will have to take some time to tweak things yourself to get it perfect.
Code is visible here: https://gist.github.com/zizibaloob/e107fe80afa6873301bf234702d4b2b9
tl;dr: The "shared element" is just the green card/background, so you create the transition using those. Place a gray background behind the green background on the second activity so that the green has something to draw on top of while it's growing. Wrap all of your content in a parent view and animate its alpha to fade in/out.
Full answer
In your image, the "shared element" appears to be the green card on the first screen / the green background of the second screen. On top of that, we add two additional requirements:
The gray background of the first activity must be visible during the transition
The contents of the card disappear and then fade back in during/after the transition
Let's go through each file and talk about the choices I made to achieve the desired results...
activity_main.xml
This one is really straightforward. I just built up a view hierarchy that vaguely resembled the one in your image. The empty View at the top is a placeholder for a Toolbar, and the Space at the bottom of the card is there just to make it a little larger.
activity_other.xml
The relevant part of this layout is the triple-stack of "parent" views. Each of them serves a purpose:
The top-level FrameLayout provides a gray background for the card to "grow" over
The middle FrameLayout provides the green background that will be shared between activities
The inner LinearLayout wraps everything that we want to have fade in/out, and will be animated by code in the Activity class
MainActivity.java
Another straightforward class. All this Activity does is make the card clickable and set up the transition.
OtherActivity.java
Most of the magic happens here. Within onCreate(), the Toolbar stuff is all standard, so we can skip that. The code inside the if statement is what sets up the fade-in animation (wrapped in an if so it only fades in on first launch). I've also overridden onBackPressed() to reverse the fade animation and to trigger the return transition.
shared_element_transition.xml
All of the rest of the magic is in this file. The <targets> element excludes the status and navigation bars, which makes sure they don't blink during the transition. The various <changeFoo> tags are the actual transition animation that plays.
styles.xml
The only reason that I included this in the Gist at all is the TransitionTheme style. This is applied to OtherActivity in the manifest, and it's what sets our custom transition (from shared_element_transition.xml).
I have a custom view, that I replace with different view. Part of the elements on the new view are connected. Like the user image.
I want to use the same animation effect as in Lollipop activities transition between my views.
Is there any way to achieve this?
In my android app, I have a notion of "trails": a sequence of objects that the user can navigate. The same view, naturally, is used to display all objects, just updating components (texts, images, etc.) when the next object is to be shown.
Now, I want to animate the transition between objects: when the user navigates from an object to the next object, I want to use the slide animation from right to left (and the other way around). The issue is that I don't have two views to animate between - only one view. Therefore when I try to animate displaying this view (when the next object is to be loaded), the visible view disappears, I get a blank screen - and then the view slides in from the right.
What I want instead is to have the existing view to slide out and be replaced by a new view (same View but with different content) to slide in from the right.
How should I go about it?
Looks to me like a combination of LayoutTransition and GestureDetector. You might even a ViewFlipper in there too.
The LayoutTransition has an animation feature you might want to look into.
I haven't been able to figure out how to use LayoutTransition in my case, so instead of having my View, I replaced it with ViewFlipper containing two copies of my View. When I need to replace the view with another, I keep track of which of the two is currently displayed, then update the other off-screen and then use standard "slide-from-left" and "slide-from-right" animation with showNext(). This is more complicated than I really wanted it to be and uses more memory, but it does the job.
The solution turned out to be very simple: ViewPager. I provide PageAdapter, which returns two similar views (same layout, different content) and ViewPager takes care of the rest. If I wanted to disable the swipe page changes, all I had to do is extend ViewPager, override onInterseptTouchListener and return false.