I'm trying to animate 2 simple Views from a selected item in a RecyclerView to a new fragment. I've looked at a lot of examples of animating shared elements from one Activity to another Activity, but very few examples of animating a shared element from one Fragment to another Fragment within the same Activity. It almost works.
Here is my structure.
Activity
-- Full screen Fragment1 with RecyclerView
-- Full screen Fragment2 with details
When the user selects an item in the RecyclerView in Fragment1, I replace Fragment1 with Fragment2 that has a View with the shared elements in it in different positions and sizes.
There's a bit of a trick to get it to work, you have to make sure your transitionName is unique for each item in your list, and of course that transitionName must match the transitionName of the element in Fragment2 for the animation to play. I have this part working, when I select an item, the 2 shared Views do animate, just not exactly how you would expect when doing it between 2 Activities.
If I select an item near the bottom of the screen, it draws the View for Fragment2 and animates the 2 shared Views as if they were in the item at the top of the screen. Hard to explain. Here are some pictures
Fragment1
Fragment2
In both fragments I'm setting the following
setSharedElementEnterTransition(new ChangeBounds());
setSharedElementReturnTransition(new ChangeBounds());
setAllowEnterTransitionOverlap(true);
setAllowReturnTransitionOverlap(true);
Also in their parent Activity in onCreate() I've set
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
Any idea why my shared element animations are starting at the top of my screen even when the they were starting in the selected item at the bottom of my screen?
Finally solved this problem! As it turns out because the view I'm sharing between 2 fragments is a child of another view (RelativeLayout) in the 2nd fragment, you need to add the ChangeTransform transition to your TransitionSet. Apparently ChangeTransform tells the system to remember the views original position in the 1st fragment before animating to the new position in the 2nd fragment. Here is my updated transitionSet. I'll also clean up my test project code a bit and make a final push to bitbucket in case it will help others after me. Thanks for all the help with this one Alex and thank you to #George-mount for answering someones similar question that dropped the hint to me for this solution.
<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
<changeTransform/>
<changeBounds/>
</transitionSet>
https://bitbucket.org/brockoli/fragmentsharedelements
Related
This is the problem I have: https://imgur.com/a/GKZpdX9
The AdView that I have anchored to the bottom of the layout will be slightly pulled out of place and will only come back to its intended place when the user scrolls through the RecyclerView again.
The activity uses two fragments, one for the banner at the bottom and another one on top for the rest of views so when the user clicks a ViewHolder the upper fragment is replaced.
I have tried to use methods such as .scrollToView to force the RecyclerView to move, but it kept the misplacement of the banner. ONLY when the user does scroll comes back into the right place.
I have checked that if instead of replacing the upper fragment the user was taken to a different activity and then the back button was pressed, this problem would not happen. But I need to use a fragment.
Instead of creating seperate fragment for banner in Activity. you should use this code technique in your fragmentActivity. use relative layout for top view in activity then add bannerView with specific height and set alignParentBottom to true. then add another layout which contain your recyclerview fragment and set this property (layoutAbove and pass the addview id to id). it will place exact top of the banner.
I want to animate a recyclerview item to outside(sibling) of the recyclerview. I tried many different animation code and libraries but nothing happened. My problem is to animate a row of recyclerview to a linearlayout outside(sibling) of recyclerview.see attached picture.
My Main Layout flow is:
ConstraintLayout
--LinearLayout
----View (empty)
--Recyclerview
I believe you can use Shared element transition built-in from Android (search for more tutorial about this keyword)
It doesn't support the transition from within 1 view. But you can use Fragment to achieve the same result. Your activity will be like this:
ConstraintLayout (Activity)
--FrameLayout (container for the Fragment)
--Recyclerview
The Fragment contains the layout of your item's destination view.
I imagine the flow can be like this:
User taps on an item in RecyclerView in Activity
Replace new fragment to the container with defined data for shared element transition
https://medium.com/#bherbst/fragment-transitions-with-shared-elements-7c7d71d31cbb
I have two activities MainAcitity and DetailActivity. MainActivity is containing recyclerview inside the fragment of viewpager. When I click on item it will go to DetailActivity and show the detail info inside the fragment of viewpager in DetailAcitivty.
The Problems is:
I want to add transition when I click on recyclerview item in MainActivity and go to DetailActivity.
When I back from the DetailActivity to MainActivity I want its transition will come to the item that I swiped in viewpager.
How can I achieve this?
Note:
-MainAcitivty and DetailAcitivty both are containing viewpager.
Thanks!
You will need to tag both your views with a unique transitionName.
ViewCompat.setTransitionName(imageView, "some_unique_transitionName");
start the new activity with this new information
ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(activity, imageView, ViewCompat.getTransitionName(imageView));
activity.startActivity(intent, options.toBundle());
Now, on the new activity :
Depending on how you open your next activity and how complex is it's view hierarchy you'll might want to leverage supportPostponeEnterTransition(); during onCreate and supportStartPostponedEnterTransition();sometime later when it's set up. I'll let you read the documentation for it
Apart from that find the view on the new activity that needs to be animated and set the transition name on it
activityImage.setTransitionName(transitionName);
and let it rip.
few other things you might want to tinker with could be animation duration, interpolators etc.
getWindow().getSharedElementEnterTransition().setDuration(200);
getWindow().getSharedElementReturnTransition().setDuration(200)
.setInterpolator(new DecelerateInterpolator());
And, entry / exit transitions for your activities (you will need this)
Fade fade = new Fade();
fade.excludeTarget(android.R.id.statusBarBackground, true);
fade.excludeTarget(android.R.id.navigationBarBackground, true);
getWindow().setEnterTransition(fade);
getWindow().setExitTransition(fade);
Remember, the shared element transitions traverses the whole view hierarchy to find out the source and target views and only after the target activity is completely laid the framework reverse transitions to give you the illusion you want to achieve so yea, if the view hierarchies are complex or the activities take time to set up etc (Network dependent), you might need to tinker around a little bit more.
I want to animate a view with SharedElement transition from one Fragment to another fragment in ViewPager.
I've 3 fragments in a ViewPager, each fragment is having a single TextView with same transition name in XML file.
Now, when ViewPager slides another Fragment, I want to see SharedElement in action.
I’ve had the same issue. Standard shared element transitions are not working between ViewPager pages.
So I wrote a Shared Element View Pager library. It works both for transitions caused by onClick() events (such as viewPager.setCurrentItem(x) ) and page slides caused by user. The animation is bound to finger movement.
It's not an android transition so there could be some obstacles. Take a look though.
SharedElementPageTransformer demo
Usage
Add all fragments from your ViewPager to the List in the same order.
ArrayList<Fragment> fragments = new ArrayList<>();
fragments.add(hello_fragment);
fragments.add(small_picture_fragment);
Create SharedElementPageTransformer presumably in Activity.onCreate().
this refers to activity:
SharedElementPageTransformer transformer =
new SharedElementPageTransformer(this, fragments);
Add shared transition by passing pairs of view ids, that need to be linked together
transformer.addSharedTransition(R.id.smallPic_image_cat, R.id.bigPic_image_cat);
Set our transformer to ViewPager's pageTransformer AND onPageChangeListener.
viewPager.setPageTransformer(false, transformer);
viewPager.addOnPageChangeListener(transformer);
it's been maybe a too long time but could be helpful though.
It's totally possible to have shared elements transitions between 2 viewPagers since i already did it myself.
I think the thing you are maybe missing is that transition name has to be unique !
So it has to be set programmatically and not in XML ! It's very important in ViewPager since same view could be inflated many times.
imageView.setTransitionName("unique_name");
This way the transition knows on what element it should be played;)
in my Activity, I have a layout containing 3 FrameLayouts, one at the top, one at the left and one at the "center".
Now, I sometimes only want to display one or two of them. Atm I am doing it this way:
FrameLayout frame = (FrameLayout) findViewById(R.id.framelayout_menu_left);
frame.setVisibility(...);
frame = (FrameLayout) findViewById(R.id.framelayout_content);
frame.setVisibility(...);
frame = (FrameLayout) findViewById(R.id.framelayout_menu_top);
frame.setVisibility(...);
However this can get really ugly results, e.g. when I switch the "content" Fragment and hide the top and/or left FrameLayout. It all starts flickering as the "content" Fragment jumps to the top and/or left and only afterwards is replaced.
Also, I can obviously not navigate back to another setup, so is there any other way to do this?
Kind regards,
jellyfish
Edit:
Maybe a little drawing makes my question clearer...
A shows a Layout of 3 FrameLayouts containing 3 different Fragments. Each color represents one distinct Fragment.
Now what I want to do is to switch from A to D.
I am doing this by replacing the blue Fragment with the yellow Fragment via a FragmentTransaction.
However, this still keeps the other Frames visible, so I hide them via the code above.
Now, Frame.setVisibility() is called way before commit(), so in B and C the blue Fragment "jumps" to the left and the top and only afterwards (in D) is replaced with the yellow Fragment. This produces a nasty flickering.
As a workaround, I now hide all three FrameLayouts before the transaction and re-show the ones I need once the transaction has finished. But there still is the problem that I can't go back via the back button as this isn't a real transaction.
I would have two suggestions. Firstly, if you both add a fragment transition effect and do the visibility changes after the transaction, that would probably substantially reduce much of your flicker effect
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
Secondly, I've simply given up on having the system manage the fragment stack for me -- it seems that this only works well with simple transactions. Override onBackPressed and do your own logic there.
--randy