Nativescript: how to vertically align text inside Label on Android
Asked Answered
F

8

5

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;
}
Few answered 29/9, 2016 at 11:54 Comment(0)
D
16

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;
}
Dalhousie answered 29/9, 2016 at 12:22 Comment(5)
On second thought it must be (height - font-size)/2 but in the case above both width and height have identical values so it will work for proportional dimensionsDalhousie
When I change the padding to exactly (height - font-size)/2 the text gets clipped from the bottom. So, yep, this still needs to be adjusted for different font sizes.Few
Btw, why is so? Why the text is centered vertically on iOS by default and no extra settings are needed, but Android it's aligned to the top?Few
padding: X is the key. Be careful if more the heightArapaima
LEGEN...Wait for it... DARY!!Gwenni
D
6

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);
        }
    }
}
Dedra answered 30/5, 2018 at 9:29 Comment(0)
P
5

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

Pennsylvanian answered 3/4, 2019 at 3:26 Comment(0)
O
4

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)

Odessaodetta answered 20/1, 2017 at 0:58 Comment(0)
B
1

Most simple solution per css:

line-height: 100%;
Blalock answered 3/9, 2018 at 13:48 Comment(0)
I
1

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>
Insecurity answered 24/2, 2019 at 2:53 Comment(2)
Can you elaborate on this one? Where in my AndroidManifest do I put this? Because if I put it at the root, it says AndroidManifest.xml:17:13-19:21: AAPT: error: unexpected element <style> found in <manifest>.Dedra
This works so well! Except you add both styles in App_Resources/Android/src/main/res/values/styles.xml, not AndroidManifest.xmlParaphrast
R
0

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

Rysler answered 23/11, 2018 at 19:45 Comment(2)
Because that often involves adding a new layout, and you'll want to minimize the amount of layouts you're using.Dedra
Agreed, they have real costRysler
P
0

@gogoout is on the right track, but his answer had a few issues.

In your App_Resources/Android/src/main/res/values/styles.xml, add the following style

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

Then add the style in your theme

  <style name="AppThemeBase" parent="Theme.AppCompat.Light.NoActionBar">
   ...
   <item name="android:textViewStyle">@style/MyTextViewStyle</item>
</style>

Works like a charm!

Paraphrast answered 24/2, 2023 at 1:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.