Fragment to Fragment Transition: postponeEnterTransition() does not work - android

I am using Android X transitions to animate content with motion between two Fragments, within the same hosting Activity.
I am trying to animate an ImageView which Image is loaded with Glide and an URL.
The problem I have is, regardless of the two ImageViews sizes, their size is 0 before the image is loaded, and because of that, the transitions capture wrong layout values and therefore show a shrinking animation (animating to size 0).
I have read about using postponeEnterTransition() which should, in association with startPostponedEnterTransition() delay the transition for the duration between the two calls.
This is the schema:
Fragment A, image is at the bottom of the screen, width is that of half of the screen's width.
Fragment B, image is at the top of the screen, width is that of the screen's width.
On Fragment A's image click, the Fragment B is loaded.
In Fragment B's onCreate I set my transitions using setSharedElementEnterTransition(transitions). Then I immediately call postponeEnterTransition();
In Fragment B's onCreateView, I await for the ImageView to be pre-drawn (using the ViewTreeObserver), after layout inflation, and then I call startPostponedEnterTransition().
Using a breakpoint and a listener on my transitions, the listener#onTransitionStarted is triggered before I reach the pre-draw callback, which proves the transition captured wrong layout values.
Also, another proof that postponeEnterTransition() has no effect whatsoever, removing the call to startPostponedEnterTransition() does not hold the transition forever.
What am I doing wrong ?
And of course, when returning to Fragment A, the same shrinking animation is being played out as well...

You should set reordering allowed during your fragment transaction by adding setReorderingAllowed(true) to your transaction.
See Android docs and the Reordering part of this blog post by Chris Banes for more context.

Related

Parent fragment destroyed with shared element transition

I have a view hierarchy such as below.
MainActivity :
FirstFragment :
SecondFragment :
In my SecondFragment, i have a RecyclerView. When an item is clicked, i want to open it in another Fragment (in full screen) so i am using the addSharedElement() method and everything works fine after 2 days of retro engineering it : every post i have found on StackOverFlow does not mention that in order to work, the "full-screen" fragment has to replace the first parent inside the activity.
What i first wanted was to nested the full-screen fragment inside the SecondFragment but it's impossible with this method.
I have tried everything else, at each steps of my view hierarchy & none of them is working, except if i replace my FirstFragment by my full-screen fragment.
This is also impossible to use the transition with the add() method unfortunately.
The problem is that this fragment is destroyed & not recreated despite the call of addToBackStack(), when i press the "back-button" inside the NavigationBar.
I am not really familiar with the addToBackStack() method & how can i get back any fragments i have added there.
QUESTION 1 : How can i make it work either without destroying the parent fragment (FirstFragment in my view hierarchy), or without using shared element transition but achieving the same result ?
It seems that what the Transition is doing is recreating a view in the new fragment with the same width / height, x & y coordinates as the one in the previous fragment & animate it from the new fragment...
QUESTION 2 : Would it be a bad idea to do it myself ?
EDIT : My goal is to close the full-screen fragment with a swipe down and as soon as the finger is moved from 10dp along the Y axis, i want to be able to reveal the previous fragment behind (the SecondFragment in my case), that's why i don't want to destroy parent fragments.

Swipe back and forth between a number of DialogFragments

I've been trying to write code which will allow me to swipe back and forth between 3 DialogFragment views which overlay the main Activity.
To be more specific, each view should be swipeable from left to right and vice versa across the entire UI, in much the same way as fragments are in a ViewPager (with limits set at the bounds like so | 1 <--> 2 <--> 3 |) . Like fragments in ViewPager, each DialogFragment should come to rest in a natural position at the centre of the screen after swiping, and the transition animation should be similar.
Ideally, the layout and functionality would be similar to the respective defaults of a DialogFragment overlaying an activity.
Initially, I attempted this with a ViewPager but ran into trouble as the fragments didn't display with the intended layout. The main problem I had here was that the ViewPager stretched the layout of the DialogFragment across the entire UI. Furthermore, the only option I found for resizing the layout of the fragment was to limit the boundaries of the ViewPager, but of course this meant that the transitions occurred in an area smaller than the UI rather than across the entire UI. Mike's provided a brief explanation why this happens in the comments below.
I've also attempted a different approach of creating a child DialogFragment within blank ViewPager fragments. However, so far I've been unsuccessful as the ViewPager functionalilty isn't operational while the child DialogFragment is visible.
In the case of a 'work around' solution things that I want to mimic from the DialogFragment view include:
The shadowed / darkened background outside of the DialogFragment view.
The ability to tap outside of DialogFragment view to close the DialogFragment view (and by extension the ViewPager) and return to the main activity.

How to prepare a fragment before I add it to the view

I have an app that initially displays one fragment, when a button is clicked it transitions to the next fragment. However inside the 2nd fragment there's a ViewPager that holds images from a URL. It can take some time to process all the images. And it is processing the images as the button is clicked which then slows down the speed the fragment gets set up, which takes a lot of time. I want the fragment to be there and prepared instantly.
I can fetch the images in the mainActivity. I however cannot set them to the ViewPager before the fragmentTransaction is committed because the ViewPager doesn't exist until the onCreateView method occurs in the fragment which is only called when the transaction is committed. Is there any way to have the fragment set up in the activity before I commit the transaction.
So the user can easily switch between the two fragments without having to wait for them to process. Or should I have rather used tabs. The thing is I don't want a tabs bar to appear at the top of the screen. I want the tabs to change when by button is clicked.
It sounds like you're processing the images in the main thread? I think it would be best if, instead, you just pass the URL to your second fragment and have it use a Loader to process those images in the background, with placeholders for each image as it's getting loaded.
If you insist on doing the loading in the first fragment, you should just be able to set up and add your second fragment without any images, but have it be hidden. Then, once your loading is complete, you will still have access to your ViewPager from your first fragment and can use another transaction to show the second fragment when ready.
P.S. it would be easier to read/understand your question if it was laid out more logically and not a huge paragraph.

Android: Change fragment on touch/swipe

Is it possible to achieve interaction between fragments described in this image:
So, if one touches (or preferably swipes vertically) on fragment B, it shows (or is replaced by) fragment C and changes size to accommodate the larger fragment. Fragment C will contain a viewPager with additional fragments that are revealed on horizontal swipe (this part is done).
Fragment B will display the crucial contents of fragment C, which is why I want a separate fragment to do this. Fragment A takes user input and should always be interact-able.
I need help wrapping my head around how this should be implemented.

Android Honeycomb: layout problem - hide/show FrameLayouts

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

Categories

Resources