Manipulating layout on a previous activity in Android - android

I have an application that has a list of buttons created dynamically in the code. When one of these buttons is clicked, a new activity containing a similar list of buttons is added on top of the stack.
These lists of buttons each have a different view for portrait and landscape, so I am overriding OnConfigurationChanged to lay update the existing buttons because it is faster than letting the view recreate itself.
When the second view changes orientation, even though the previous activity is in the background, it performs the changes to the buttons in its list.
The second activity is also transparent and you can see the previous activity through it. Normally you won't see the first activity from the second activity, but the entire second activity is in a HorizontalScrollView and the user can slide the view off the screen which then finishes the activity and goes back to the first activity.
The problem is that when there are hundreds of buttons on each activity and both activities are being updated on orientation change, things slow down considerably.
In all my cases, I have noticed that things go smoothly if only one activity is being updated on orientation change. Is there any way I can postpone the previous activities changes OnConfigurationChange or speed this up in general?

Related

Can you measure the height of a view on an activity that's not been loaded yet?

I want to make an animation on click that a button slides down to the position of another button and at the same time I'm loading another activity. This other button is on the new activity. Picture it as if a button from one activity is replacing a button on another activity, so it has to slide down to where the new button is.
Can I measure this new button's position before the activity is loaded? So I can get the animation right for all screen sizes.
Activities are designed to be used as full-screen components, meaning that you understand that the other activity that pops in is going to take the full screen. If that is your goal, you can use shared element transitions with the activities to get the desired effect: https://developer.android.com/training/transitions/start-activity#start-transition
On the other hand, if you need both activities to stay on the screen, than you should rather to use fragments, as activities are not suited for that. For more info on that approach, see here: https://developer.android.com/guide/navigation/navigation-animate-transitions

How to alternate between fragment containers easily?

I've got a problem that I'm having problems solving. My app has 2 types of fragments. When the app starts, a fragment with main menu is added to a FrameLayout that I use as a fragment container. This fragment takes up the entire screen. Then, when I choose one of the items in the menu, a corresponding fragment should be loaded into the container, replacing the menu. However, this fragment must only take 1/4 of the screen from the left, and the space outside is to be used by some other fragment.
I was thinking about making 3 FrameLayouts, one for the left side, one for the right and one for the entire screen, but this is going to have problems with fragment transactions, since I would have to keep tabs on which fragments are where and remove them by hand.
Basically what I need is some way to change whether my fragments are loaded into a container that takes up full screen, or a container that takes up only some part of the screen. I probably could do it with tons of trail and error and some code, but I bet there is a really easy way to do this in android that I missed.
Instead of trying to dynamically load these fragments into the various containers, I would suggest having two different Activities.
It sounds like the main menu fragment will only ever appear on its own in full screen. So, make that a full Activity (let's call it MainMenuActivity).
The second activity will have two FrameLayouts as it's contents, with one taking up 1/4 of the screen and the other taking up the remaining 3/4. Load this second activity upon choosing a main menu option and populate the fragments in onCreate() of the second activity.
Hitting the back button from the second activity will return the user to MainMenuActivity.

Android Two layout for one activity

I have a form, and I have chosen to divide it in two steps.
To do it, I created two layouts for a same activity. When the user complete the first form, I call the second layout with :
setContentView(R.layout.activity_form2);
The problem is, if the user wants to come back at the first step of the form, it's not running, because he comes back to the previous activity.
Is it correct to do that, or I need to use fragment?
Otherwise, how can I do to come back on the previous layout, and not the previous activity?
Never set different layout's for the same Activity. You can navigate to a different Activity or you could use Fragments.
Layout is set to the Activity and when you click back button Activity is popped from the back stack and previous Activity in the stack takes focus. So setting different layouts for the same Activity is not a good choice.

Save screen position when changing to different activities

I have a relativelayout with 30 buttons within a scrollview. What I would like to know is if there is a way of saving the position, ie. when the user has scrolled down to the second last button and clicked on it to display an image or text, and when pressed back to select a different button to return to the last position (which was the second last button for example) without having to scroll all the way down again? I had a sliding drawer and it worked fine, but with the buttons (which are image buttons) it takes a while to load the screen with all the buttons. And I found doing it without the sliding drawer it loads faster but now have to scroll all the way down to the button every time I return to the buttons.
Android docs say here:
[...] you should use the onPause() method to write any
persistent data (such as user edits) to storage. In addition, the
method onSaveInstanceState(Bundle) is called before placing the
activity in such a background state, allowing you to save away any
dynamic instance state in your activity into the given Bundle, to be
later received in onCreate(Bundle) if the activity needs to be
re-created.
Perhaps you just recreating your activity content by accident.

How to manage UI state and the back stack in a single/dual-pane layout

I'm having trouble wrapping my head around how to properly manage Fragments in a typical list-detail design pattern.
My layout is working fine and is structured like this for the landscape view (dual pane):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout ... >
<FrameLayout android:id="#+id/list" ... />
<FrameLayout android:id="#+id/container" ... />
</LinearLayout>
And like this for the portrait view (single pane):
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout android:id="#+id/container" ... />
I also have a refs.xml in res/values-w600dp/ to make sure the appropriate layout is loaded based on the screen width of the device.
When a list item is selected, the landscape view should show the list and the details side-by-side, while the portrait view should show only the details fullscreen. When nothing has been selected, the landscape view should show the left on the left and blank space on the right, while the portrait view should show only the list fullscreen.
However, here's where I'm having trouble:
Do I use a "main" Activity for the list + optional details layout, and another "details" Activity for the portrait, details-only layout? This seems to be what the Fragments guide example does. I've gotten this approah to work generally, but how do I maintain the state of my details fragment when the orientation changes?
Consider the opposite case shown above -- rotating from portrait to landscape while the details are visible means the details Activity would need to be finish()ed so the main Activity could display the two-pane layout, but this also destroys the details fragment and its savedInstanceState. If the user has typed information into the EditText fields in the details fragment, then rotates the device, how do I preserve the entire UI state of the details fragment when I add it to the main (two-pane) Activity?
Do I use only one Activity and manage the Fragments myself? This allows me to retain the state of the details UI when the orientation changes (because Android takes care of this automatically), but it gets messy when it comes to the back stack.
Consider the case in the image -- rotating from landscape to portrait when the details are visible should show show the details single-pane, but how do I properly manage the back stack and ActionBar home icon to show the list single-pane? Rotating back to landscape would also need to undo whatever back stack manipulation I did previously, as both fragments will be visible at once.
After some more searching, I found two similar questions (Switch from dual pane to single pane on orientation change maintaining fragment stack and Retain Fragment state between Activities), but my situation is slightly different because I'm not trying to retrofit this functionality but best plan for it up front. What am I missing? Surely Android can manage both the back stack (as in the multiple Activity case) and the UI state (as in the single Activity case) at once, right?
I solved this by going the multiple activities route. See my answer to "Retain Fragment state between Activities".
The key was using FragmentManager.saveFragmentInstanceState() to save the state of the fragment's UI and Fragment.setInitialSavedState() to restore it when instantiating the same fragment in another activity.
For my purposes, I found that I needed to save the UI state in two cases. I created a helper method public void saveState() inside my fragment and call this from the fragment's own onPause() method as well as from my "main" activity immediately prior to using replace() to attach a new instance of the fragment to the dual-pane layout.
I'm still interested in know if the back stack manipulation required for this type of single/dual-pane layout scenario is possible or if the single activity approach would require overriding onBackPressed and simulating a back stack manually.
It is possible to use only one Activity, but you'll have to manage the backstack when in portrait orientation yourself.
As you describe the behaviour of the app, there could be 4 states:
State A: portrait, showing the list fragment.
State B: portrait, showing the details fragment with the list fragment on the back stack.
State C: landscape, showing the list fragment on the left and a blank space on the right.
State D: landscape, showing both the list fragment and the details fragment side by side.
Imagine you are on state D (with both fragments, let's call them FA and FB), and you change the orientation of the phone. The following state should be the state B, but the problem is that your portrait layout only has one FrameLayout. Using the following as the single pane layout:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout android:id="#+id/list" ... />
Android will recreate FA and will have it attached to that FrameLayout. FB, on the other hand, will also be recreated but will not have a container associated, so it won't show up. At this point you could create another fragment, FB2 with the same contents as FB, and use it to replace FA. You will have FA-FB2 in your backstack and FB hidden.
If you change the orientation again (expecting the state D), you can use onSaveInstanceState() to pop FB2 from the backstack with popBackStack(), thus having again FA and FB. Before removing FB2, you may also want to copy its content to FB. When the app is again in state D, FB will have its FrameLayout.
There would be a few other transitions and situations that you would have to take care of, but the main idea would be that.
It's not a very elegant solution, so I am sure that it has to be a better, maybe more efficient (without replicating Fragments for example) way to solve this problem.

Categories

Resources