5
votes

The text inside label is vertically aligned by default on iOS, however on Android it's not. How to center it vertically on Android (I'm interested in centering text inside Label, not wrapping label inside any other layout to get the same effect)?

To see what I mean run the next code on iOS and Android.

xml:

<Page xmlns="http://schemas.nativescript.org/tns.xsd" loaded="onLoaded">
    <Label text="test" />
</Page>

css:

Label {
    width: 60;
    height: 60;
    text-align: center;
    background-color: aquamarine;
    border-radius: 30;
}
7

7 Answers

13
votes

Set the padding accordingly to the (width - font-size) / 2 (rough approximation may differ for smaller boxes where Capital or small letters has different center point)

e.g.

Label {
    width: 60;
    height: 60;
    border-radius: 30;
    text-align:center;
    background-color: aquamarine;
    padding: 15;
    font-size: 20;
}

or example with bigger sizes:

Label {
    width: 200;
    height: 200;
    border-radius: 100;
    text-align:center;
    background-color: aquamarine;
    padding: 80;
    font-size: 20;
}

p.s If you wrap your label in StackLayout you won't need height

e.g.

  <StackLayout>
    <Label text="test" class="title"/>
  </StackLayout>

Label {
    width: 200;
    border-radius: 100;
    text-align:center;
    background-color: aquamarine;
    padding: 80;
    font-size: 20;
}
5
votes

Using padding will screw things up if you're using the same css on iOS. setGravity(17) will also horizontally align the text. If you want to just vertically align the text, and keep the normal behavior for the horizontal alignment, use

this.nativeView.android.setGravity(this.nativeView.android.getGravity() & 0xffffffdf);

this will remove the vertical-align=top flag from the label

I've created this directive that should change the default for labels:

import {AfterViewChecked, Directive, ElementRef, Input} from '@angular/core';
import { Label } from 'ui/label';

@Directive({
    selector: 'Label',
})
export class UpdateLabelDirective implements AfterViewChecked {    
    private get nativeView(): Label {
        return this.el.nativeElement;
    }

    constructor(private readonly el: ElementRef) {}

    ngAfterViewChecked(): void {
        if (this.nativeView.android && (this.nativeView.android.getGravity() & 0x00000020)) {
            this.nativeView.android.setGravity(this.nativeView.android.getGravity() & 0xffffffdf);
        }
    }
}
5
votes

Don't think of it as vertically centring your labels text. Instead put your Label in a container and centre it relative to the container.

<StackLayout verticalAlignment="center">
  <Label text="test" />
</StackLayout>

This will centre align your Label (vertically) within the StackLayout. You'll also notice the StackLayout will now only take up the vertical space required by its children. If you want it to use up more vertical space you just need to give it a height.

The following creates a three row GridLayout with each row occupying 33.3...% of the screen with their labels centred within them.

<Page xmlns="http://www.nativescript.org/tns.xsd">
  <GridLayout rows="*, *, *">
    <StackLayout row="0" class="red stack">
      <Label text="red" class="label"/>
    </StackLayout>
    <StackLayout row="1" class="green stack">
      <Label text="green" class="label"/>
    </StackLayout>
    <StackLayout row="2" class="blue stack">
      <Label text="blue" class="label"/>
    </StackLayout>
  </GridLayout>
</Page>
.stack {
  height: 100%;
  vertical-align: center;
}

.label { text-align: center; }

.red { backgroundColor: red; }
.green { backgroundColor: green; }
.blue { backgroundColor: blue; }

Here's a Playground of the above if you'd like to see it working on your device. Try commenting out the height property in home-page.css (line 13).

4
votes

You can enable it natively, in the code:

myLabel.android.setGravity(17)

17 is value for Gravity.CENTER constant (https://developer.android.com/reference/android/view/Gravity.html#CENTER)

1
votes

Most simple solution per css:

line-height: 100%;
0
votes

Another option is to reconsider why you're trying to vertically align the contents of the label.

I came to this page trying to do the same thing but decided to remove the height css on the label and just let the label be the size of the text and vertically center the label within it's parent

0
votes

After spent some time digging, I found this solution which will make vertical_center your default setting.

in your AndroidManifest.xml, add the following style

<style name="MyTextViewStyle" parent="android:Widget.TextView">
        <item name="android:gravity">center_vertical</item>
</style>

Then apply the style in your theme

<style name="AppTheme" parent="AppThemeBase">
   <item name="actionMenuTextColor">@color/ns_white</item>
   <item name="android:actionMenuTextColor">@color/ns_white</item>   

   <item name="android:textViewStyle">@style/MyTextViewStyle</item>
</style>