Android Layouts - Combining fills with wraps and gravities - android

I have an oddly organized activity with a number of LinLayouts inside of LinLayouts inside of LinLayouts (inside of LinLayouts) all so that each little section is organized correctly. Everything looks good except for one part.
I have a vertical LinearLayout with two things inside of it. One is another LinearLayout with weight set to 6, and below it is a TextView weight set to 1. What I want to do is have the height of the TextView to scale depending on the amount of lines in it. It could either be a one-liner sentence or maybe a four-line paragraph--I don't know what it'll end up. Then the LinLayout above it needs to fill in the rest of the height.
What layout_height settings do I need to combine to get this to work?

Finally figured it out. It's sort of weird, but this is what I had to do:
<LinearLayout
android:id="#+id/everything_but_description"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal" />
<TextView
android:id="#+id/description"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/paragraph" />
I had to have both set to "wrap_content" but give the one I wanted to fill the remaining space a weight WITHOUT giving the other one a weight. Very weird workaround but it works perfectly.

Related

Border Lines for cells in GridLayout, TableLayout, or GridView?

I am trying to create a table/grid for some items within my app and I would like to have a border around each cell to divide the items up and have a coherent association of the setting with the item. This app will be used in an industrial setting where there may be people unfamiliar with Android that need to use this, thus trying to make it as easy as possible.
The table/grid will contain TextView, EditText, Spinner, and Button, and will also be scrollable (via ScrollView parent).
I read about the GridView and found that it (seems) to only be able to get items programmatically, please correct me if I am wrong. I felt that this was unnecessary since I know what items I want and where. Also, I have not tried adding items to a layout programmatically yet so I figured I would try the other options first. Also, the GridView documentation does not say one way or the other if border lines are automatically shown, or if you can have them shown at all.
I started with a TableLayout and was able to get everything except the border lines to work. I tried android:divider to get the lines but that didn't work. One thought I had was to create a bunch of TextViews with black backgrounds and ~2dp widths/heights to make my own border lines. This feels like a huge waste though. Then I also read the TableLayout documentation and found this: "TableLayout containers do not display border lines for their rows, columns, or cells."
I then tried the GridLayout and had the same results as the TableLayout. I tried padding and margins, neither worked. Also, the GridLayout documentation states: "The grid is composed of a set of infinitely thin lines that separate the viewing area into cells."
My questions are:
Is there an attirbute that I missed in TableLayout or GridLayout that will give me border lines via the xml?
If no, then will the GridView give me the lines I want?
Will I be able to add all the perviously mentioned items I want to the GridView?
I was actually able to achieve the desired look by setting the android:background="#000000" within the GridLayout view and then in the child items I set the android:background="#8CDD81" (just some green color) and combined with android:layout_margin="2dp" I was able to get the "grid" lines that I wanted. Thanks to CommonsWare though for getting me thinking in a new direction that turned into a solution.
EDIT:
This does not work quite as anticipated. You need the android:layout_alignLeft/Right which are only available via RelativeLayout in order to get just the right width on the child items. Haven't tested this yet using this idea, child items within RelativeLayout within GridLayout.
Is there an attirbute that I missed in TableLayout or GridLayout that will give me border lines via the xml?
No.
If no, then will the GridView give me the lines I want?
No.
Will I be able to add all the perviously mentioned items I want to the GridView?
Yes, though how well something like a Spinner will work, I can't say.
The simplest way, off the top of my head, to give you the lines you seek is to have each cell of the TableLayout or GridLayout be some container containing the widget(s) for that cell, where you give the container a background that is your line. A ShapeDrawable could be defined in XML for that background, which will be nicely resizeable based upon the actual requirements of the cell.
For future visiters this is how I did it with TableLayout:
table.xml
<TableLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#969696">
<!-- table heading -->
<TableRow>
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Name"
android:background="#d2d2d2"
android:layout_margin="1dp"
/>
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Address"
android:background="#d2d2d2"
android:layout_margin="1dp"
/>
</TableRow>
<!-- table data -->
<TableRow>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Ahtisham"
android:layout_margin="1dp"
android:background="#f1f1f1"
/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Kashmir"
android:layout_margin="1dp"
android:background="#f1f1f1"
/>
</TableRow>
</TableLayout>

Fixed-width TextView with stretched compound drawable

I'm trying to achieve the following layout: a fixed width TextView aligned to the left of its parent, with the text inside it aligned to the right side of that TextView (that's why fixed width, can it be done other way?) and the rest of the parent is filled with a drawable (simple line). Like this:
It's a ListView containing 2 types of rows and the layout for the rows with lines is quite trivial - LinearLayout with TextView and ImageView (I can post the exact code later if needed). And I'm getting a warning that it could be replaced with a single TextView with compound drawable.
I'm all for optimization so I really tried to follow that advice. Unfortunately I wasn't able to get the same result - the line is either constrained to TextView's width or text is aligned to the right side of the ListItem, now to fixed position.
Am I missing something?
Edit: Apparently it is not actually possible and since there are some other complications (the drawable is now a level-list drawable, which is not always a line and sometimes it has a non-fixed height that I have to set) I will leave it as it is now - linear layout, containing one TextView and one ImageView.
I don't think that you're missing anything. The TextView compound drawable features are not very customizable and in general are not worth the time you spend trying to get them to look right. Some lint warnings are a little overzealous and premature.
The optimization that the lint refers to is something that is better attributed for a fixed size image. In your case, the line has to stretch the rest of the screen length and as such it is not something that can be done with a textview with compound drawable. This kind of lint warning is more of a suggestion rather than something that MUST be done and is detected by just checking for a linear layout with only a textview and an imageview rather than checking what would need to go in the image view. If you already have it working the way you did it I think you should leave it alone.
Your view create from this -
<?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:id="#+id/time"
android:layout_width="#dimen/today_time_width"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:gravity="right"
android:layout_marginRight="5dp" />
<ImageView
android:layout_gravity="center"
android:id="#+id/border"
android:layout_width="match_parent"
android:layout_height="#dimen/today_current"
android:src="?attr/item_boundary" />
</LinearLayout>
There is no way to achive this using only standart TextView. If you really want to reduce view count you can create your custom TextView class, set layoutWidth to matchParent and draw line from text end to right border. But it's not worth to be doing. Some extra views won't slow your list.
I am not sure if you will be able to achieve what you really want to , but then you could change the linear layout in the link you posted to something like this:
<RelativeLayout
android:id="#+id/relTrial"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/txtTime"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:gravity="right"
android:text="12:45 AM"
android:layout_alignParentLeft="true"/>
<LinearLayout
android:id="#+id/lnrSep"
android:layout_width="fill_parent"
android:layout_height="1dp"
android:gravity="bottom"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_centerVertical="true"
android:orientation="horizontal"
android:background="#android:color/darker_gray"
android:layout_toRightOf="#+id/txtTime"
android:layout_alignParentRight="true"></LinearLayout>
</RelativeLayout>
This way the time text will be right aligned although being at the left side, and the line will also be visible.
Hope that helps.
If I got you right, you want to add bottom border to list view item?
What about to try this:
android:drawableBottom="#drawable/line"

Can't Align ImageView in Table Cell in Android

OK, here's ANOTHER question about positioning objects in tables in Android, but nothing I've found on Stack has helped.
I want the ImageView in the XML below to be left aligned in its cell. No matter what I've tried, though, it won't do this (it's always centered). The layout_width and layout_weight are set as they are to control the position and sizes of the cells themselves. Maybe these settings are making it impossible to left align the ImageView in its cell, though.
android:layout_gravity="left" and android:gravity="left" didn't work in either the ImageView tag or the TableRow tag. One kind of kludgy solution that seems to work is to add a blank TextView in a third column, to force the 2nd column holding the ImageView to be exactly the width of the ImageView's bitmap. However, I'd prefer not to have to do this, especially since different rows may contain bitmaps of different widths.
<TableLayout
android:id="#+id/scoreTable"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true" >
<TableRow
android:id="#+id/thisWeek"
android:layout_width="wrap_content"
android:layout_height="fill_parent" >
<TextView
android:id="#+id/thisWeekText"
android:layout_width="0px"
android:layout_height="30dp"
android:layout_weight="35"
android:gravity="right"
android:paddingRight="30px"
android:text="#string/thisWeek"
android:textStyle="bold" />
<ImageView
android:id="#+id/chevron1"
android:layout_width="0px"
android:layout_height="20dp"
android:layout_weight="65"
android:layout_marginLeft="0px"
android:src="#drawable/doser_scale4a"
android:visibility="visible" />
</TableRow>
I replaced the TextViews with ImageViews, using bitmaps of the text that was in the TextViews. This was OK for me because that text won't be changing, though I guess if it did I could create images for all possible text and switch between those images.
This was not an ideal solution, since I assume using bitmaps instead of text uses more memory, and making bitmaps for my text required a little time and effort and some sacrifice of ease and flexibility of changing the text, if that is desired at some point, but I couldn't figure out how to make this work with TextViews. Android definitely seems limited in this way, since it shouldn't be that difficult to align text any way you want in a table cell, should it?
Each "cell" of the TableRow is a View, so you could put a LinearLayout (with your preferred gravity) and put inside this LinearLayour your image.

Android RelativeLayout strange behaviour

I'm learning the relative layout and wrote a little test layout to simulate a login page:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent">
<TextView android:id="#+id/labelUsername"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="username:"
android:layout_centerVertical="true"/>
<EditText android:id="#+id/txtUsername"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:hint="input username here"
android:layout_toRightOf="#id/labelUsername"
android:layout_alignBaseline="#id/labelUsername"/>
<TextView android:id="#+id/labelPassword"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="password:"
android:layout_below="#id/txtUsername"
android:layout_alignParentLeft="true"/>
<EditText android:id="#+id/txtPassword"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:hint="input password here"
android:layout_below="#id/txtUsername"
android:layout_alignLeft="#id/txtUsername"
android:layout_alignBaseline="#id/labelPassword"/>
</RelativeLayout>
What I want is putting the Username Label and Textfield above the Password Label and TextField. But the result is reverted, password are above!
I think the problem is the "android:layout_below" property in labelPassword, if I set it to below labelUsername, it works, however because the textfield is much bigger than label, the both textfields are in this case overlayed. So i try to make the labelPassword below the txtUsername, but it performs strange, I don't understand.
By the way, is there any guideline when I build layout with Relative Layout?
What should I put there at first?
What should I put at last?
thanks!
I think what you are trying to achieve here is trying to get both the username and password fields vertically centered, and the password field below the username field. The error in your layout is that you only tell the username textview and edittext to center vertically, and relative layout centeres the layouts after having arranged them. So your username field is centered, while the password is left on top.
What you should do is tell the parent(RelativeLayout) to vertically center all its child elements.
For that simply remove this attribute from the "username" TextView element :
android:layout_centerVertical="true"
And add this attribute to your RelativeLayout element:
android:gravity="center_vertical" //tells RelativeLayout to vertically center all child elements
In this case i would recommend using a LinearLayout but you can continue using RelativeLayout for now. Hope it helps!
To answer your concrete question, it's because android:layout_centerVertical="true" rule you are applying to labelUsername.
It seems that the relative position doesn't work well, when the elements you are refering to, are centered. And it also doesn't make sense, in this case, because you probably want the whole form centered, not only the username fields and then put the password bellow.
You can put the elements in a containing element (another relative layout, or linear layout, or table layout, etc.) and center that element. That works. Or to center all the contents, you can add android:gravity="center" to the containing layout.
As you go through the different Layouts you will find that while Relative layout feels the most "natural" if you're used to positioning things via CSS, for example (with absolute or relative positions) the situation you're describing here calls for either Linear or Table layout. Table layout is probably your best bet for anything "form" related. Your table elements (columns) should have a layout_span attribute that details how many columns to go across (it's sort of analog to colspan in HTML).
I'm not sure what specifically is going wrong in your RelativeLayout above, and I'm sure that with adequate trial and error you could get it to do roughly what you want, but I strongly advise you to use the right tools for the job.
LinearLayout is also a terrific tool (which you should remember can be nested indefinitely). Give your Layout a weightSum and then each item can have a layout_weight (they should add up to be the sum), while their layout_width should be 0dp (it's not intuitive, but that's how it works). That's also a terrific way to make things sit where they ought to.
Lastly the answer to the correct order in RelativeLayout is that the items are Z ordered from bottom to top, so the later an item appears in the sibling order, the higher its Z order is. Otherwise, their order is irrelevant.

Android EditText won't take up remaining space

In my Android app, I have a tabbed Activity. In one of the tabs I have two TextViews and two EditTexts.
The first EditText is only one line, and that's fine. However, I want the other EditText, android:id="#+id/paste_code", to take up the remaining space, but no matter what I do to it, it will only show one line. I don't want to manually set the number of lines, since the number that would fit on the screen differs based on your device.
Here's the relevant code. It's nested inside all the necessary components for a tabbed Activity.
<ScrollView
android:id="#+id/basicTab"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Paste title"
android:layout_weight="0" />
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="#string/paste_title_hint"
android:id="#+id/paste_title"
android:lines="1"
android:gravity="top|left"
android:layout_weight="0" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Paste text"
android:layout_weight="0" />
<EditText
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:hint="#string/paste_hint"
android:id="#+id/paste_code"
android:gravity="top|left"
android:layout_weight="1" />
</LinearLayout>
</ScrollView>
Since the accepted answer doesn't address the situation fully, here's a proper fix for people coming to this while searching:
Firstly, Romain Guy from the Android dev team addresses this well in this blog post:
http://www.curious-creature.org/2010/08/15/scrollviews-handy-trick/
Essentially, your ScrollView needs to contain the android:fillViewport="true" attribute.
If things aren't working once you've done that, here are a couple of things to check:
The layout inside the ScrollView (such as a LinearLayout) needs to have layout_height="wrap_content"
The view(s) you want to expand should have layout_height="wrap_content"
The view(s) you want to expand should have layout_weight="1.0" or similar
Don't forget to set minLines="3" or similar in the view(s) you want to expand if you don't want it/them to shrink too much.
The problem seems to come from your use of ScrollView. I've tested your code using a ScrollView as the parent container, and got the same problem. However if I replaced the ScrollView with a LinearLayout, then the second EditText properly expanded to fill the whole screen. The problem must be that ScrollViews are designed to wrap to their smallest possible size, regardless of what settings you put in android:layout_height. I experimented with another few layouts, e.g. a RelativeLayout using layout_above and layout_below, but those only affected its maximum size, not its size when empty. Unfortunately, that means I'm not sure how to solve your problem... Is there a way you can redesign your layout to use something other than the ScrollView as the parent container?

Categories

Resources