Android centering text in lists - android

Say I have a list of Strings with the elements:
"One",
"Two",
"Three",
"Four"
I want to center them in the middle of the screen but I want to do it in a way that the start of each word is next to each other.
Like this:
One
Two
Three
Four
Considering that the font probably has different length per character, how do I do this best in Android?

I'm not sure how your application is behaving and if a ListView is strictly required, but the effect you desire can be achieved using TableLayout and TableRows. The TableLayout will line up the elements in each column for each row as you have described.
Having said that, TableLayout does not support having lines between the rows or gridlines (although I have seem some clever hacks involving changing the background colour of the TableRow to black, and then changing the padding and background colour of the View objects in the TableRow to white to get a black divider line - but that doesn't always work depending on your View objects).
I'm in a similar pickle, and that was the first avenue I examined. It didn't have a solution for my situation, but this might work for you. And if you do find a way of lining up the text in a List, I'd love to hear about it.
EDIT:
I also feel it is worth mentioning (based on how the conversation is progressing) that you can also set row.setOnClickListener() and make an entire row clickable in a TableView. Once you wrap it in a ScrollView, it's pretty list-like.

you can set the gravity at the elements you want to be center and for detail
android:gravity="center_horizontal"

Wrap your ListView in a LinearLayout with layout_gravity="center_horizontal" or
nvm: that won't work obviously..
So wait.. You want a list, where each line is clickable for the whole width of the screen, and you want to justify all lines to left, and ALSO center all of the justified text without breaking justification?

It sounds like you want to place your items within a parent with layout_width="wrap_content" and center the whole parent.
Something like this, perhaps?
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView android:text="Content above..."
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal">
<TextView android:text="One"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView android:text="Two"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView android:text="Three"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<TextView android:text="Content below..."
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
Remember the difference between gravity and layout_gravity. The gravity attribute refers to the view's content. layout_gravity (and all other attributes prefixed with layout_) refers to the view's layout within its parent.
Edit: If you're looking to format ListView items similarly, try something like this as your list item layout with the ListView itself using layout_width="fill_parent" and layout_height="fill_parent":
<LinearLayout android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
android:weightSum="2"
android:gravity="center">
<TextView android:id="#+id/text"
android:layout_weight="1"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
Change the content of the TextView with id text in each list item in the usual way. The minHeight setting pulled from the current theme will make sure it stays a good size for touch.
The uniform centering in this case is handled by a combination of the weightSum and gravity on the LinearLayout and the layout_weight on the TextView. The TextView's weight divided by its parent's weightSum will determine the percentage of horizontal space the LinearLayout will give it. In the example above it will get 1/2 the available horizontal space, but centered.
Since ListView never knows the content of list items that are not currently onscreen there is no way to have it measure the text of every item in your adapter to center the content perfectly. You will have to approximate it using a list item layout like the example above.

Related

Why my TextView under an ImageView is not showing

I am writing an Android game. In the level selection activity's layout file, I want to layout the levels' buttons (They are actually ImageViews) like this:
x x x
x x x
And each level button has a TextView, with that level's name as the text, below it (Let's call these two views together as a "level choice"). I used a lot of LinearLayouts to do this. Here is the code for a level choice:
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal"
android:layout_weight="1">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/angles"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/angles_level"
android:textSize="#dimen/level_text_size"/>
</LinearLayout>
As you can see, the two views' height and width are all wrap_content. But when I look at the designer, the text view doesn't show up.When I select the text view in the component tree, it shows where the text view is:
P.S. The picture isn't showing all six levels because I haven't made them yet.
As you can see, the text view is right at the bottom! When I select the ImageView, it shows that it is occupying all the space of its parent!
I don't know why this is happening, my image is certainly a square! Can you explain why this is happening and how do I fix it?
If you need my whole layout code, feel free to tell me in the comments.
For me, the best solution is to position and size it properly by code (where you have total control) instead of xml.
Anyway, i think your problem can be solved by setting ImageViews ScaleType
imageView1.setScaleType(ScaleType.FIT_START);
By XML:
android:scaleType="fit_start"
Hope this helps.
I use background color for textview when I'm studying the layout.
If you use wrap content in both dimension for TextView, that is invisible since you did not write any text inside it. wrap content means that the view take the minimum space. And no text means 0px; try to set ImageView and TextView with layout_weight 1 and layout_height 0dp. In this way both view take half of space of parent layout
Because right now, your LinearLayout doesn't know how to distribute the ratio of its children. And in fact, your imageview's wrap content already
consumes the whole space.
So, LinearLayout says "Sorry TextView, you have no space left".
Use layout_weight to both of the children.
I guess you want to have your picture twice the size of your text.
2:1
That is,
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal"
android:layout_weight="1">
<ImageView
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight=2
android:src="#drawable/angles"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight=1
android:text="#string/angles_level"
android:textSize="#dimen/level_text_size"/>
</LinearLayout>
I just realized that I posted a question about ImageViews leaving out too much whitespace:
LinearLayout leaving out too much white space. Why?
I think this is the same as that problem. So I tried setting adjustViewBounds to true in the xml. And it works! Now the image view look like this:
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:src="#drawable/parallel_lines"/>
You can use relative layout
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/angles"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/angles_level"
android:textSize="#dimen/level_text_size"/>
</RelativeLayout>
or simple you can set background of textview to that image by putting this
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/angles_level"
android:background="#drawable/angles"
android:textSize="#dimen/level_text_size"/>

match_parent not performing as expected

I imagine this should be a fairly easy one to answer, if you understand XML Layouts better than I do that is. I don't seem to get what I was thinking I should when using the match_parent layout_height.
I have a LinearLayout root element with android:orientation="vertical". Inside this LinearLayout I want three elements:
- TextView
- ListView
- TextView
For both the TextViews I set android:layout_height="wrap_content" so that they will be only as tall as is necessary to display their contents. The thing is, I want the one TextView to sit at the top of the form, the other one to sit at the bottom of the form while the ListView fills up whatever space is available on the form. So here is what my xml layout looks like:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="Top TextView" />
<ListView
android:id="#+id/listView_Species"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="Bottom TextView" />
But it doesn't work. Here's what I get. I've selected the ListView so that it will be highlighted. Notice how it extends all the way to the bottom of the form, pushing the bottom TextView off the form.
When I change the layout_height property of the ListView to some fixed value, like 180dp, this is what the form looks like. I'm just posting this to prove that the bottom TextView is there but I still don't know how to get it to be fixed to the bottom of the screen while the ListView takes up whatever space remains, but in between the two TextViews.
Thanks in advance.
While the other answers try to fix your problem (which they don't actually--they suggest you do something that looks similar but may or may not look good on different devices), no one has filled in the gaps in your knowledge of LinearLayouts and match_parent. And these gaps are very common--Google's documentation is still far below stellar.
First, how do Views work within a LinearLayout? Let's go through the process of drawing a LinearLayout, using orientation="vertical" for simplicity.
Examine the height of the first child of the LinearLayout (LL for short). If the height is match_parent or fill_parent (old name for the same thing) then the height of the View is stretched to fill the entire viewing area. If the height is wrap_content, then measure the vertical space the View takes and use that space for the View. If the height is a non-zero number, use exactly that many pixels for the View's height (may clip if too small). If the height is 0 see below.
Put the next view below the view in 1. Check its height and act accordingly.
Continue for all the Views. If a View is pushed off the bottom, go ahead and stop calculating because no one will see it or any succeeding Views (assuming no ScrollView).
If the height of a View is 0, check it's gravity. This requires a second pass, storing the gravity of all the views and then allocating their heights proportionally. As you can guess, the second pass doubles the time layout takes, which isn't significant for simple layouts.
Explanation of your example: The first child of the LL (the first TextView) is measured and takes a certain amount of pixels. Then your ListView takes all the remaining space (via match_parent). And then your second TextView is not drawn at all as it's off the bottom of the screen. Which is pretty much what you observed, but now you understand why.
Solution: Use RelativeLayout. Works perfectly in this case.
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/top_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:textSize="30sp"
android:text="Top TextView" />
<TextView
android:id="#+id/bottom_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:textSize="30sp"
android:text="Bottom TextView" />
<ListView
android:id="#+id/listView_Species"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/top_tv"
android:layout_above="#id/bottom_tv"
/>
</RelativeLayout>
The RelativeLayout tells the layout inflater to draw the first TextView at the top, then draw the second TextView at the bottom, and then fill the rest of the space with your ListView. I believe this is exactly what you want.
Welcome to Android. You'll be using this pattern a LOT!
Change the ListView height to 0dp and add weight=1
i.e.:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="Top TextView" />
<ListView
android:id="#+id/listView_Species"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="Bottom TextView" />
use android:layout_weight to define weights to your widgets inside the outermost layout. Declare their height as 0dp and then define android:layout_weight to each one of them .
Total weigh sum of the three of them should be 1. According to your need you can deine 0.1 weight to both top and bottom TextView's and define 0.8 to ListView.
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight = "0.1"
android:textSize="30sp"
android:text="Top TextView" />
<ListView
android:id="#+id/listView_Species"
android:layout_width="match_parent"
android:layout_weight = "0.8"
android:layout_height="0dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:textSize="30sp"
android:layout_weight = "0.1"
android:text="Bottom TextView" />

Mimicking the Gmail app label listing

I'm trying to build a layout for my ListView items similar to the Gmail app's listing of labels, where it has the label text on the left and the count to the right. What I have mostly works, except with long text. What I have results in the text overlapping the count.
This is what I'm trying to mimic:
As you can see, the bottom label isn't wrapping where the top label is (read below for more details on this).
When both labels have a count, the count lineup on each row:
With what I have there should be a 3 showing for the last item but it's getting overlapped. Also, I'd like the "count" TextView to lineup on each row the same way the Gmail app is (center, right aligned, I guess?):
Layout code:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
android:weightSum="1"
>
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:padding="10dp"
android:gravity="left"
android:layout_weight=".75"
/>
<TextView
android:id="#+id/count"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:gravity="right|center_vertical"
android:padding="10dp"
android:layout_weight=".25"
/>
</LinearLayout>
I know when you're using layout_weight you're supposed to set the layout_width to 0px, however, this results in every row being cutoff at the same spot. I only want the text wrapping if it goes longer than the count TextView.
I am not good with Android layouts, I think they are extremely frustrating to work with, so this may be something easy. Thanks.
You should be able to prevent the views from overlapping by using a RelativeLayout instead of your LinearLayout, using the layout_toRightOf or layout_toLeftOf XML attributes to position the views relative to one another.
Figured it out. I needed to add android:layout_toLeftOf="#+id/count" to the first TextViewwhich Ernir answered above

Collapsing margins in Android layouts

Is it possible to make margins collapse in Android? Let's say I have a LinearLayout and add three TextViews, each with an android:layout_margin of 10dp. I get the following result:
However, I'd like to get this result:
I know that I could workaround this by setting different top/bottom margins for the different items:
set the top margin of the first item and the bottom margin of the last item to 10dp,
set the remainding top/bottom margins to 5dp,
but that makes the design more complicated (especially if the TextViews are dynamically created). Is there some way to make the margins behave like in CSS? (For an explanation of why this makes sense, see: What is the point of CSS collapsing margins?)
What I typically do to fix this myself, is to simply cut the View's (i.e. your TextView) margin in half, and add that same number as padding to the containing ViewGroup (i.e. your LinearLayout). This way you will end up with even spacing around all items. For example:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="5dip"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:text="I'm a TextView!"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:text="I'm a TextView!"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:text="I'm a TextView!"
/>
</LinearLayout>
Posting a solution for someone who might need this in future. Works for static as well as AdapterViews where list items are dynamic.
Example parent container:
<RecyclerView
----
android:padding_top="10dp"
android:padding_start="10dp"
android:padding_end="10dp"
----
>
</RecyclerView>
The padding ensures the spacing from top, left & right of the window.
Only thing remaining now is the vertical gap between two consecutive children & bottom gap after last child.
Example child / item view:
<RelativeLayout
----
android:margin_bottom="10dp"
----
>
<DynamicChild1 />
<DynamicChild2 />
</RelativeLayout>
For this question specifically, the child view will just be a TextView with bottom margin.
This will give you the exact output as expected in the question.

android layout dynamic sizing

For many "header" TextViews across the pages I'm designing for a program, I would like them to be the parent.Width / 2 then properly aligned. While that would be fairly easy to code in the Java, I am attempting to do as much as possible in the XML layouts to avoid XML-Java code intersections until the last little bits (button presses, finish page, etc).
Do I have to go through each page and calculate every item's specific width myself or is there a way to put something along the lines of "fill_parent / 2"?
EDIT: Forgot to mention what is likely a key note - almost everything I am doing is in RelativeLayouts, I have very little use for LinearLayouts in this project.
If you have a LinearLayout that is flush to the left and right, you can do the following:
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:weightSum="2"
android:gravity="left"
android:orientation="horizontal">
<TextView
android:layout_weight="1"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:text="I take up half the width!!!1" />
</LinearLayout>
By setting the weightSum on the parent, you're saying that the weights of the children should equal that amount. By setting the single child's weight to half of that, it'll take up half the space. Make sure to set the width of the child to 0 so it knows to use the weight value to calculate its space relative to its parent.
Then, you can align it however you'd like by setting gravity on the parent LinearLayout.
Use a tableview with two columns where each column is stretched and has a text view. Then hide the second textview
<TableLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:stretchColumns="1">
<TableRow>
<TextView android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=" Set Item Name "/>
<TextView android:id="#+id/hiddenTextView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:visibility="invisible"/>
</TableRow>
</TableLayout>

Categories

Resources