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.
Related
I am developing an Android app and the layout I am currently working on is a ConstraintLayout.
I need to place three elements below one "top" element, like this:
How it should be
Using horizontal and vertical chains I managed to do it like this:
How it currently looks like
However, I don't know how to place the first and the third small box also directly below the big box. I understand that I somehow need a vertical chain, but I don't know how to do it because I only have one big box I can chain them to and I already used it for the small box in the middle.
The only thing I can think of is to add e.g. TextViews without a text to both sides of the big box and then chain the other two boxes to them, but is there maybe a more elegant solution to this?
Thanks
You can follow something like the following code snippet to achieve your desired UI,
<ConstraintLayout>
<View android:id="#+id/topView" />
<View
android:id="#+id/bottomView1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/topView" />
<View
android:id="#+id/bottomView2"
app:layout_constraintEnd_toStartOf="#id/bottomView3"
app:layout_constraintStart_toEndOf="#id/bottomView1"
app:layout_constraintTop_toBottomOf="#id/topView" />
<View
android:id="#+id/bottomView3"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#id/topView" />
</ConstraintLayout>
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.
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.
I'm building an Android app that requires backward compatibility to API 10.
I've built a series of Help Dialogs for each Activity in the app with the following layout pattern:
<ScrollView>
<LinearLayout>
<Series of TextViews />
<Space />
</LinearLayout>
<ScrollView>
I found the Space view necessary because the dialog cuts off the last couple lines of the last TextView with the "Done" Button (which is not in the layout file, but was placed there by AlertDialog.Builder).
What can I use in lieu of the Space view that will provide the same functionality OR what can I do with the layout that will render the manual creation of space at the end unnecessary?
Thanks!
You can just use View, something like
<View android:layout_width="match_parent"
android:layout_height="8dp"
android:visibility="invisible"/>
It will show up as an empty space. Experiment a bit with the layout height to get the kind of spacing you need.
You can also take the source code of the space view from the Android SDK and copy it into your own code. It overrides draw(Canvas) to do nothing at all, which is less than what View does by default, so slightly more efficient.
I am developing an android app, where the entire UI is being developed in Java, since there's alot of dynamic stuff involved, like i might have to add buttons and checkboxes, depending on the user interaction.
I want to know how to position 2 different views relative to one another?
if i was using XML, i would've written like this:
<RelativeLayout ...
<EditText android:id="#+id/text1" .... />
<Button android:id="#+id/button1"
android:layout_toRightOf="#id/text1" .... />
</RelativeLayout>
Now how do i do the same thing using Java?
This is similar: How to lay out Views in RelativeLayout programmatically?
And this looks exactly like your question: Setting parameters on child views of a RelativeLayout