I typically organize my code/logic by a fragment represent one layout. Now I am in need of few relatively simple forms to get input data from user, which are somewhat related in purpose.
Say I hav 3 screens, and I could create 3 fragments to handle them (display view, read input, submit, ..). Or should I use one fragment, and use FrameLayout create a stack of layouts. I was thinking like, stacking all 3 views and hide/display the view I like. But the documentation say
Generally, FrameLayout should be used to hold a single child view,
because it can be difficult to organize child views in a way that's
scalable to different screen sizes without the children overlapping
each other
Any good way to do this or should I create multiple fragments for this (the down side of this is lot of small classes and repeated code. I may use a base class, still like to explore other options)
Thanks.
It sounds like you don't really care that much if the views overlap each other in the FrameLayout, or in fact they are supposed to overlap because you expect to be showing only one at a time. FrameLayout can certainly display stacked child views that each take up its full width and height just fine, and if you set the visibility of the unused views to INVISIBLE or GONE, they will not intercept screen presses or take focus if they happen to be located above the visible view the user is interacting with.
On the point of readability and code maintenance, I think swapping fragments makes more sense though, even if there is more memory overhead. The layout management can be encapsulated within the individual fragments, and you do not need to worry about showing/hiding views, as fragment transactions will take care of that aspect.
Related
I have inherited a project where its user input screens are using single layout file. Depending on the type of user input required to show, a group of views are hidden or shown via View.GONE and View.VISIBLE. I don't understand why the old programmers did this. Is there a performance gain in this approach?
Official guideline about Improving Layout Performance
Sometimes your layout might require complex views that are rarely
used. Whether they are item details you can reduce memory usage and
speed up rendering by loading the views only when they are needed.
You can use ViewStub. It is zero sized invisible View that can be used to lazily inflate layout resource at runtime.
Sometimes might need to re-use larger components that require a special layout. To efficiently achieve this, You can try with Re-using Layouts with <include/>. Good way to share layout parts between different layout’s.
It could be a case of performance gain as Views will not be rendered. However, I am not certain why those developers went with this approach. If there are multiple views are not going to be used then rather create two separate layouts and based on the user, inflate one or the another.
In an Android application I'm building, I have a single activity which has multiple buttons and textviews. Based on user actions, I hide the elements and/or show them. This is intentional, cause I don't want the user to change activity.
For further clarity, the activity is a type controller. So when a user enables an option different buttons show up. This is why I want all of them in the same activity.
I am concerned about performance. Currently everything is in a Constraint Layout. Is there an effective way of having mutliple UI elements in the same activity, and having the ability to hide and show them at will? Should I look into Fragments?
Thank you in advance.
As it turns out there isn't a clear answer.
There are a few solutions that may prove useful, I list them below for anyone who might stumble onto this:
Fragment is useful when you have multiple independent parts of your layout. You are limited in the communication between elements of different Fragments.
ViewStub is used when you have some elements which are rarely used in your layout. This makes the initial loading of the layout lighter by not inflating the elements in the ViewStub. You can then inflate the elements on demand.
ViewFlipper allows you to cycle through a list of elements (or display them selectively using setDisplayedChild). It's mostly used for single elements, so I'm not sure about its performance if you were to use it for showing and hiding nested layouts.
ConstraintLayout is probably the best solution for cases similar to mine, where you have a layout of buttons and text which are hidden and displayed in a complex manner.
In my app, for instance, when a user creates a new post, he or she can select a type of media (photo, video, text, place, etc.) and then review it in the following activity.
The way I have been doing it is to have all of the views (i.e. ImageView, VideoView, WebView, etc.) there, but set their visibility to invisible, unless the user chooses that type of media.
For instance, all of the views are invisible until the user takes a photo and then only the ImageView is visible. This seems wasteful though. Before I start the activity, I know which type of media the user chooses, but still have the invisible, unused views.
Would it be smarter to have separate layouts for each type of media with the repeated elements (the create post button, the privacy and venue buttons, etc.)? But this would violate the DRY principle...
How costly are invisible views? What is the correct way of doing this?
Depends on the complexity of the Layouts, I had this issue in previous app, in first iteration I did like you, but in 2nd iteration I found its hard to optimise single layout with bunch of invisible views; much less the if else cases to toggle views visibility.
and about layout performance, also it depends on layout/design complexity, I don't think unused view will consume that much of memory or cpu.
so if your layout is simple, its okay for now, if not I recommend to use separate layout for each design/type.
and as #ashishduh said, the best is to set visibility to GONE instead of INVISIBLE, since the parent layout will not measure GONE views, but this doesn't prevent view usage of memory or cpu (mostly in custom views)
Basically I want one class to hold 3 separate Views on one screen.
I would like the top half of the screen to display a panoramic View (which I have defined in Panorama.java), and the bottom half will be split in half vertically and have 2 separate Views on them. On the left I would have my map class(CampusMap.java) and on the right I would have my other Activity (CampusTour.java).
Is this possible? If so, how would I implement it?
Fragments may be what you are looking for.
You can have multiple fragments on the same screen at the same time.
Fragments my friend...the answer you seek is Fragments...
They are basically modular code blocks that consist of an XML file married to Java code. They can be populated inside of a single container view, have work done to them via the container or via their own code, and can be removed and added at run time
you can only run one activity at a time. You probably looking to implement three views in a single layout.
I have a ListView with layouts in them. Sometimes the layouts need to look one way, sometimes the other. They are mainly text laid out in different areas with different weights sizes etc. The ratio of main views compared to other views is about 5:1. When it needs to be changed only 2/3 of the whole view changes.
I think I have two options :
(the way it is now) One layout(so it never has to be re-inflated, as the recycled views are all the same) and the 2nd 2/3 of the view is hidden until it is needed to be changed, then code will reveal it and hide the original 2/3 of the view.
(other way) Two layouts, with the 1/3 layout duplicated, and each having its on other 2/3. Then when one of the different layouts needs to be used, the old view from the ListView recycler gets thrown away and a new correct view is inflated, and back again when the list is moved.
So what I am asking here is that is it better to hide/show parts of the same layout to prevent the recycler in a ListView from inflating more layouts, or have two cut-down layouts with no extra hidden views, and have them inflated when they are needed?
If the TextViews are the main part of those layouts, I don't think there is going to be a big difference in performance so you could go either way. I would go with option two because:
The ratio between the number of normal rows layout vs special rows is big. If you keep the single layout approach then you'll have to modify the layouts in code for each of the rows, normal or special, because you could be dealing with a recycled View that has 2/3 part hidden when it's time to show a normal one(so you end up modifying the layout each time). If you were to use the second option then you could eliminate this part from the getView method and simply use a switch to see with what row type you're dealing with(no more modification of the row layout each time in the getView method, you let the ListView handle that by providing you with the correct type of row layout). Don't worry about inflating another layout file(once), this isn't the performance hit to be afraid of.
Using one type of layout it means you're having Views remaining in memory even if the user doesn't see them(so you may be preventing the ListView from inflating more Views(only one time, in fact) but at the same time you're occupying more memory with the ones you even don't show to the user). The first option has the advantage that the binding of data to the row is more simple as you have all the views at your disposal(even if the user doesn't see a part of them) instead of the second option, where you would have to see which data need to be shown based on row type.
Code readability. Having two row types and testing to see which one you get in the getView method it's more meaningful as you see what logic you have for each type of row. Also, it will be better if you plan to change those row layouts in the future or add more row types.
The ListView does a great job on recycling views as long as you help it with providing the row types.
Edit: The ListView will keep a recycled view for each type you declare in the adapter. So the ListView will inflate the second layout only the first time it finds it in the ListView, next time when it will need a row with with type it will use the recycled one(and it will maintain 2 types of recycled views, the first and second row type).
Actually this little bit of extra GC IMHO should not be the driver for your decision.
I would go the route that is easier to maintain and understand.
Also there is an nice useful include tag in xml like this:
<include
android:id="#+id/abc"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
layout="#layout/abc" , where abc = the xml file you want to include
/>