Android Linear Layout gives me headache - android

I've got the following xml file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/linearLayout1"
android:background="#android:color/transparent"
android:layout_marginTop="0px"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:weightSum="1"
android:orientation="horizontal">
<Button android:id="#+id/info" android:text="Info" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom"></Button>
<Button android:id="#+id/town" android:text="Town" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom"></Button>
<Button android:id="#+id/unit" android:text="Unit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom"></Button>
<Button android:layout_height="wrap_content" android:text="EndTurn" android:id="#+id/endturn" android:layout_width="wrap_content" android:layout_gravity="bottom"></Button>
</LinearLayout>
which provides the following result: http://i42.tinypic.com/otdkb4.png
Now I've got some questions about this:
The top and bottom padding, how to get rid of it?
I tried RelativeLayout, multiple layouts within each other, padding, margin, changing height nothing seem to affect it in any way.
Is there a way to get the layout transparent? android:background seems to be the wrong one.
Between the third and the fifth button is a bit more space (where the fourth button should be). I catch it the in the program and set it to invisible.
unitButton.setVisibility(INVISIBLE);
unitButton.setWidth(0);
Now the space between the two buttons is more than double of the normal range (between 1 and 2) Any idea on this? - Altough this is a minor problem
Thanks in advance.

1: Is the layout presented in a Dialog? If so, that'll give you some headaches. To get more control you should either create your own custom Dialog extension (as some dialog layout values are hardcoded), or display your layout in another way (a new activity on top, or using a framelayout perhaps)?
2: To get a layout transparent, simply don't give it a background-attribute. (Though, if you really are using a dialog, the dialog box is not transparent, and it is that which you see. You can also set it to be transparent by setting background to "#00000000" (which is what you do).
3: A View with visibility as "invisible" is still measured, that means both its width/height as well as its margins and padding is displayed as empty space in your layout. Setting the visibility to "gone" instead will not measure it, and you won't need the setWidth(0) either. (You can still display it later by setting it back to "visible")
Edit: removing the unused "weightSum" attribute might also be a good idea, as the view is now expecting its children to have a total weight of something other than 0.

Related

Android ListView width keeps changing

Firstly, I am new to android so if I have missed something basic I apologise.
I have a page which has two ListViews side by side, both with varying amounts of content. I also have a TextView above the ListViews and another TextView below the listviews. These text view boxes change based on items selected in either of the two ListViews.
These two ListViews sit side by side, taking up half of the screen each, while a Textview sits directly above and directly below, both centred to the page. An image is shown below.
This is the page looking normal on load.
The problem is when I select an item from either list. I have a feeling I am missing some XML properties, but I am not sure which properties or if this is even the case. When an item is selected, let's say from the ListView on the right, the TextView at the bottom is updated with text taken from an array. The ListView also decides to change the width and I am not sure why this is.... I don't want the ListView to change width. I want it to remain taking up half of the page and half of the page only.
This is the page after an item from the right ListView has been selected.
I would also like to keep things in RelativeLayout. I also believe it is only an XML issue and not to do with the adapter or any other code so I will not include that for now. I can include it if required.
Any help would be great. Thanks in advance.
content_titles.xml my activity xml file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".TitlesActivity">
<ListView
android:id="#+id/unlocked_titles_list"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:longClickable="true"
android:layout_below="#+id/current_title"
android:layout_alignEnd="#+id/requirements"
android:layout_marginEnd="26dp"
android:layout_above="#+id/requirements">
</ListView>
<TextView
android:id="#+id/current_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="65dp"
android:text="Current Title: Novice"
android:textSize="24sp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"/>
<ListView
android:id="#+id/locked_titles_list"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignStart="#+id/requirements"
android:layout_marginStart="28dp"
android:layout_above="#+id/requirements"
android:layout_below="#+id/current_title"/>
<TextView
android:id="#+id/requirements"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="34dp"
android:text="temp"
android:textAlignment="center"
android:textSize="24sp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"/>
</RelativeLayout>
activity_listview.xml used as the individual rows of the ListViews
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/label"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dip"
android:textSize="16dip"
android:textStyle="bold" >
</TextView>
The problems with layout could be caused by ScrollView to be the wrapper
I stumbled upon some note in http://developer.android.com/reference/android/widget/ExpandableListView.html
"...Note: You cannot use the value wrap_content for the android:layout_height attribute of a ExpandableListView in XML if the parent's size is also not strictly specified (for example, if the parent were ScrollView you could not specify wrap_content since it also can be any length. However, you can use wrap_content if the ExpandableListView parent has a specific size, such as 100 pixels."
I removed wrapping ScrollView and linear layout started working properly. Now its only to understand how to wrap the stuff to ScrollView. God help me
But anyway this is really weird behavior. I think that fill_parent is not really correct wording. When using heirarchyviewer tool I always see WRAP_CONTENT and MATCH_PARENT values for layout_width and leayout_height. So probably fill_parent is actually means match_parent which puts me in cognitive dissonance.
You have your layout_width properties set to wrap_content. This means that they could change as the data changes. I would recommend putting your ListViews in a LinearLayout with orientation:horizontal and set the amount of space that each element takes up with layout_weight. Here is a relevant SO question What does android:layout_weight mean?

fill_parent in LinearLayout isn't being honored

After much research on both SO and google, I haven't seen any one with exactly the same problem I am experiencing, so here it is:
I recently redid the entire UI on an android app. For the most part, I made only cosmetic changes to each of the screens. They appear in the UI editor of eclipse perfectly as expected. However, directly after doing this, two of the screens stopped being laid out correctly on both all tested devices and the emulator.
Now, the big problem one these two screens was that the root level LinearLayout didn't appear to be actually honoring the fill_parent for either layout_height or layout_width. it looks like it's being measured as if it were set to wrap_content instead. It only takes up about 70% of the screen - which is just enough to wrap the individual elements inside the root LinearLayout. I would post an image, but as a new user, I am not allowed to.
The layout isn't stretching to fill the screen. Here's the code for layout, except that there are a few more in the LinearLayouts containing a TextView and an EditText.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#FF000000"
android:orientation="vertical" >
<TextView
style="#style/sans.white.16.bold"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingTop="4dp"
android:text="#string/edit_account" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<com.teamunify.ondeck.widget.TUTextView
style="#style/sans.white.14"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="#string/first_name" />
<com.teamunify.ondeck.widget.TUEditText
android:id="#+id/acc_editor_first"
android:layout_width="fill_parent"
android:layout_height="40dp"
android:selectAllOnFocus="true"
android:singleLine="true" />
</LinearLayout>
I think the root LinearLayout should be filling both height and width. I've used this same layout many MANY times in our app without problems. (A quick count revealed that I used 76 LinearLayouts in our app, and all but two of them are working.)
At first, I suspected that perhaps our custom classes measure was wrecking things, so I changed the layout to use all plain EditTexts, but there was no change. I double checked the activity, but it isn't doing anything except to load this xml. So, in desperation, I redid the layout like so:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#FF000000"
android:orientation="vertical" >
<TextView
style="#style/sans.white.16.bold"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center|top"
android:paddingTop="4dp"
android:text="#string/edit_account" />
</LinearLayout>
After that, The words Edit Account appear with a black background mashed into the upper left corner. Clearly, the LinearLayout isn't filling the parent.
Long story short, I am asking how to fix this so that the LinearLayout fills the screen as expected.
I am at a complete loss as to why this is happening, and I am certainly hoping that someone on SO has an idea. This has got me pulling my hair out!
Try setting fixed width and height for the root layout.
Then only you will be able to debug who is driving length and width. It is very much possible that parent activity or background activity is setting dimensions. Once you identify the root cause you can go back to original settings.
As of now from your code snippet given here, nothing wrong here
If you use a custom activity as a container to other activities for some reason (In our case, we were recreating the look of our iOS app, and needed a custom menu to show up along the button side of the screen) the window manager seems to get a bit confused with what the actual height and width of the nested activities should be. A call to fillparent or matchparent ends up wrapping the content instead.
We ended up changing the behavior of several methods in our container activity class to make this work.

Android horizontal LinearLayout with wrapped text in TextView

I've observed a behavior with layout_weight that I can't explain. The following is a trivial example:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="This is a very very very very very very very very very very very very very very very long string."
android:layout_weight="1"
/>
<View
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="center_vertical"
android:background="#ffffffff"
/>
</LinearLayout>
In a QVGA display, the TextView wraps the text. The white square is displayed to the right of the text.
However, if I remove android:layout_weight="1" from the TextView, the TextView now takes up the entire display width. The white square is no longer displayed.
Why would layout_weight in the TextView affect whether or not the white square is displayed? Shouldn't the View with the white background always be assigned 32dpx32dp first? (It makes no difference if the view were any other types - ImageView or TextView).
The problem I was working on is that I want the white square to always be displayed to the right of the TextView (whether or not the text is wrapped), but I don't want any empty space between the TextView and the white square. (If I add android:layout_weight="1" to the TextView, then there is a gap if the text is not wrapped.)
Any help would be appreciated!
To answer my question #1: One thing I learned by looking at the source for LinearLayout: Not only does layout_weight assign unused space to a child, it also shrinks a child with layout_weight if the child extends beyond the bounds of the LinearLayout. That explains why a TextView with wrapped text is shrunk in my layout.
As for the answer to my question #2, I think you meant android:toRigthOf instead of android:layout_alignRight. Using a RelativeLayout instead of a LinearLayout doesn't change the layout behavior. The tricky part is placing a view immediately to the right of a TextView, without gaps, whether or not the text is wrapped. Setting a maxWidth would limit the TextView's width, but that solution doesn't scale across portrait/landscape and different display dimensions.
Solution - Looks like Dyarish's solution is the best available. My layout problem exists regardless of the layout you use. The key is to set a maxWidth for the TextView so that it doesn't take up the all of the horizontal space in the layout. Because hardcoding a android:maxWidth value in the TextView doesn't scale across different displays, setting the maxWidth at runtime, as Dyarish suggested, is a good solution.
Hopefully this is what you are looking for.
First off, here is a great resource I found for Creating UI's.
layout_weight - Specifies how much of the extra space in the layout to be allocated to the View.
If you want to ensure that the white square is always to the right of the textview, you can use a Relative View, and add the parameter to the view. android:layout_alignRight="+id#yourTextViewID". This should always make the box appear right beside the textView area. You should probably also add something like android:maxWidth="250px" This will ensure that you don't push the white box completely out of the screen.
Here is a code sample:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView
android:layout_width="wrap_content"
android:maxWidth="250px"
android:id="#+id/TextForWhiteBox"
android:layout_height="wrap_content"
android:layout_gravity="center|left"
android:text="This is a very very very very very very very very very very very very very very very long string."
/>
<View android:background="#ffffffff" android:layout_width="32dp" android:layout_height="32dp" android:id="#+id/view1" android:layout_toRightOf="#+id/TextForWhiteBox"></View>
</RelativeLayout>
You could also add to the View:
android:layout_alignTop="#+id/TextForWhiteBox" android:layout_alignBottom="#+id/TextForWhiteBox"
to make the white box the same size as the TextView.
Firstly I've tested the code from my other answer and it does exactly what you've described you've wanted. (unless I'm misunderstanding what you are asking for). You definitely do not want to use the android:layout_alignRight which is not what is in the code sample. That would simply keep the box on the right hand of the screen and not be affected by the textview at all. This sample uses android:layout_toRightOf="#+id/TextForWhiteBox" which is possible due to it being a relative layout. Since the Relative Layout allows you to place objects in relation to others. That line will always place the box just to the right of the textview with no gaps.
As for the screen orientation changes:
When the orientation changes it creates a new instance of the view.
Here is a simple solution.
//Add to oncreate in your Activity
private TextView textStatus;
textStatus = (TextView) findViewById(R.id.TextForWhiteBox);
// This get's the width of your display.
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int width = displaymetrics.widthPixels;
// Now you know the screen orientation, and it's width. So just set the maxwidth of the text view to match the display width - the pixels of your white box.
textStatus.setMaxWidth(width - 32); // 32 is here because you already know the size of the white box. More logic is needed to dynamically get this value, because you would need to wait for the activity to be fully created.
}
Here is the main.xml I used:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView
android:layout_width="wrap_content"
android:id="#+id/TextForWhiteBox"
android:layout_height="wrap_content"
android:layout_gravity="center|left"
android:text="This is a very very very very very very very very very very very very very very very very very very very long string."
/>
<View android:background="#ffffffff" android:layout_width="32px" android:layout_height="32px" android:id="#+id/view1" android:layout_toRightOf="#+id/TextForWhiteBox"></View>
</RelativeLayout>
You might need some additional logic to keep screen values.
This code has been tested, you should be able to literally copy and paste this to work as you asked.
Also depending on your logic you could use something like this to return the screen orientation.
int orient = getResources().getConfiguration().orientation;
Hope this helps!
If this helped you, please click the accepted button. =) Cheers!

android:layout_gravity effect in main.xml?

I have 4 buttons in a horizontal linear layout. I'd like the right edge of the 4th button to align with the right edge of the linear layout (equal to screen width) I've tried using android:layout_gravity="right" but it doesn't work - the right button is to the right of the 3rd one but not right aligned . Am I missing something obvious?
main.xml with only the relevant layout params only is:
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<Button
android:layout_height="fill_parent"
android:layout_width="wrap_content">
<Button SAME LAYOUT AS BUTTON 1>
<Button SAME LAYOUT AS BUTTON 1>
<Button
android:layout_height="fill_parent"
android:layout_width="wrap_content"
android:layout_gravity="right" />
</LinearLayout>
</LinearLayout>
This doesn't seem to match the stated behaviour for layout_gravity in the SDK reference :"Defines how to place the view, both its x- and y-axis, within its parent view group."
I know this isn't really the proper answer to your question, but you should really consider using RelativeLayout instead of LinearLayout. It scales better to different phone screen resolutions, and you can place the buttons in the correct order by using the layout_toRightOf and layout_alignParentRight attributes in your XML (or layout_above, layout_alignParentTop, etc.). Using gravity in a linear layout won't really behave as you expect because Android is still attempting to place the widgets in a fixed position.
RelativeLayout is a bit more of a pain to get working than LinearLayout, but it's worth the trouble and is also the one which Google recommends using. Once you get the hang of it, they are very convenient to work with.

How to create layout like this?

I have a horizontal LinearLayout, inside which I have 2 TextViews. Let's say that the LinearLayout's width is 320px. If the TextViews don't fit into the LinearLayout (they are together wider than 320px), I want to somehow achieve this:
The second TextView is fully displayed and is at the right edge of the LinearLayout
The first TextView is only shown partially, only first x characters are visible
What I mean:
[TextView1|TextView2_________________________] // this is normal
[VeryVeryL...|VeryVeryLongTextView2] // VeryVeryLongTextView1 is not fully visible
To get the effect you're requesting in the comments above, you could modify Mayra's solution to something like:
<LinearLayout ...>
<TextView android:layout_width="wrap_content"
android:maxWidth="20dp"
android:layout_height="wrap_content"/>
<TextView android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
I think that will work. Weirdly, the maxWidth param is only present on a couple view classes, but TextView luckily is one of them. You'd think it'd be useful in more cases, so I'm not sure why it's not just available in the default view params.
Specify a specific width for your first textView (i.e, 20dp... note, it is better to use dp than hard coded pixels, to deal with multiple resolutions of devices), give your 2nd TextView a weight of 1. This tells it to take up the remaining space. For example:
<LinearLayout ...>
<TextView android:layout_width="20dp"
android:layout_height="wrap_content"/>
<TextView android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
</LinearLayout>

Categories

Resources