9

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:

enter image description 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" />
David Wasser
  • 93,459
  • 16
  • 209
  • 274
lisovaccaro
  • 32,502
  • 98
  • 258
  • 410
  • what `ViewGroup` are you using? i am thinking your solution is `Gravity.CENTER` to `match_parent` children – Elltz Feb 02 '15 at 00:27
  • do you have any reason to use `android:textSize="90dp"` ?? try the approved directive and see `android:textSize="90sp"` – Elltz Feb 02 '15 at 01:53
  • hi @Eltz, the app is for people with low eyesight and already uses the max text size possible. So if I use SP I may risk the user choosing a large text size and breaking the UI. All the buttons are in a TableRow, I tried chaning the height to match_parent on the button and I still have the same problem. Still I don't think it has anything to do with the height. – lisovaccaro Feb 02 '15 at 14:47
  • I think that is because default padding of Textview for texts, http://stackoverflow.com/questions/4768738/android-textview-remove-spacing-and-padding-on-top-and-bottom . I tried their solutions but didn't work for me. – Chitrang Feb 04 '15 at 06:52
  • 1
    Please post the XML for the surrounding View or Layout. – David Wasser Feb 07 '15 at 13:50
  • Try a negative top margin or padding. – Christine Feb 07 '15 at 13:58

9 Answers9

2

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"?

bond
  • 11,236
  • 7
  • 48
  • 62
2

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. enter image description here

Let me know if this issue is resolved. If not, I will be happy to help you again.

Enjoy Coding... :)

Shreyash Mahajan
  • 23,386
  • 35
  • 116
  • 188
2

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.

Mukesh
  • 402
  • 4
  • 19
1

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.

Ameen Maheen
  • 2,719
  • 1
  • 28
  • 28
1

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.

Community
  • 1
  • 1
Durgadass S
  • 1,098
  • 6
  • 13
1

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.

Jeroen Mols
  • 3,436
  • 17
  • 24
1

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.

enter image description here

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));

Leonidos
  • 10,482
  • 2
  • 28
  • 37
1

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.

Jitty Aandyan
  • 1,994
  • 1
  • 13
  • 12
1

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.

romtsn
  • 11,704
  • 2
  • 31
  • 49