layout_weight in float and decimal - android

I change the width of a view dynamically in my code using:
final ImageButton ButtonTwo = (ImageButton)findViewById(R.id.callButton);
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) ButtonTwo.getLayoutParams();
params.weight = 1.3f;
ButtonTwo.setLayoutParams(params);
The idea is that it matches another view in XML :
<ImageButton
android:layout_height="match_parent"
android:layout_width="0dp"
android:id="#+id/imageButton"
android:src="#drawable/softkeyboard"
android:clickable="true"
android:onClick="softkeyboardButton"
android:layout_gravity="center_horizontal"
android:layout_weight="1.3"
android:background="#drawable/buttonstates"
/>
They're not the same width - the first button is wider than the second one. I know that this is because one is float and one is decimal, but how can I make them both the decimal size, or should I just do trial and error on the float value? My params.weight only accepts float values.
EDIT:
Here's my XML code:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/LinearLayout1"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical"
android:paddingBottom="0dp"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:paddingTop="0dp"
tools:context=".MainActivity">
<ListView
android:id="#+id/ListView_2"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_weight="1">
</ListView>
<!--Let's set the height of the linearlayout below to 0dp. Apparently it's less work on resources,
as otherwise we would be drawing it twice, because the size is also set dynamically-->
<LinearLayout
android:id="#+id/LinearLayout2"
android:layout_width="match_parent"
android:layout_height="60dp"
android:orientation="horizontal"
>
<!--android:adjustViewBounds="true"-->
<!-- we want the text to begin in the centre of the edittext view
that's what gravity does-->
<EditText
android:layout_width="0dp"
android:layout_height="match_parent"
android:id="#+id/editText"
android:inputType="phone"
android:gravity="center"
android:background="#d9d9d9"
android:layout_weight="4"
/>
<ImageButton
android:layout_width="0dp"
android:layout_height="match_parent"
android:id="#+id/callButton"
android:src="#drawable/call"
android:clickable="true"
android:onClick="softkeyboardButton"
android:background="#ffa62b"
android:layout_weight="2"
/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:orientation="horizontal" >
<CheckBox
android:layout_height="match_parent"
android:layout_width="0dp"
android:background="#ffa500"
android:text="New CheckBox"
android:id="#+id/checkBox"
android:layout_weight="5"
/>
<ImageButton
android:layout_height="match_parent"
android:layout_width="0dp"
android:id="#+id/imageButton"
android:src="#drawable/softkeyboard"
android:clickable="true"
android:onClick="softkeyboardButton"
android:layout_gravity="center_horizontal"
android:layout_weight="1.3"
android:background="#drawable/buttonstates"
/>
<View android:layout_height="fill_parent"
android:layout_width="2px"
android:background="#90909090"/>
<ImageButton
android:layout_height="match_parent"
android:layout_width="0dp"
android:id="#+id/imageButton2"
android:src="#drawable/settingsicon"
android:background="#drawable/buttonstates"
android:layout_gravity="center_horizontal"
android:layout_weight="1.3" />
</LinearLayout>
</LinearLayout>

Posting this as answer as advised. :)
If the idea is to just have them match the LayoutParams, why not just retrieve the LayoutParams of the ImageButton indicated in the xml, then set it as the LayoutParams of the ImageButton you want dynamically? Like so:
buttonTwo.setLayoutParams(buttonOne.getLayoutParams());
And to quote #Christophe Harris for other users:
I was having terrible trouble with the float - params.weight = 1.3f. The widths were never exactly the same, even though I was using your setLayoutParams = getLayoutParams. Probably something to do with floats never being accurate, I don't know. But then I changed it to params.width= 80, and it was exact.

You need to set layout_width to "0dp" for ButtonTwo for layout_weight to work correctly.
Hope this should work for you!

Related

android nested LinearLayout sizing

I am trying to achieve the following layout for my expandable listview.
Layout
Problem:
On android previewer the layout looks as expected:
refer to first image in attachment below.
However, when I run it on an emulator or a device the second TextView is not displayed.
refer to second image in attachment below
I have to set the height of the second ImageView (ivGroupIndicator) to match parent in order for the second TextView to display. But this stretches the expandable arrow icon.
refer to last image in attachment below
Images
Here is my layout.xml
<?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="50dp"
android:orientation="horizontal">
<ImageView
android:layout_width="25dp"
android:layout_height="match_parent"
android:src="#drawable/ci_hand_cursor"
android:layout_gravity="center" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="5dp"
android:paddingTop="5dp"
android:layout_weight="0.8">
<TextView
android:id="#+id/route_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Dhelhi Belhi"
android:fontFamily="sans-serif"
android:textSize="16sp"
android:textStyle="bold"
android:textColor="#color/colorPrimaryText"
android:paddingBottom="2dp"/>
<TextView
android:id="#+id/route_schedule_date"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="20-September-2017"
android:fontFamily="sans-serif"
android:textSize="14sp"
android:textColor="#color/colorSecondaryText"
android:paddingBottom="5dp"/>
</LinearLayout>
<ImageView
android:id="#+id/ivGroupIndicator"
android:layout_width="25dp"
android:layout_height="match_parent"
android:background="#drawable/group_indicator"
android:layout_gravity="center"/>
</LinearLayout>
What am i missing here?
This should do the trick:
Use 0dp as height/width when using weights
Weight can just be 1 (not 0.8)
Use equal weights on the 2 text views so they share equal vertical space
Set gravity to center_vertical on text views so the text is centered.
set scale type on image so it doesn't stretch.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal">
<ImageView
android:layout_width="25dp"
android:layout_height="match_parent"
android:layout_gravity="center"
android:scaleType="centerInside"
android:src="#drawable/ci_hand_cursor" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical"
android:paddingLeft="5dp"
android:paddingTop="5dp">
<TextView
android:id="#+id/route_name"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:fontFamily="sans-serif"
android:gravity="center_vertical"
android:text="Dhelhi Belhi"
android:textColor="#color/colorPrimaryText"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="#+id/route_schedule_date"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:fontFamily="sans-serif"
android:gravity="center_vertical"
android:text="20-September-2017"
android:textColor="#color/colorSecondaryText"
android:textSize="14sp" />
</LinearLayout>
<ImageView
android:id="#+id/ivGroupIndicator"
android:layout_width="25dp"
android:layout_height="match_parent"
android:layout_gravity="center"
android:background="#drawable/group_indicator"
android:scaleType="centerInside" />
</LinearLayout>
The problem maybe is that you set the height of the parent layout to 50dp. Try to set it to wrap content, and use height=0dp and weight=1 for the vertical LinearLayout

How do I overlap three equally-sized views with smaller views between them?

I am trying to make three buttons equally-spaced and aligned vertically with circles overlapping between them like so:
I ran into difficulties because a LinearLayout was needed to equally weight the three buttons, but overlapping views are most easily done in RelativeLayout and FrameLayout (I need to support <21 SDK, so I can't use z-index with LinearLayout).
When I put the "OR" circles in the Frame/RelativeLayouts, there's no easy way to set them at 1/3rd the view height so that they fall in between the buttons.
How do I divide a FrameLayout with the OR circles into thirds to properly place the circles?
I have did following xml coding and generate similar out put
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:weightSum="3"
android:gravity="center"
>
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:text="dd"
android:background="#CCCCCC"
android:gravity="center"
android:layout_margin="5dp"
android:layout_weight="1"/>
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:text="dd"
android:layout_margin="5dp"
android:background="#CCCCCC"
android:gravity="center"
android:layout_weight="1"/>
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_margin="5dp"
android:text="dd"
android:background="#CCCCCC"
android:gravity="center"
android:layout_weight="1"/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:weightSum="3"
android:gravity="center"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="30dp"
android:background="#000000"
android:text="OR"
android:textColor="#FFFFFF"
android:gravity="center"
android:layout_height="30dp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="30dp"
android:background="#000000"
android:text="OR"
android:textColor="#FFFFFF"
android:gravity="center"
android:layout_height="30dp" />
</LinearLayout>
</LinearLayout>
</FrameLayout>
I couldn't find a straightforward solution to this, so I'm answering my own question! Please let me know if you have a better solution.
The solution I came up with was to layout the buttons in a LinearLayout inside a FrameLayout and weight them properly. The OR circles are placed in the FrameLayout after the buttons, so that they will be drawn on top. However, they are not positioned in the xml.
In onCreate() I measured the drawn size of the LinearLayout with buttons and then moved the OR circles by one third plus the radius of the circle.
Here is the relevant XML. The key points are:
FrameLayout wrapper, matching parent for full area buttons to be shown.
LinearLayout wrapper for buttons, matching parent.
Button heights all set to 0dp and layout_weight="1"
TextViews for OR circles centered horizontally, but not adjusted vertically. Note their diameter is 30dp
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="#+id/buttons_container">
<Button
android:id="#+id/record_topic_option_1"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:onClick="topic1"
android:theme="#style/PrimaryButton"/>
<Button
android:id="#+id/record_topic_option_2"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
android:onClick="topic2"
android:theme="#style/PrimaryButton" />
<Button
android:id="#+id/record_topic_option_3"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:onClick="topic3"
android:theme="#style/PrimaryButton" />
</LinearLayout>
<TextView
android:id="#+id/top_or"
android:layout_width="30dp"
android:layout_height="30dp"
android:textAlignment="center"
android:text="OR"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:textSize="#dimen/material_text_caption"
android:textColor="#android:color/white"
android:background="#drawable/or_circle_background"
/>
<TextView
android:id="#+id/bottom_or"
android:layout_width="30dp"
android:layout_height="30dp"
android:textAlignment="center"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:text="OR"
android:textSize="#dimen/material_text_caption"
android:textColor="#android:color/white"
android:background="#drawable/or_circle_background" />
Once that is set up, the trick is to adjust the circles programmatically in onCreate()
final View buttonContainer = findViewById(R.id.buttons_container);
View topOr = findViewById(R.id.top_or);
View bottomOr = findViewById(R.id.bottom_or);
//Get the 15dp radius in pixels at the current screen density.
final int added_height_for_radius = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
15, getResources().getDisplayMetrics());
//Use a ViewTreeObserver to make sure that the view is drawn and you get an accurate measurement of the LinearLayout with buttons
buttonContainer.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
#SuppressLint("NewApi")
#SuppressWarnings("deprecation")
#Override
public void onGlobalLayout() {
int width = buttonContainer.getWidth();
int height = buttonContainer.getHeight();
//Moving the topOr and bottomOr by setting the top margin to height/3-radius and 2*height/3-radius
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams)topOr.getLayoutParams();
params.setMargins(0, (height/3)-added_height_for_radius, 0, 0);
topOr.setLayoutParams(params);
FrameLayout.LayoutParams params2 = (FrameLayout.LayoutParams)bottomOr.getLayoutParams();
params2.setMargins(0, (2*height/3)-added_height_for_radius, 0, 0);
bottomOr.setLayoutParams(params2);
buttonContainer.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
Thanks to
Get height and width of a layout programmatically

Center text vertically independently of View height?

I'm doing my best to center the text vertically but I cannot manage to do it. The problem is that I have rows of buttons with height=fill_parent and weight=1 and as the rows become smaller my text starts touching the bottom of the view as seen here:
I tried removing the padding, margin, changing the height and so on. But nothing seems to do it.
How can I align it vertically even when the text size is close the the view height?
Here's the code for the view containing number 5:
<Button
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="5"
android:layout_weight="1"
tools:ignore="HardcodedText"
android:clickable="false"
android:textSize="90dp"
android:textColor="?attr/color1"
android:gravity="center"
android:paddingLeft="#dimen/normal_margin"
android:paddingRight="#dimen/normal_margin"
android:padding="0dp" />
As per my advice if you have two options to make such layout and getout from the issue you are having.
1. Use GridView
Using gridview you will have equal space in all four directions(left, right, top, bottom). You dont have to worry about the equal spacing for the grid item.
<GridView
android:id="#+id/album_list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:cacheColorHint="#00000000"
android:gravity="center"
android:numColumns="auto_fit"
android:stretchMode="spacingWidthUniform"
android:drawSelectorOnTop="true"/>
Just try above code with which you will have all view equally distributed in the grid.
2. Use TableLayout and TableRow
Please check below code to use TableLayout and TableRow with its attribute to have all view equally arranged. Even if you smaller the height and width of the TableLayout, it will remain equally arranged in that view.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin" tools:context=".MainActivity">
<TableLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:layout_margin="5dp">
<TableRow android:weightSum="3"
android:layout_weight="1" android:gravity="center">
<Button android:gravity="center"
android:textSize="13sp" android:textColor="#000000"
android:text="1" android:layout_weight="1"/>
<Button android:gravity="center"
android:textSize="13sp" android:textColor="#000000"
android:text="1" android:layout_weight="1"/>
<Button android:gravity="center"
android:textSize="13sp" android:textColor="#000000"
android:text="1" android:layout_weight="1"/>
</TableRow>
<TableRow android:weightSum="3" android:layout_weight="1" android:gravity="center">
<Button android:gravity="center"
android:textSize="13sp" android:textColor="#000000"
android:text="1" android:layout_weight="1"/>
<Button android:gravity="center"
android:textSize="13sp" android:textColor="#000000"
android:text="1" android:layout_weight="1"/>
<Button android:gravity="center"
android:textSize="13sp" android:textColor="#000000"
android:text="1" android:layout_weight="1"/>
</TableRow>
<TableRow android:weightSum="3" android:layout_weight="1" android:gravity="center">
<Button android:gravity="center"
android:textSize="13sp" android:textColor="#000000"
android:text="1" android:layout_weight="1"/>
<Button android:gravity="center"
android:textSize="13sp" android:textColor="#000000"
android:text="1" android:layout_weight="1"/>
<Button android:gravity="center"
android:textSize="13sp" android:textColor="#000000"
android:text="1" android:layout_weight="1"/>
</TableRow>
</TableLayout>
Please find output of this TableLayout.
Let me know if this issue is resolved. If not, I will be happy to help you again.
Enjoy Coding... :)
If this button is inside a linearlayout with vertical orientation. Since you define the weight, you want to make the height to be "0dp" instead of "fill_parent".
To make the text center vertical. Did you try android:gravity:"center_vertical"?
Try this
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentBottom="true"
android:layout_below="#+id/dialer_title"
android:orientation="vertical"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.2" >
<ImageButton
android:id="#+id/btn1"
style="#style/DialPadButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0.33"
android:contentDescription="#string/desc_1"
android:scaleType="centerCrop"
android:soundEffectsEnabled="false"
android:src="#drawable/dial_num_1_no_vm" />
<ImageButton
android:id="#+id/btn2"
style="#style/DialPadButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0.33"
android:contentDescription="#string/desc_2"
android:scaleType="centerCrop"
android:soundEffectsEnabled="false"
android:src="#drawable/dial_num_2" />
<ImageButton
android:id="#+id/btn3"
style="#style/DialPadButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0.33"
android:contentDescription="#string/desc_3"
android:scaleType="centerCrop"
android:soundEffectsEnabled="false"
android:src="#drawable/dial_num_3" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.2" >
<ImageButton
android:id="#+id/btn4"
style="#style/DialPadButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0.33"
android:contentDescription="#string/desc_4"
android:scaleType="centerCrop"
android:soundEffectsEnabled="false"
android:src="#drawable/dial_num_4" />
<ImageButton
android:id="#+id/btn5"
style="#style/DialPadButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0.33"
android:contentDescription="#string/desc_5"
android:scaleType="centerCrop"
android:soundEffectsEnabled="false"
android:src="#drawable/dial_num_5" />
<ImageButton
android:id="#+id/btn6"
style="#style/DialPadButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0.33"
android:contentDescription="#string/desc_6"
android:scaleType="centerCrop"
android:soundEffectsEnabled="false"
android:src="#drawable/dial_num_6" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.2" >
<ImageButton
android:id="#+id/btn7"
style="#style/DialPadButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0.33"
android:contentDescription="#string/desc_7"
android:scaleType="centerCrop"
android:soundEffectsEnabled="false"
android:src="#drawable/dial_num_7" />
<ImageButton
android:id="#+id/btn8"
style="#style/DialPadButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0.33"
android:contentDescription="#string/desc_8"
android:scaleType="centerCrop"
android:soundEffectsEnabled="false"
android:src="#drawable/dial_num_8" />
<ImageButton
android:id="#+id/btn9"
style="#style/DialPadButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0.33"
android:contentDescription="#string/desc_9"
android:scaleType="centerCrop"
android:soundEffectsEnabled="false"
android:src="#drawable/dial_num_9" />
</LinearLayout>
<LinearLayout
style="#style/DialPadRow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.2" >
<ImageButton
android:id="#+id/btnStar"
style="#style/DialPadButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0.33"
android:contentDescription="#string/desc_astr"
android:scaleType="centerCrop"
android:soundEffectsEnabled="false"
android:src="#drawable/dial_num_star" />
<ImageButton
android:id="#+id/btn0"
style="#style/DialPadButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0.33"
android:contentDescription="#string/desc_0"
android:scaleType="centerCrop"
android:soundEffectsEnabled="false"
android:src="#drawable/dial_num_0" />
<ImageButton
android:id="#+id/btnHash"
style="#style/DialPadButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0.33"
android:contentDescription="#string/desc_hash"
android:scaleType="centerCrop"
android:soundEffectsEnabled="false"
android:src="#drawable/dial_num_hash" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.2" >
<ImageButton
android:id="#+id/btnContacts"
style="#style/DialPadButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0.33"
android:contentDescription="#string/string_menu_contacts"
android:scaleType="centerCrop"
android:soundEffectsEnabled="true"
android:src="#drawable/selector_dial_contact_b" />
<ImageButton
android:id="#+id/btnCall"
style="#style/DialPadButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0.33"
android:contentDescription="#string/string_menu_call"
android:scaleType="centerCrop"
android:soundEffectsEnabled="true"
android:src="#drawable/dial_num_call" />
<ImageButton
android:id="#+id/btnDelete"
style="#style/DialPadButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0.33"
android:contentDescription="#string/desc_backspace"
android:scaleType="centerCrop"
android:soundEffectsEnabled="true"
android:src="#drawable/dial_num_delete" />
</LinearLayout>
</LinearLayout>
This will create phone dealer with equal button size.
For style="#style/DialPadButton" create style with name DialPadButton and customize buttons as you want. In my case I have added item name="android:layout_margin" with value 5dp.
design this using a grid view you will have some more functionality. else take one Linear Layout inside that set another three linear layout orientation horizontal and weight sum= 3 ,put each button on the child layout and give layout weight =1 for each button.
It does not mean that the text "5" is not centered. The text "5" appears slightly below center because the button is not given enough space to layout its text content. Even though it is provided the adequate height, the text "5" will appear slightly above center. This is because, there are characters('y', 'g', etc) with larger descent than "5" (maximum possible ascent and descent are considered during layouting the text even tough your text contains no taller glyph or glyph with non zero descent). Also see this.
If more height is provided for the buttons in row, they will neatly center align their texts.
I would suggest using a TextView instead of a Button, because that has less tricky margins and gives you more control on how to place your Text. (In general I only seldom use buttons, but tend to make other views TextView, ImageView,... clickable instead)
<TextView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="5"
android:layout_weight="1"
tools:ignore="HardcodedText"
android:clickable="false"
android:textSize="90dp"
android:textColor="?attr/color1"
android:gravity="center"
android:paddingLeft="#dimen/normal_margin"
android:paddingRight="#dimen/normal_margin"
android:padding="0dp" />
In case you need some kind of indication on whether or not the TextView was pressed, you can add a selector as a background.
For this, have a look here.
Finally if you want your text to fit for any possible view sizes, have a look at the AutoFitTextView.
I think the simplest way to achieve this by using AutoFitTextView
You can get this library from this link : https://github.com/grantland/android-autofittextview
It will dynamically resize text size with current height and width.
I hope this will help you.
Good Luck.
Try to use a negative top padding, for example:
<Button
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="5"
android:layout_weight="1"
tools:ignore="HardcodedText"
android:clickable="false"
android:textSize="90dp"
android:textColor="?attr/color1"
android:gravity="center"
android:paddingLeft="#dimen/normal_margin"
android:paddingRight="#dimen/normal_margin"
android:paddingTop="-2dp" />
You can play with that, and get the necessary value for top padding. Of course, you can use different values for different screen densities by using #dimen.
you can't use upper spacing for centering because it belongs to font. I mean every font has ascent and descent metric. See pic below.
so when android centers text it calculates it's overall height (including upper nad bottom spacing). And than centers resulted rect. You can get FontMetrics to see font acsent and descent values.
E.g. calling Paint.FontMetrics fm = textView.getPaint().getFontMetrics();we get:
fm = {android.graphics.Paint$FontMetrics#3668}
ascent = -25.976562
bottom = 7.5878906
descent = 6.8359375
leading = 0.0
top = -29.572266
Intresting? So how to remove top and bottom spacing and use this space to center font? I see two solutions:
create custom component and layout text excluding those spacings. If
you want only single line text it will be easy. See TextView code.
we know spacings, so we can move text accordingly. Set translation to
a Button content. To remove top spacing you can do:
button.setTranslationY(fm.top - fm.ascent); If you want text centered
without spacing, do following: button.setTranslationY((fm.top - fm.ascent) + (fm.bottom - fm.descent));

HorizontalScrollView Not Scolling When Specified Width

I'm trying to have a HorizontalScrollView with 8 buttons which I can code fine. But I want to have the layout double the width of the screen so there are 4 buttons on the screen and the user has to scroll to see more (I'm don't want a "snap" scroll).
To do this I've manually change the width of the HorizontalScrollView to say "770dp" but whenever I specify the width it looks correct but does not scroll. Changing the width back to "wrap_content" and it works fine but does not look correct (5 or 6 buttons on the screen).
My xml code is below. This is just an extract - there are many more layouts/views on the screen.
I will be wanting to programmatically specify the width later the double the phone's screen size didn't want to move on to that until I worked out why the above isn't working.
I have included that code if anyone wants to lend a hand, but it is NOT related to the above non-scrolling problem.
Thanks in advance for any help you can give. Much appreciated.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true"
android:orientation="vertical"
tools:context="com.example.testScroll.MainActivity"
tools:ignore="MergeRootFrame" >
<HorizontalScrollView
android:id="#+id/topline_Buttons"
android:layout_width="770dp"
android:layout_height="wrap_content"
android:fillViewport="true"
android:scrollbars="none">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="0dp"
android:orientation="horizontal" >
<Button
android:id="#+id/button_1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="0dp"
android:layout_weight="1"
android:text="#string/button_1" />
<Button
android:id="#+id/button_2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="0dp"
android:layout_weight="1"
android:text="#string/button_2" />
<Button
android:id="#+id/button_3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="0dp"
android:layout_weight="1"
android:text="#string/button_3" />
<Button
android:id="#+id/button_4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="0dp"
android:layout_weight="1"
android:text="#string/button_4" />
<Button
android:id="#+id/button_5"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="0dp"
android:layout_weight="1"
android:text="#string/button_5" />
<Button
android:id="#+id/button_6"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="0dp"
android:layout_weight="1"
android:text="#string/button_6" />
<Button
android:id="#+id/button_7"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="0dp"
android:layout_weight="1"
android:text="#string/button_7" />
<Button
android:id="#+id/button_8"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="0dp"
android:layout_weight="1"
android:text="#string/button_8" />
</LinearLayout>
</HorizontalScrollView>
</LinearLayout>
Here is what I have found on SO HERE to programmatically set the width. ALthough I haven't got it working yet
//Set HorizontalScrollView double screen width
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(metrics.widthPixels*2, LayoutParams.MATCH_PARENT);
LinearLayout topline_Buttons = (LinearLayout) findViewById(R.id.topline_Buttons);
topline_Buttons.setLayoutParams(params);
I think trying to increase the size of the scroll view is the wrong way to approach this. If you want the layout that the scroll view wraps to be larger, then change the height of the layout.
Remember that the buttons are in the LinearLayout, and that is currently set to wrap content, so it will only take the space needed to display its children (the buttons).
Try this (with the rest of your code of course):
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true"
android:scrollbars="none">
<LinearLayout
android:id="#+id/topline_Buttons"
android:layout_width="770dp"
android:layout_height="wrap_content"
android:layout_margin="0dp"
android:orientation="horizontal" >
// try this way,hope this will help you..
Note : if fix HorizontalScrollView layout_width then it's not Scrollable so you have gave layout_width "wrap_content"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true"
android:orientation="vertical">
<HorizontalScrollView
android:id="#+id/topline_Buttons"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fillViewport="true"
android:scrollbars="none">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:id="#+id/button_1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="button_1" />
<Button
android:id="#+id/button_2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="button_2" />
<Button
android:id="#+id/button_3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="button_3" />
<Button
android:id="#+id/button_4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="button_4" />
<Button
android:id="#+id/button_5"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="button_5" />
<Button
android:id="#+id/button_6"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="button_6" />
<Button
android:id="#+id/button_7"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="button_7" />
<Button
android:id="#+id/button_8"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="button_8" />
</LinearLayout>
</HorizontalScrollView>
</LinearLayout>
**Also remove this peace of code from Activity**
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(metrics.widthPixels*2, LinearLayout.LayoutParams.MATCH_PARENT);
topline_Buttons.setLayoutParams(params);
Ok I've worked it out! Or at least one way of doing it...
If there is a better way let me know.
Instead of specifying the width of the LinearLayout or HorizontalScrollView I needed to specify the width of the buttons inside to 1/4th of the screensize. The HorizontalScrollView should fill the whole page, the LinearLayout wrap content and so the buttons make enough space for themselves.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true"
android:orientation="vertical">
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true"
android:scrollbars="none">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="0dp"
android:orientation="horizontal" >
<Button
android:id="#+id/button_1"
android:layout_width="92dp" // Specify width here manually
android:layout_height="wrap_content"
android:text="1" />
... etc
That worked but obviously wouldn't look right with many screen sizes, so I specified it programmatically:
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int screenWidth = size.x / 4;
button_1 = (Button)findViewById(R.id.button_1);
button_1.setLayoutParams(new LinearLayout.LayoutParams(screenWidth, LayoutParams.WRAP_CONTENT));

android view default padding or margins

It seems some views like TextView has its own padding or margin...I mean when I'm setting textSize 16dp to textView, it takes more then 24 pixels on hdpi device screen to display this control. Maybe I'm missing something, please help
<LinearLayout
android:id="#+id/uc_button_title_panel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="#color/closed_red" />
<TextView
android:id="#+id/uc_button_title_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="0dp"
android:includeFontPadding="false"
android:background="#null"
android:padding="0dp"
android:text="#string/demo_text"
android:textColor="#325083"
android:textSize="16dp"
android:textStyle="bold" />
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="#color/closed_red" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="#dimen/activity_vertical_margin"
android:layout_marginBottom="#dimen/activity_vertical_margin"
android:layout_marginLeft="#dimen/activity_horizontal_margin"
android:layout_marginRight="#dimen/activity_horizontal_margin"
android:orientation="vertical">
</LinearLayout>
In android while using layouts, the default margins and padding available is this: #dimen/activity_vertical_margin or #dimen/activity_horizontal_margin. I have put an example code above.

Categories

Resources