I have created a set of vertical tabs using buttons to represent the tabs and I have set the height of the buttons to wrap content.
This doesnt seem to be respected though as the buttons scale to take up all available space, there are only 5 buttons in the vertical linear layout yet they all stretch to take up the available space. The icon in the button is small and so is the text so this doesnt look very good.
How do I get the buttons to truly only wrap their content? I would like them all the same size and to not fill all available space.
Is setting the height explicitly in dp a good or bad idea?
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.app.FragmentTabHost
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/light_grey">
<LinearLayout android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginLeft="8dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_marginRight="8dp">
<FrameLayout android:layout_width="0dip"
android:layout_height="fill_parent"
android:layout_weight="3">
<TabWidget android:id="#android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:visibility="gone"/>
<LinearLayout
android:id="#+id/tab_btn_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="1.0"
android:background="#color/lightest_grey"
android:id="#+id/patient_tab_btn"
android:text="Patient"
android:textSize="7sp"
android:gravity="bottom|center"
android:drawableTop="#drawable/user"
android:paddingTop="4dp"
/>
<Button
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="1.0"
android:background="#color/lightest_grey"
android:id="#+id/relations_tab_btn"
android:text="Relations"
android:layout_marginTop="1dp"
android:textSize="7sp"
android:gravity="bottom|center"
android:drawableTop="#drawable/family"
android:paddingTop="4dp"
/>
<Button
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="1.0"
android:background="#color/lightest_grey"
android:id="#+id/providers_tab_btn"
android:text="Providers"
android:layout_marginTop="1dp"
android:textSize="7sp"
android:gravity="bottom|center"
android:drawableTop="#drawable/doctors_bag"
android:paddingTop="4dp"
/>
<Button
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="1.0"
android:background="#color/lightest_grey"
android:id="#+id/locations_tab_btn"
android:text="Locations"
android:layout_marginTop="1dp"
android:textSize="7sp"
android:gravity="bottom|center"
android:drawableTop="#drawable/map_marker"
android:paddingTop="4dp"
/>
<Button
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="1.0"
android:background="#color/lightest_grey"
android:id="#+id/summary_tab_btn"
android:text="Summary"
android:layout_marginTop="1dp"
android:textSize="7sp"
android:gravity="bottom|center"
android:drawableTop="#drawable/treatment_plan"
android:paddingTop="4dp"
/>
<Button
android:layout_height="|"
android:layout_width="match_parent"
android:layout_weight="1.0"
android:background="#color/lightest_grey"
android:id="#+id/cpis_tab_btn"
android:text="Protection"
android:layout_marginTop="1dp"
android:textSize="7sp"
android:gravity="bottom|center"
android:drawableTop="#drawable/students"
android:paddingTop="4dp"
/>
</LinearLayout>
</FrameLayout>
<FrameLayout android:id="#android:id/tabcontent"
android:layout_width="0dip"
android:layout_height="fill_parent"
android:layout_weight="17"
android:background="#color/white"/>
</LinearLayout>
</android.support.v4.app.FragmentTabHost>
Thanks
Setting height in dp will not keep perfect proportions through different screens.
For me, the easiest way is to create my interface by code so i can make any calculations i need and set the exact sizes on px.
Take a look at my post asking for opinions.
As for fixing your xml, set your LinearLayout height to wrap_content or remove the weights, it is making the buttons to distribute parent height equally.
Hope this helps.
The layout_weight parameter of the buttons is what is causing your problem. If this parameter is set, the height parameter is ignored. Setting a weight results in all the remaining space being allocated to all children with weights in the ratio of their weights. In your layout, you have 6 buttons. Hence, the remaining space is filled by the 6 buttons with equal height set for all. You can either limit the height of the linear layout parent, or remove the weights of the buttons.
Edit: I have mentioned that if weight is set, height is ignored. This is true only if the orientation of the LinearLayout is vertical. In case it is horizontal, the width attribute is ignored.
Related
I seem to be having issues understanding weightSum and LayoutWidth. My code is below:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="3">
<LinearLayout
android:background="#cccccc"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:padding="20sp"
android:textSize="30sp"
android:gravity="center_horizontal"
android:text="Cheapest Fare Option"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
<LinearLayout
android:background="#666666"
android:layout_weight="2"
android:layout_width="match_parent"
android:layout_height="match_parent">
</LinearLayout>
</LinearLayout>
My understanding of this is the 1st layout will take up 1/3 of the space and 2nd layout will take 2/3 of the space, but the reverse is happening, i.e. 1st layout is taking 2/3 and 2nd layout is taking 1/3
Why is this happening? Trying hard to understand this.
Taking your android:orientation="vertical", you want to get this ratio vertically therefore your android:layout_height attribute should be 0dp for both the child LinearLayout.
Set -
android:layout_height="0dp"
for both the inner LinearLayout.
Alternatively if you want to obtain the ratio horizontally then use android:orientation="horizontal" set -
android:layout_width="0dp"
for both the inner LinearLayout.
The thing is when you want to achieve ratio then you don't set that particular dimension (width or height) to match parent. Rather set it to 0dp so that Android can handle it for you automatically.
<LinearLayout
android:background="#cccccc"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="0dp">
<TextView
android:padding="20sp"
android:textSize="30sp"
android:gravity="center_horizontal"
android:text="Cheapest Fare Option"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
<LinearLayout
android:background="#666666"
android:layout_weight="2"
android:layout_width="match_parent"
android:layout_height="0dp">
</LinearLayout>
I am trying to understand the weight layout with this example.
It is definitely not a rocket science. However, this example making it...
The weightSum dictate how big the size is and
Then divide the layout based on layout_weight value for the view in LinearLayout.
In this example I have a layout, weighted with 5, that is then divided between two views:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#color/transactionRowBackground"
android:paddingBottom="5dp"
android:paddingTop="5dp" android:orientation="horizontal" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" android:layout_weight="2" >
<TextView
android:id="#+id/title"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true"
android:gravity="top"
android:padding="5dp"
android:text="Test Title"
android:textColor="#color/textColor"
android:textSize="#dimen/subHeadingTextSize"
android:textStyle="bold" />
<TextView
android:id="#+id/description"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true"
android:gravity="top"
android:padding="5dp"
android:text="This is a test description"
android:textColor="#color/textColor"
android:textSize="#dimen/normalTextSize" />
</LinearLayout>
<ImageView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="3"
android:src="#drawable/ic_launcher"
android:layout_gravity="top"
android:contentDescription="" />
</LinearLayout>
The thing that I cannot understand is the bigger number I give to ImageViewer the smallest space it get from the parent. So how it is actually calculating the size for ImageView.
You can try with the above xml. If you change the layout weight of an ImageView to 1 , and child linearlayout to 4, that I believe makes more sense, then the opposite will occur.
ImageView will expend and child linearlayout will shrink. I thought the bigger the number is more you get some space.
Since on your outermost layout you have android:orientation="horizontal", I believe you want to vary the size/space taken by ImageView and internal LinearLayout in horizontal direction. For this case try using
android:layout_width="0dp"
on the layouts where you've put android:layout_weight. If your orientation of the outer layout was vertical, I would have used android:layout_height="0dp" in order for the weights to handle width/height of the layouts.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#color/transactionRowBackground"
android:paddingBottom="5dp"
android:paddingTop="5dp" android:orientation="horizontal" >
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical" android:layout_weight="2" >
<TextView
android:id="#+id/title"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true"
android:gravity="top"
android:padding="5dp"
android:text="Test Title"
android:textColor="#color/textColor"
android:textSize="#dimen/subHeadingTextSize"
android:textStyle="bold" />
<TextView
android:id="#+id/description"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true"
android:gravity="top"
android:padding="5dp"
android:text="This is a test description"
android:textColor="#color/textColor"
android:textSize="#dimen/normalTextSize" />
</LinearLayout>
<ImageView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="3"
android:src="#drawable/ic_launcher"
android:layout_gravity="top"
android:contentDescription="" />
</LinearLayout>
Reading over Android docs might help: Layout Weights
With layout_weight you can specify a size ratio between multiple views. E.g. you have a MapView and a table which should show some additional information to the map. The map should use 3/4 of the screen and table should use 1/4 of the screen. Then you will set the layout_weight of the map to 3 and the layout_weight of the table to 1.
To get it work you also have to set the height or width (depending on your orientation) to 0dp.
Example
If there are three text boxes and two of them declare a weight of 1, while the third one is given no weight (0), then remaining space is assigned as follows:
1st text box = 1/(1+1+0)
2nd text box = 1/(1+1+0)
3rd text box = 0/(1+1+0)
I have seen that the width of an element can be set to a fraction of the screen width by using a relative layout (code below showing ONLY the relevant properties):
<LinearLayout>
<ImageView
android:layout_width="0dp"
android:layout_weight=".40" />
</imageView>
<TextView
android:layout_width="0dp"
android_layout_weight=".60" />
</LinearLayout>
But ... apparently this same trick can NOT be done for assigning proportional height of an element. Eclipse complains if I attempt to set a layout_height of 0dp. What should I do if I want an image with a caption, where the image takes up 40% of the screen height and the caption below gets 60% ?
You can indeed assign weights for both horizontal and vertical orientations of a LinearLayout.
Horizontal orientation example:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<ImageView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight=".40" />
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight=".60" />
</LinearLayout>
Vertical orientation example:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight=".40" />
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight=".60" />
</LinearLayout>
As an aside, it's useful to know that you don't have to specify floating point numbers for the weights. Android will simply sum up all of the weights and then divide by the total to get the percentage for each. So using 4 and 6 respectively for the layout_weights would have worked just as well.
Add android:orientation="vertical" to your layout and then set layout_height=0dp and weight to wanted values.
So:
<LinearLayout
android:orientation="vertical">
<ImageView
android:layout_height="0dp"
android:layout_weight=".40" />
</imageView>
<TextView
android:layout_height="0dp"
android_layout_weight=".60" />
</LinearLayout>
I want to fit two Listviews (+two Textviews) and a Button evenly into a LinearLayout. The final result should look something like this:
The Listviews can contain any number of items (from empty to requiring to scroll), however the button must be always visible. A lot of answers here suggest to use layout_weight along with layout_height="0dp" and layout_width="fill_parent", however this results in the Listviews taking up all available space and pushing the button out of the screen. I assume the parameters for the button are wrong, but I can't figure out which of them. At least the TextViews are working, since they are positioned correctly in every case.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_gravity="center">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="12sp"
android:gravity="left"/>
<ListView
android:layout_height="0dp"
android:layout_weight="1"
android:layout_width="fill_parent"/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="12sp"
android:layout_marginTop="12dp"
android:gravity="left"/>
<ListView
android:layout_height="0dp"
android:layout_weight="1"
android:layout_width="fill_parent"/>
<Button
android:layout_height="0dp"
android:layout_weight="1"
android:layout_width="fill_parent"/>
</LinearLayout>
I want to avoid to further nest the layout with additional LinearLayouts, unless there is no other way.
Something like this (not tested):
<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:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12sp"/>
<ListView
android:layout_height="0dp"
android:layout_weight="1"
android:layout_width="fill_parent"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12sp"
android:layout_marginTop="12dp"/>
<ListView
android:layout_height="0dp"
android:layout_weight="1"
android:layout_width="fill_parent"/>
<Button
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_width="wrap_content"/>
</LinearLayout>
Your button needs to have wrap_content height and (I think the reason of your bug) LinearLayout should have fill_parent as the height.
I'd like to have two adjacent views, a first that is a fixed size and a second that adjacent to the first that uses the remaining space.
I could easily do this with LinearLayout and weights, but I would like to avoid the "nested weights are bad for performance" problem.
Is there another layout type that can accomplish the equivalent? Please provide an example if so.
A RelativeLayout could do what you want, for example:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<Button
android:id="#+id/button1"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:text="Button"
android:background="#99cc00" />
<Button
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_toRightOf="#id/button1"
android:text="Button"
android:background="#0077cc"/>
</RelativeLayout>
The first Button will be 200dp in width and the second will stretch to fill the rest of the parent's remaining width.
You could also use a RelativeLayout to split two views in equal sizes to avoid having double weights on some layouts.
I believe this could be done with a RelativeLayout. Example:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="#+id/button"
android:layout_width="100dp"
android:layout_height="match_parent"
android:layout_alignParentLeft="true" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toRightOf="#id/button">
...
</LinearLayout>
</RelativeLayout>
You can try
<?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:orientation="horizontal" >
<Button
android:layout_width="50dp"
android:layout_height="wrap_content"
android:text="view with fixed size " />
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="view with remaining space" />
</LinearLayout>
this is how weight works in LinearLayout:
At first, it will deduct the fixed dimension, then according to the weight, divide the available space, assign to the views which specify the weight attribute