How to group multiple Views without using nested Layouts - android

Consider this situation:
<LinearLayout style="#style/Basic_W_mp_H_wc_Vertical">
<!-- IMAGE-1 -->
<TextView style="#style/Copyright_TextView_1" />
<ImageView style="#style/Copyright_Image_1" />
<include layout="#layout/layout_copyright_info"/>
<View style="#style/HorizontalSeparatorGray"/>
<!-- IMAGE-2 -->
<TextView style="#style/Copyright_TextView_2" />
<ImageView style="#style/Copyright_Image_2" />
<include layout="#layout/layout_copyright_info"/>
<View style="#style/HorizontalSeparatorGray"/>
<!-- IMAGE-X -->
[...]
</LinearLayout>
Now I want to hide copyright information for IMAGE-1. I have two options:
Create a wrap-layout (LinearLayout) with an Id, so I can find and hide it
Give Id for every View find and hide them.
The first option will work, but I don't want to create an extra nested layout for this.
The second option will also work, but my layout will get unreadable if every view has an Id.
I know there is a third memory-optimized option to group multiple views, but I can't remember how it works and google search gives me always ViewGroup...
Any idea?

You could try to use what's called the merge tag and pair it with the include tag. What this does is it will allow you to use the same layouts in different files (since you seem to have multiple groups together). The <merge/> tag will merge the elements in to the top-level layout (in this case a LinearLayout). I have not used it with this scenario, so I imagine what will happen is you will not be able to retrieve them in a group. It is worth a shot though.
I think option 1 is not a bad choice either for these reasons:
It's easier to code. If you don't group them together than you'll have an extra lines and remember extra IDs. With just one Layout wrapped around it, then you can just hide one layout.
It's easier to maintain. What happens if you change the copyright look? What happens if you want to change the rest of the layout? With one wrapped, it's easier to just fiddle around with one view and everything inside stays intact.
The performance hit isn't that bad. Overall, this looks like the top-most root view. Inflating this Layout won't be as bad as if you were say, inflating a ListView item. This is a one-and-done operation and that's it. You don't want to fall in to the trap of doing premature optimization where you sacrifice code maintainability in favor of optimizations without any benefit.

Related

What is the ButtonBarLayout and how should we use it?

When I developed, I found a new widget called android.support.v7.widget.ButtonBarLayout unexpectedly. I tried to search it on the internet, but nothing was found, even on the official development documents site.
In the meantime, I found two ButtonBarLayout when I search ButtonBarLayout everywhere in Android Studio, one is android.support.v7.widget.ButtonBarLayout and the other is com.android.internal.widget.ButtonBarLayout. I tried to read source codes of both, I found that they are the same except package name. So I thought maybe android.support.v7.widget.ButtonBarLayout came from com.android.internal.widget.ButtonBarLayout after the internal ButtonBarLayout was through tests and released. At the same time, ButtonBarLayout is inherited from LinearLayout.
But there are some question:
What can we get from ButtonBarLayout literally and how should we use it?
I noticed the variable of private boolean mAllowStacking. When it changes, orientation of this layout would be changed. But I didn't really understand what it is used for.
So does somebody know ButtonBarLayout well?
P.S.: I used Android Studio of 2.0.0 Preview 4 and Gradle Plugin of 2.0.0-alpha3 and Android Support Library of 23.1.1 and Platform-tools of 23.1 and Build-tools of 23.0.2.
As others pointed out, the class description tells exactly what it is: an extension of LinearLayout that automatically switches to vertical orientation when it can't fit its child views horizontally.
I might add that this was clearly done to fit with the material design specifications about dialogs. They make a distinction between side by side buttons and stacked buttons. See for example:
Side-by-side buttons are recommended when the text of each label does
not exceed the maximum button width, such as the commonly used
OK/Cancel buttons.
While you should go for stacked buttons when the single button is too large, or there's not enough room for both:
When text labels exceed the maximum button width, use stacked buttons
to accommodate the text. Affirmative actions are stacked above
dismissive actions.
So, one possible use of this class, is when designing your own dialogs. For example, AlertDialog and AlertDialog.Builder offer internal support for dialogs with buttons, but sometimes you just want to subclass DialogFragment or AppCompatDialogFragment for a better control.
There, it might be useful to setup a bottom button bar that follows the design guidelines, and have full control on the buttons (like enabling and disabling, things you can't do with an AlertDialog AFAIK).
The source code describes ButtonBarLayout as follows:
/**
* An extension of LinearLayout that automatically switches to vertical
* orientation when it can't fit its child views horizontally.
*/
So, in essence, it is nothing but a smart LinearLayout which manages auto-switching orientations based on available space on screen.
The same ButtonBarLayout.java file describes mAllowStacking in comments as follows:
/** Whether the current configuration allows stacking. */
Source Code Here
You are right first of all. ButtonBar layout does not seem to be featured anywhere in the official Android documentation. I tried myself to search about it, but to no avail. However I have found some information which defines what is a ButtonBar layout and when to use it. Hopefully this will help you.
Most tutorials use the Buttonbar layout in a dialogbox or at the bottom of a screen to confirm or decline an option. The image below is a visual representation of how the ButtonBar layout has been used in a screen.
The screenshot above has the following layout xml:
<LinearLayout
style="?android:attr/buttonBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:id="#+id/Button01"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Show" />
<Button
android:id="#+id/Button02"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Change" />
</LinearLayout>
<EditText
android:id="#+id/myView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10" >
<requestFocus />
</EditText>
So essentially what Android is doing here is simply creating two buttons next to each other in a LinearLayout with each button having the match_parent parameter set to the width. Hence each button takes half the size of the screen. Android have actually taken away the hassle of creating seperate buttons and positioning them correctly to fit different screens, by creating a simple widget handling this altogether.
As with the support library, Android have implemented this for developers using an earlier API. It is normal for them to use the support library for this purpose.
Hope this helps :)
https://android.googlesource.com/platform/frameworks/base/+/master/core/java/com/android/internal/widget/ButtonBarLayout.java
Looking into the code, I think it's a LinearLayout for buttons (duh). You can probably look at it like the Dialog buttons divided by a vertical spacer: | . AllowStacking will change the orientation to vertical and the gravity to the right instead of bottom. I should try it out to give a better answer
ButtonBarlayout is not featured anywhere in the official Android documentation.
it is used for auto-switching orientations according to the space.
Regarding your question:
How should we use it?
I guess it is undocumented because it is not stable yet.
It just popped up because this long lasting complaint originate from poor ROM modification by device vendor.
https://code.google.com/p/android/issues/detail?id=78377
See #270 for the resolution regarding classpath and why all classes inside .internal. were made public.
And nope even that fix a lot of bugs from poor ROM modification are still out there (in lots of device of well known brands). The issue is soon declined by project member.
I don't think we should use it just yet until the document show up.
Just my $.02 though.
Just to add to the other answers, if you guys want to check the orientation of a ButtonBarLayout you should check the orienation AFTER the value has called on measure.
In other words (Kotlin):
buttonBarLayout.post {
val orientation = buttonBarLayout.orientation
val height = buttonBarLayout.measuredHeight
}

Most Performant Android ViewGroup to Use For Independantly Positioned Children? - RelativeLayout vs FrameLayout

I'm no Android expert but I am aware of discussions regarding the appropriate use of LinearLayout and RelativeLayout, keeping the view hierarchy as small as possible, avoid unnecessary passes of onMeasure(), etc.
Lets imagine I have two ImageView's that I want to position completely INDEPENDENTLY, the first in the center of the parent and the second in the bottom left of the parent. (note this is a vastly simplified example of far more complex real life requirements).
The obvious way to solve this is using a RelativeLayout...
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="#drawable/first_image" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignRight="true"
android:layout_alignBottom="true"
android:src="#drawable/second_image" />
</RelativeLayout>
However something keeps telling me that a RelativeLayout isn't appropriate in this situation because I don't want to organise the children relative to each other. All I want to do is position the children according to the parent and I wonder if using a RelativeLayout causes some unnecessary layout calculations that I don't really require.
I am wondering if there is another ViewGroup type that would perform better? Its totally possible to achieve what I want with a FrameLayout for example but I've no idea if this is more performant or if I am abusing the intent of a FrameLayout etc...
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="#drawable/first_image" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|bottom"
android:src="#drawable/second_image" />
</FrameLayout>
Maybe there is another Layout type I am unaware of?
Short answer
Given the information you have provided, the FrameLayout has a good chance of performing better. As you may have learned already watching (Adam Powell quote in Google I/O 2013 conference),
[...] RelativeLayouts will measure child views more than once in order to solve some of the constraints you give it. So, being generic has a cost [...]
From what I read and understood, this is not guaranteed and it depends on the constraints you give it.
Long answer
It really depends.
We all read Romain Guy blog post : Android Layout Tricks #1, who said that most people misinterpret his post and started using RelativeLayout everywhere.
This post, if you haven't read it, talks about how removing one hierarchy level using a RelativeLayout instead of a LinearLayout which saves loading time in a list.
Basically, it means that if you don't need them, as you described it yourself
[...] I have two ImageViews that I want to position completely INDEPENDENTLY [...] I don't want to organize the children relative to each other
you should not use them because of that reason.
Concrete example of : "Don't use them if you don't need to."
For instance, in one of our applications, we have serious performance issues on devices running Gingerbread -- which we want to support.
Our most complex layout involves a vertical ScrollView, attached to the current activity, in which we have several containers and one HorizontalScrollView that displays images and information which are contained in a complex LinearLayout.
We started to replace the LinearLayout by RelativeLayout. The result: no obvious improvement -- equivalent or maybe worse.
Since that layout is fairly complex, adding more RelativeLayouts embedded in each other just increased the onMeasure() calls that were made for a single draw.
Even a small circular ProgressBar was now spamming the UI thread with several measure calls because it was in one of those embedded RelativeLayout which triggered recalculations of the whole view.

Avoid impact to performance, when designing activity with more than 80 views

I'm new to android. I'm creating an application, which should handle more than 200 settings, mostly Boolean. Settings can be grouped by they type, there are 5 groups. I assume, that users won't like to configure and save each group separately,but would like to configure all the settings and by pressing save -> save all of them at one time, so scenario with having 5 different activities for each setting group doesn't suite.
What I've tried to do, is set up a TabHost, with separate tab for each group. After I've got "more than 80 views" warning, I've split up my layout, and now each group has own layout.xml;
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TableRow
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<CheckBox
android:id="#+id/cbSetting1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/strSetting1" />
</TableRow>
<TableRow
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<CheckBox
android:id="#+id/cbSetting2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/strSetting2" />
</TableRow>
...
</TableLayout>
And I'm inflating those views onCreate:
View setting1View= getLayoutInflater().inflate(R.layout.group1_layout, null);
group1Tab.addView(view);
With this steps done, I'm avoiding "more than 80 views warning", but won't have it impact on performance, when all views are inflated -> activity will have more than 80 views in total?
Next question: should I get references to all CheckBoxes on my views onCreate:
CheckBox setting1 = (CheckBox)setting1View.findViewById(R.id.cbSetting1);
or should reference them on my saving button press, like:
onSaveClick{
Boolean setting1Value = ((CheckBox)setting1View.findViewById(R.id.cbSetting1)).value
}
or in some other way, to have as little performance impact as possible?
Is there any "good pattern", for designing apps with a lot of views?
Thanks in advance!
P.S. I know, that "best practice" questions are not recommended on StackOverflow, but I've tried to ask as defined questions as possible, and, hopefully, my post is showing at least my researching effort on the issue.
Update
My fault not mentioning it earlier - those settings are stored remotely, and are accessed using HTTP requests (using Web-api). Does suggestions about Preference activities/fragments and ListViews fit in this case?
Based on the way you have described your application, it seems like you have many similar views. I would recommend using a ListView in each of your tabs. ListViews very efficiently handle tons of views.
You will need to write a custom adapter for you ListViews, but you can do this cleverly in a way that doesn't call findViewById() all the time (using the ViewHolder pattern).
It is hard to give specific advice because you have not described exactly what these settings items will contain, but this general idea works well when you have long lists of (event potentially slightly different) views. This pattern would work if you want to have a lot of flexibility over you layout. If you want some standard settings behavior, check out PreferenceFragments, or check out Android's settings developer guide.
If its just boolean settings [i.e. Checkbox].
Then I would prefer trying PreferenceActivity, its just like another activity but preferably used for settings functionality. Also there is an easy way to group your settings element, try PreferenceCategory for grouping.
A small tutorial is available here.
CheckBoxPreference is what you need.
Hope this helps!

Can I create a statich part of view

I`m wondering about one thing. If I decide to have a part of my View same in every Intent. For example 2 buttons at the bottom of screen and for example I have 3 diffrent views, List, Detail and a third one :) Do I need to put the buttons on every xml schem for each view or can I create other xml and attach it in each activity with all listener etc.
If I can attach in activity how can I do that ?
Create a XML buttons.xml with the common elements
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<ImageButton
android:id="#+id/myButton"
android:src="#drawable/ic_title_search"
android:onClick="myHandle" />
<ImageButton
android:id="#+id/myButton2"
android:src="#drawable/ic_title_search"
android:onClick="myHandle" />
</merge>
Include it in another xml:
<include layout="#layout/buttons"/>
where buttons is the name of the xml file to be included
You can use the <include /> tag in your XML files.
See Layout Tricks for an example.
Create a separate layout for your buttons then in the layout you wish to display them use the include tag.
This will allow you to reuse the same layout in multiple parent layouts.
The include works as stated above you could also consider using fragments
Fragments
You can use these in older versions of Android by including the compatibility library in your application. It's definitely more work than a simple include but if you need some reusable UI for more sophisticated features than simple buttons you might want to look at that as well
How to use compatibility API

HTML formatted content in a ScrollView

I'm trying to put together an Android view that has several elements stacked on top of one another. Some of these elements need to have HTML formatting applied, and I plan to stack enough of them that they will run off the screen, requiring a ScrollView. As an example, I would expect the layout to look something like this:
<ScrollView>
<LinearLayout vertical>
<TextView />
<Button />
<Html />
<TextView />
<Button />
<Html />
Etc...
</LinearLayout>
</ScrollView>
The obvious choice up front for the HTML portion is a WebView, since it renders everything exactly as I would want to see it, but the problem is that the WebView begins to fall apart when used in a ScrollView. It's difficult to get it to even show up without some manual refreshing.
Given that, what would be the most effective way to display this type of content?
Option #1: As Sameer Segal indicates, use Html.fromHtml() and TextView.
Option #2: Render the whole thing in HTML. There is nothing particularly magic about Android TextView and Button.
Option #3: Choose some other UI model that would eliminate the need for the ScrollView.

Categories

Resources