Can I move a fragment elsewhere instantly without recreating anything? - android

This may sound stupid, but can I do that? I have searched a little, and this says "Re-attach a fragment ... causes its view hierarchy to be re-created, attached to the UI, and displayed.", probably meaning that the UI of the fragment is recreated losing states and other things.
The reason why I am trying to do is that I would like to achieve something like the Bottom Sheet of Google Maps. The only title part is showed at the bottom, but we can swipe it up and it becomes a Bottom Sheet. I think when only the title part is showing, it is not actually a Bottom Sheet, as it would be difficult to make exactly that part of a Bottom Sheet to be shown. I think Google Maps has put the title part separately, and is replacing it with a Bottom Sheet whose top part looks just like the title part, when swiping up begins.
So, to achieve similar effect, I thought I would create a cluster of UI as a fragment, and when the user begins swiping up, I place a Bottom Sheet with the peek size is set exactly to the height of the fragment, and move the fragment into the top of the Bottom Sheet, so that it can be swiped up.
But I want to keep everything of the fragment without recreating anything, as if I take the fragment and just move into the fragment instantly. Is that possible, or should I save the states and restore them when the fragment's UI is recreated?

Yes. Consider fragment as View and play with ObjectAnimator or any animation class as per behaviour. (Slide-up animation will do the trick)
Note: Fragment will initialize first even you display 20% of portion over main layout. State will remain same This does answers your question i guess.
Here is similar example for your work around. Reference

Related

Scrolling a ViewPager programmatically, by a small amount

I have the requirement for what is effectively two activities side by side, allowing the user to scroll from one to the other, and back. I've decided that ViewPager is probably the best way to handle this, but am open to suggestions.
When the activity loads, the left hand view is displayed. I want to indicate to the user that the other view exists, by just scrolling it a small amount to the left and back again (similar to the way it's now common to show that a sliding drawer menu exists).
I've tried a number of things but have yet failed to find a method where both the views scroll smoothly together. Another way of interpretting the requirement is saying I want to programmatically fake a user flicking the page briefly.
Try calling the method fakeDragBy(float)! According to the documentation you need to first call beginFakeDrag() to initiate it and then call endFakeDrag(). This will mantain the ViewPagers default snapping behavior, so once you've revealed the other screen is there you don't have to animate the transition back, simply call endFakeDrag and the ViewPager will correctly snap back to the last screen (As long as you haven't dragged it past the half-way mark).

How to go about building an expanding fragment in Android?

So, I'm working on a media player application.
I would like to make something similar to Google Play Music's or SoundCloud's slide up mini-player to full-player UX.
I'm not really sure how to tackle that, though. Is it simply two fragments/views? I can understand how to transition onClick with animations, but how would I go about the fluid dragging?
Yes, it can be done with a fragment, OnTouchListener, and dragging the fragment up. I've done it with a click event and animation with no dragging.
The activity is on the bottom and the container with the fragment placed on top via the xml.
I wouldn't call it expanding though. Its just not fully revealed on screen (i.e. the location is on and off the screen and the fragment isn't actually changing).

RelativeLayout required to display fragment on top of each activity?

I want to make it possible to display a fragment on top of every activity (if the right action is called). It should look like a window on top of everything. This works fine so far, but I am a bit confused about how to get the layout integration working.
When I wanted to display something like a fragment on top of everything, I had to use a RelativeLayout as the root element, then nesting maybe LinearLayout (containing the activity's layout) and fragment.
Is that the only way to achieve this? Do I have to refactor now every activity layout to use RelativeLayout as the base? Or is there a more straightforward way?
I cannot comment, so will write here. Please provide some code to express what you mean, much easier to understand it than. If i understood you correct, u want to have a window on top of another window?
Cannot see why this would be voted down, and not even a comment for the reason :/.
You might achieve what you want with an overlapping fragment. I have had this side effect when making my app, i.e. that a fragment view is transparent on top of another fragment. To achieve this, just skip if(savedInstanceState != null){return;} in your onCreate() in your activity. And instead of replacing a fragment (transaction.replace) use (transaction.add)

Shouldn't there be an option for Fragments to retain click events within their view hierarchy?

After seeing a couple questions here on SO regarding Fragments "passing" their click events down to clickable Views in underlying Fragments, I recalled that I once encountered this problem. What is actually happening is that if a user clicks on a blank area of the top most Fragment, since its ViewGroup is not clickable, the event will be handled by the clickable View (i.e. Button) that is conveniently placed just below the user's finger. I fixed it by making the top Fragment's ViewGroup clickable. Back then I didn't give it much thought, but this solution seems a bit "hacky".
I understand that it is normal behavior for a View that is non clickable by default to not intercept click events, but one would think that given that one big use for Fragments is to display the view hierarchy (a task done by the Activity only before) that it will resemble an Activity in this sense. When one Activity fires the Intent to create a new Activity, and then this Activity is on the screen, no click events are delivered to the underlying Activity. I realize that an Activity can contain many Fragments that may not fill the whole screen or even have no xml, but sometimes click events are only meant to be retained by the top most Fragment.
With all that said, here come the questions:
1) Is setting the ViewGroup on the top most Fragment to be clickable the best way to solve this?
2) Does this feature exist and I am not aware of it? And if not, should it?
Is setting the ViewGroup on the top most Fragment the best way to solve this?
Assuming that your UI is akin to the UI from the question you linked to, the UI is written improperly.
My take on the UI from that question is that the developer has two fragments, A and B, each of which fill the screen. A is there initially, with the three buttons at the bottom. The developer then calls add() to display B, where B has an opaque black background.
This is dumb on a few levels. Not only do you run into this touch event propagation issue, but you have overdraw problems, because Android is going to render the buttons, then render the black background on top of them.
The right answer here is to have B replace() A.
(I realize that the developer actually does not have a fragment A, but has those widgets in the activity, which adds another level of sketchiness to that UI)
More generally, I would not have fragments, or anything else, higher on the Z axis with the intent to hide underlying widgets. So, for example, having a full-screen VideoView, with a pop-up MediaController higher on the Z axis is fine, because touch events destined for the controller would be picked up by the controller, yet the user can still tap on portions of the VideoView not blocked by the controller. Conversely, I would not implement a tabbed Web browser by having one WebView overlay another WebView on the Z axis -- either there would only be one WebView, or there would only be one visible WebView (with the other removed from the view hierarchy or marked as View.GONE).
When one Activity fires the Intent to create a new Activity, and then this Activity is on the screen, no click events are delivered to the underlying Activity.
That is because there is no "underlying activity" in terms of the view hierarchy. More technically, each activity is in its own Window, and so even if the top-most Window does not fill the screen (e.g., dialog-themed activity), the "underlying activity" is visible but cannot receive touch events.
I realize that an Activity can contain many Fragments that may not fill the whole screen or even have no xml, but sometimes click events are only meant to be retained by the top most Fragment.
Then there should not be anything underneath "the top most Fragment", IMHO. Use replace(), not add(), when doing this sort of UI switch. Or, use a DialogFragment, if you want to temporarily have something modal take over foreground input (as a dialog gets its own Window, if I understand correctly). Do not just paint a solid background and pretend that other widgets, now painted over, do not exist.
Does this feature exist and I am not aware of it?
No, because fragments are not ViewGroups and therefore are not involved in managing the routing of touch events.
And if not, should it?
IMHO, no, though you're welcome to file an issue for it.

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