I'm trying to make a grid-like form, similar to the example on the official Android Developers blog.
Here is my layout:
<?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="match_parent"
android:orientation="vertical">
<GridLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="48dp"
android:layout_marginRight="48dp"
android:layout_marginTop="#dimen/activity_vertical_margin"
android:columnCount="2"
android:rowCount="2">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="0"
android:layout_gravity="end"
android:layout_row="0"
android:text="Send"
android:textColor="?android:attr/textColorPrimary"
android:textSize="24sp" />
<Spinner
android:id="#+id/send_currency"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="1"
android:layout_row="0" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="0"
android:layout_gravity="end"
android:layout_row="1"
android:text="to"
android:textColor="?android:attr/textColorPrimary"
android:textSize="24sp" />
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="1"
android:layout_row="1"
android:hint="username"
android:textColor="?android:attr/textColorPrimary"
android:textSize="24sp" />
</GridLayout>
</LinearLayout>
My left column (static text, right-aligned) is working fine. It aligns the text to the right, and the width is dependent on the widest row.
However, the right column seems to be drawing way outside of the bounds of the GridLayout.
In that picture, the blue box is the bounds of the GridLayout. You can already see the problem in the green bar at the top. The right side is supposed to be stopping at the bounds of the GridLayout (like the left side is), but for some reason it's going way past it.
The blue box in that picture is the bounds of the EditText (it's set to wrap_content). However, the aqua-colored box is the bounds in which it's allowed to expand. When I type lots of characters into the EditText, it goes past the GridLayout's bounds, and even past the edge of the phone screen!
Is this a bug in GridLayout? Or am I missing something?
That is 'normal' behavior of GridLayout.
Fortunately, there is a new version of GridLayout, which was added with API 21. Thanks of that fact, you can make GridLayout accomodates children to its either width or height according as its orientation.
To know details look at documentation, especially at Class Overview -> Excess Space Distribution. You can find there info how to use GridLayout in the way you want.
Tip:
Don't forget that to make use of new GridLayout, you need to add it as support library and in xmls you should use:
<android.support.v7.widget.GridLayout ... >
instead of
<GridLayout ... >
I found this answer to be helpful. Also, paulina_glab's answer of using <android.support.v7.widget.GridLayout instead of just <GridLayout - thanks!
In particular these attributes on each cell:
android:layout_width="0dp"
app:layout_columnSpan="1"
app:layout_columnWeight="1"
app:layout_rowSpan="1"
Hope it helps.
You can restrict edittext to single line.
<EditText
...
android:singleLine="true"
android:lines="1"
android:maxLines="1"
android:hint="to"></EditText>
Definitely odd. What happens if you constrain the width of the EditText to "match_parent" instead of "wrap_content" (which should constrain its horizontal width to within the grid cell)?
i.e.
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_column="1"
android:layout_row="1"
android:hint="username"
android:textColor="?android:attr/textColorPrimary"
android:textSize="24sp" />
or, alternatively, give your EditText a right margin to try and push that right hand border in a little bit? e.g.
android:layout_marginRight="20dp"
and see if that makes a difference?
Related
I want to have a list of input fields with labels to their left for an edit screen. At the bottom there needs to be a set of buttons, which should be aligned centrally.
The labels can have different widths depending on the language, so the EditText views need to span across the remaining space. I am using a grid layout, because I need to have all EditText views aligned to a vertical line at their left.
I have spent half a day now to solve this, but I fail to make progress. The closest I could get to is this:
<?xml version="1.0" encoding="utf-8"?>
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_column="0"
android:layout_row="0"
android:text="Label 1234545"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tvHeightLabel"/>
<EditText
android:layout_column="1"
android:layout_row="0"
android:text="Some text which is too long that it could fit in one single row"
android:layout_gravity="fill_horizontal"
android:inputType="numberDecimal"
android:ellipsize="end"
android:id="#+id/etHeight"
android:layout_width="259dp"/>
<TextView
android:layout_column="0"
android:layout_row="1"
android:text="Label 2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tvHeightLabel2"/>
<EditText
android:layout_column="1"
android:layout_row="1"
android:text="Some text which is too long that it could fit in one single row"
android:layout_gravity="fill_horizontal"
android:inputType="numberDecimal"
android:ellipsize="end"
android:id="#+id/etHeight2"
android:layout_width="259dp"/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_row="3"
android:layout_column="0"
android:layout_columnSpan="2">
<Button
style="?android:attr/buttonBarButtonStyle"
android:text="Button 1"
android:layout_height="wrap_content"
android:id="#+id/btCancel"
android:layout_weight="1"
android:layout_width="wrap_content"/>
<Button
style="?android:attr/buttonBarButtonStyle"
android:text="Button 2"
android:layout_height="wrap_content"
android:id="#+id/btSave"
android:layout_weight="1"
android:layout_width="wrap_content"/>
</LinearLayout>
</GridLayout>
This layout looks like this:
It seems to work first, but when the labels exceed a certain size, the EditText view elements grow out of the screen to the right:
I don't even get why the above solution works for labels, which just grow slightly. The width of the EditText elements is set to 259dp, which was set by Android Studio automatically. (I tried to arrange the EditText views by sizing it with the mouse on the preview on the design screen. Android Studio arranged it automatically at a certain point as given above.)
There must be some property to let a view eat up what is left independent of its content. The text could scroll, I'm ok with that. I feel like I have not understood the layout concept at all.
Use padding to restrict the flow of the text.
<TextView
android:layout_marginLeft="12dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Text"
android:id="#+id/tvVExample"
android:textColor="#496933"
android:singleLine="false"
android:textStyle="bold"
android:textSize="16sp"/>
For example, the text is:
Having desirable or positive qualities especially those suitable for a thing specified
And it shows me:
Having desirable or positive qualities especially those suita
specified
It can wrap. And It shows two lines but some words is hidden
What I expected is:
Having desirable or positive qualities especially those
suitable for a thing specified
Finally I find the solution, if the TextView which is the child of GridLayout. I can't set the width to WRAP_CONTECT becacuse it will use the whole row as the width but not the width of the cell. The solution is that set the width to 0dp and set the layout_gravity to fill_horizontal. Also, the width of the gridlayout must be MATCH_PARENT.
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:columnCount="3"
android:orientation="horizontal">
.
.
.
<TextView
android:layout_marginLeft="12dp"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="fill_horizontal"
android:text="New Text"
android:id="#+id/tvVExample"
android:textColor="#496933"
android:textStyle="bold"
android:textSize="16sp"/>
.
.
.
</GridLayout>
It seems in many cases the trick was not to setup single="false" but maxLines="100", maybe you can have a try:
<TextView
android:layout_marginLeft="12dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Text"
android:id="#+id/tvVExample"
android:textColor="#496933"
android:maxLines="100"
android:textStyle="bold"
android:textSize="16sp"/>
If you are using a LinearLayout and above is not working, you can maybe try adding android:layout_weight="1" (but layout_width will have to be set to match_parent).
I need a View to hold a number of TextViews, and the exact number I will not know unfortunately. I need the TextViews to sort of stack either under each other or right next to each other (imagine Tetris, but with just rectangles or squares). The way I have tried thinking about it is using LinearLayout to hold them either horizontally or vertically. I then use their weights to stretch them appropriately if they are next to each other. Otherwise, I use a vertical orientation. Problem is the performance with nested LinearLayouts with more complicated stacks. I thought about using RelativeLayout, but that wouldn't work because I need the TextViews to not overlap. So like if they are next to each other, they need to each take enough space evenly. With layout_weight it works great. I was hoping someone had any idea on how to make this work right/alternative.
Heres an example that is giving me a warning (only a simple example of what I am doing programmatically):
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_weight="1">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Hello World 1"
android:background="#000000"
android:layout_weight="1"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Hello World 3"
android:background="#000000"
android:layout_weight="1"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Hello World 4"
android:background="#000000"
android:layout_weight="1"/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_weight="1">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Hello World 2"
android:background="#000000" />
</LinearLayout>
I've tried it with RelativeLayout by the way, but one of the TextView's needs to be a set size, but I need them to take space evenly. I won't know specific sizes. Measuring the screen width and dividing it that way is also both clunky and not precise. I appreciate anybodies input.
Edit: So I've been thinking about it some more and thought of a solution using RelativeLayout. There is a nice example in the Android docs, but the only problem is one of the Views needs to be a set size so the other one could stretch. But if there is a way to allow all of them not to have a set size, that could work too, so then they can stretch. Anyone tried doing that at some point?
It's a bit unclear what your final use case looks like, so I don't know if this will completely solve your problem, but you might take a look at TableLayout (docs link). It's based on LinearLayout so items can still be defined to evenly occupy a given space, but it allows you to define your positions and spans in terms of rows and columns.
So, for instance, your example code would look like:
<TableLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:stretchColumns="*" >
<!-- Wrap all items in a given row in a TableRow -->
<TableRow>
<TextView
android:text="Hello World 1"
android:background="#000000"/>
<TextView
android:text="Hello World 3"
android:background="#000000"/>
<TextView
android:text="Hello World 4"
android:background="#000000"/>
</TableRow>
<!-- If a child occupies an entire row, it can be by itself -->
<TextView
android:text="Hello World 2"
android:background="#000000"/>
</TableLayout>
You can also use the android:layout_column and android:layout_span attributes to define exactly which column an item should be in, and how many columns it should occupy. Also note that TableLayout and TableRow have basically ignore any layout params applied and use very specific (documented) parameters, so adding them to your code will only confuse what is actually going on. Of course, this can all be built programmatically as well as in XML.
If this does not provide the flexibility you need, I would then recommend creating your own custom layout that either extends or is based on LinearLayout. The mechanism is uses to measure children with weight is not that complex, and then you can override how each child is placed after measurement. Here is a source link to LinearLayout if you want to see how the platform does these things.
Update: As we know the percent support library is deprecated from API level 26. ConstraintLayout is the new way to achieve the same flat xml structure.
Updated Github Project
Updated Samples:
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/fifty_thirty"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#ffff8800"
android:gravity="center"
android:text="#string/fifty_fifty_text"
android:textColor="#android:color/white"
app:layout_constraintHeight_default="percent"
app:layout_constraintHeight_percent="0.5"
android:textSize="25sp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_default="percent"
app:layout_constraintWidth_percent="0.5" />
<TextView
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#ffff5566"
android:gravity="center"
android:text="#string/fifty_fifty_text"
android:textColor="#android:color/white"
android:textSize="25sp"
app:layout_constraintHeight_default="percent"
app:layout_constraintHeight_percent="0.5"
app:layout_constraintLeft_toRightOf="#id/fifty_thirty"
app:layout_constraintTop_toBottomOf="#id/fifty_thirty"
app:layout_constraintWidth_default="percent"
app:layout_constraintWidth_percent="0.5" />
</android.support.constraint.ConstraintLayout>
Deprecated
update: We can use android support library for the same.
compile 'com.android.support:percent:23.0.0'
Consider this demo for dividing the screen into 50-50 percent.
<android.support.percent.PercentRelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/fifty_huntv"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#ff7acfff"
android:text="20% - 50%"
android:textColor="#android:color/white"
app:layout_heightPercent="20%"
app:layout_widthPercent="50%" />
<TextView
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_toRightOf="#id/fifty_huntv"
android:background="#ffff5566"
android:text="80%-50%"
app:layout_heightPercent="80%"
app:layout_widthPercent="50%"
/>
</android.support.percent.PercentRelativeLayout>
Output:
Demo HERE!!!
GitHub Project HERE!!!
I have a linear layout with several buttons in it. The button images are all the same size and have the same attributes... except for one button. This one button has a smaller font size. All the buttons except for this one are in a perfect line exactly the way I want. For some reason, the button with the smaller font appears a little lower on the screen than the other buttons. I'm having a hard time wrapping my head around the idea of a button that requires less space taking up additional space.
Might someone give me a hint on what to read up on?
EDIT
Here's main.xml (seems like SO filters some of it, all the important stuff is here...)
<ScrollView android:id="#+id/scroll"
android:layout_width="match_parent"
android:layout_height="300px">
<TextView
android:id="#+id/the_text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:typeface="monospace"
android:textSize="9pt"
android:background="#color/paper"
android:paddingLeft="20dp"
android:paddingBottom="20dp"
android:textColor="#color/type"
/>
</ScrollView>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button style="#style/ASR33_button"
android:tag="Y"
android:text="Y"
/>
<Button style="#style/ASR33_button"
android:tag="N"
android:text="N"
/>
<Button style="#style/ASR33_button"
android:tag="E"
android:text="E"
/>
<Button style="#style/ASR33_button"
android:tag="W"
android:text="W"
/>
<Button style="#style/ASR33_button"
android:tag="S"
android:text="S"
/>
<Button style="#style/ASR33_button"
android:tag="F"
android:text="F"
/>
<Button style="#style/ASR33_button"
android:tag="R"
android:text="R"
/>
<Button style="#style/ASR33_button"
android:tag="M"
android:text="M"
/>
<Button style="#style/ASR33_button"
android:tag="T"
android:text="T"
/>
<Button style="#style/ASR33_button"
android:onClick="onEnterButtonClicked"
android:textSize="6pt"
android:text="RE-\nTURN"
/>
<Button style="#style/ASR33_button"
android:tag="U"
android:text="U"
/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/instructions"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="9pt"
android:paddingLeft="10dp"
android:typeface="normal"
android:text="Commands: (Y)es, (N)o, (N)orth, (E)ast, (W)est, (S)outh, (M)ap, (ST)atus, (Fight), (R)un, (SU)icide. All commands must be followed by RETURN."
/>
</LinearLayout>
The one that's wonky is the 2nd from the bottom, with the different onclick event. The style has 11pt for the character size. If I use it (and a 1 letter button name, like the others) it behaves. But that's not what the ASR33 'enter' key has on it. So if I reduce the font size to say 6 pt, the weirdness happens.
The style can be seen here.
Again, just reading references or ideas please, I can figure it out if I have a word or two to search on. It's hard to know what you don't know...
RESOLUTION
Anurag has it right, see his answer below. Here's an excerpt of the updated LinearLayout:
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="false">
maybe the re sizing has happened due to the wrap_content property of your button. so what you should do is have a fixed height to the linear layout holding all the buttons while its with is set to fill parents.
and inside the linear layout let individual buttons have height set to wrap content which will give all the buttons the same height as that of the linear layout and also set the attribute android:adjustViewBounds="true" for the small button. this attribute will resize your image button to maintain the aspect ratio. i hope this helps.
EDIT:
So here is the solution to your problem, something that was caused due to the base alignment property of the linear layout. A horizontal LinearLayout aligns the baselines of all its child controls by default. So the first line of text in your multi-line button is vertically aligned with the single line of text in the other buttons. set android:baselineAligned="false" on the LinearLayout. This worked perfectly on my HTC.
I have an EditText and a Button in my LinearLayout and I want to align them closely together so they see seem to belong together (edittext + micButton for speech input).
Now they don't have the same height and they aren't really aligned well (Button seems to be a little lower than the EditText). I know I can apply a negative margin like -5dp to make them come closer together, but is there perhaps a better way to do this?
Set them in a specific container/layout so that they will automatically have the same height and no margin between them?
Using relative layout you can stretch a view depending upon another views size without knowing the exact size of the other view.
Here is the code :
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<Button
android:layout_width="100dp"
android:layout_height="100dp"
android:text="button"
android:id="#+id/but"/>
<EditText
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/but"
android:layout_alignBottom="#id/but"
android:layout_alignTop="#id/but"
/>
</RelativeLayout>
Check this link for reducing space between views :
https://groups.google.com/forum/?fromgroups#!topic/android-developers/RNfAxbqbTIk
Hmm, don't know why people bother so much with tables. Since the both Views are within a LinearLayout (presumable orientation=Horizontal), this command should center both within the layout:
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical" />
</LinearLayout>
Note: Since EditTexts and Buttons may orient their text slightly differently, you may have to do some tweaking (by changing margins or padding) to get the text to align properly.
I hope this solution might help for your scenario...Here is the code..
<RelativeLayout
android:id="#+id/rlLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:orientation="horizontal"
android:padding="3dp" >
<EditText
android:id="#+id/etId"
android:layout_width="fill_parent"
android:layout_height="50dip"
android:background="#c8c8c8"
android:hint="Edittext"
android:paddingLeft="20dip"
android:paddingRight="10dip"
android:textColor="#000000" />
<RelativeLayout
android:id="#+id/rlLayoutid"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignRight="#+id/etId" >
<Button
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignParentRight="true"
android:layout_marginRight="14dp"
android:layout_marginTop="10dp"
android:background="#drawable/calender" />
</RelativeLayout>
</RelativeLayout>
# Daniel Here You can use layout weight and weight sum
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:weight_sum=2
>
<Button
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight=1
android:text="button"
android:id="#+id/but"/>
<EditText
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight=1
/>
</LinearLayout>
Android tries to automatically level everything off of the text and not the buttons themselves.
Took me forever to finally figure it out. Its really simple. Should fix it.
myButton.setGravity(Gravity.CENTER_VERTICAL);
or if they are in a row.. attach the buttons to a table row, then.
myTableRow.setGravity(Gravity.CENTER_VERTICAL);