Nativescript: Feature Request: Span supporting alignment

Created on 5 Sep 2017  路  41Comments  路  Source: NativeScript/NativeScript

Please, provide the details below:

Did you verify this is a real problem by searching Stack Overflow and the other open issues in this repo?

Yes

Tell us about the problem

Please, ensure your title is less than 63 characters long and starts with a capital
letter.

Which platform(s) does your issue occur on?

Android -- confirmed

Please provide the following version numbers that your issue occurs with:

Lasted CLI, runtime, core-modules

Please tell us how to recreate the issue in as much detail as possible.

<Button row="3" col="1" class="action-button" tap="{{ $parents['ListView'].onReplyTap }}">
            <FormattedString>
                  <Span text="&#xE0CB; " class="mdi"></Span>
                   <Span text="{{ reply_count }}"></Span>
            </FormattedString>
</Button>

Given the above layout, using spans for positioning a font icon next to the text inside a button. It would be nice to have a way to shift the alignment of the span. The font icon is slightly offset vertically compared to the string text. I've looked through the span source and seen the limited list of styling props available. If this isn't simply achievable, maybe an explanation on the limitation so the documentation can be improved in this area as well. I'm sure I can't be the only one who's tried this approach and noticed it 馃槃 so if there are limitations at least having it documented for new NS devs would be nice 馃憤 look forward to hearing more info. Thanks as always 馃

Below is screen demonstrating the offset:
offsetspan


Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

feature

Most helpful comment

Any progress on this FR?

All 41 comments

@bradmartin I remember I was looking into this when working on 3.0 release but there was limitation on android - the attributes that center text were not working (my guess either a bug or limitation on android). So I didn't implement it.

I'm not seeing option for vertical alignment in a span:
https://developer.android.com/reference/android/text/Layout.Alignment.html

Maybe custom Layout could do it.

Any fixes for this ?

+1

Just stumbled upon this one since I wanted my icon to be bigger than the text, but then it aligns them at the bottom so it does not look good. Workaround is to use GridLayout and have separate button and icon but then you loose all the goodies like ripple effect in android or pressed styles.

@hshristov Would you by any chance have that (iOS) changeset still lingering around somewhere? I'd be happy to take a look.

Does any formatting css work inside a Formatted String with Span? I'm trying to add some spacing between the font icon and my text, and it's not working out.

<Button (tap)="on.tap()"
            class="side-menu-button">
      <FormattedString class="button-text">
        <Span class="material-icon"
              [text]="route.icon">
        </Span>
        <Span [text]="route.text"></Span>
      </FormattedString>
    </Button>
    .material-icon {
      display: inline-block;
      margin-right: 30px;
    }

@EddyVerbruggen nope, but I think it was possible using NSAttributedString. Android is problematic and probably requires custom text layout.

@hshristov Thanks, don't worry about it.

@kamok You can prefix the second Span with spaces (<Span [text]="' '" + route.text"></Span>), or use fi. srtyle="margin-right: 10 to the first Span.

@EddyVerbruggen Adding spaces to the second Span works, but that's bad code. Not reuse-able at all. Can't seem to add content using css either.

The style="margin-right: 10" to the first Span does not work either. Like I said, all the margin, padding, alignment css seems to be not working when it's inside a FormattedString

I'm gonna open up another Issue, but here's the gist:

  <Label>
    <FormattedString>
      <Span class="foo"
            text="Foo"></Span>
      <Span class="bar"
            text="Bar"></Span>
    </FormattedString>
  </Label>
  .foo{
    font-size: 30px;
    margin-right: 10px;
  }

  .bar {
    font-size: 10px;
  }

margin-right does not work at all.

I know. Span is very limited css wise. That鈥檚 why I mentioned the spaces trick. It鈥檚 not that bad if you want a fixed width between the left and right element. Just throw a Span with a few spaces in between them.

What a disappointment, I opened #1482 and got a official response though, so that was good. Span should really not be that limited. It's a very basic tool in the toolbox of a developer. I resulted in the spaces trick, but still have the same issue as this poster where the font doesn't align.

please any idea on how to bypass @tap in Span I really need this to work on NativeScript-Vue

<Label class="login-label sign-up-label center" textWrap="true">
                <FormattedString>
                    <Span text="By signing up I agree to the "/> 
                    <Span text="terms of service " @tap="termsSer" class="acl"/>
                    <span text="&"/>
                    <span text=" privacy policy " @tap="privatePol" class="acl"/>
              </FormattedString>
 </Label>  

Or any alternative solution

+1

this may help someone else am able to do by

<StackLayout class="login-label text-center" textWrap="true">
   <Label text="By signing up I agree to the " class="t-12 ftf m-t-0"/>
        <StackLayout orientation="horizontal" class="m-b-10">
                    <Label text="terms of service " @tap="termsSer" class="acl t-12 ftf"/>
                    <Label text=" &" class="t-12 ftf"/>
                    <Label text=" privacy policy " @tap="privatePol" class="acl t-12 ftf"/>
        </StackLayout>
 </StackLayout> 

Any update ?

[bump]

+1 We are facing the same issue.

We are trying to create a button with text and an icon with possibly different font-sizes (e.g. because the icon may appear too small). For this purpose we use two Spans inside a FormattedString inside a Button. Unfortunately, both Spans remain anchored to the bottom and nothing seems to be changing their positions so we cannot get the alignment we are aiming at.

It would be really great if we could apply the alignments previously mentioned in this issue in order to vertically center the two Spans inside the FormattedString, as well as to vertically center the FormattedString inside the Button.

Here is a playground example:
https://play.nativescript.org/?template=play-ng&id=3Jf73f&v=3

+1

+1

+1

Any progress on this FR?

Same here, it's nearly impossible to vertical align two span with different font-size

Added a PR for this issue. Not completely finished, but mostly working. Enhancement ideas are welcome.

@bundyo I updated to latest @nativescript/core 6.5.12 and I still do not see how to get vertical-alignment of Spans working, maybe I am missing something.

I created a css class for each alignment value like this:

.top {
    vertical-align: top;
}

.middle {
    vertical-align: middle;
}

.stretch {
    vertical-align: stretch;
}

.text-top {
    vertical-align: text-top;
}

.text-bottom {
    vertical-align: text-bottom;
}

.super {
    vertical-align: super;
}

.sub {
    vertical-align: sub;
}

.baseline {
    vertical-align: baseline;
}

.center {
    vertical-align: center;
}

Then I try to make a Label with multiple spans, where some spans have different fontSize values and different alignment values like this:

<Label height="90" backgroundColor="#f5f5f5" textWrap="true">
            <FormattedString>
                <Span text="top" className="top" fontSize="15"/>
                <Span text=" "/>
                <Span text="middle" className="middle" fontSize="10"/>
                <Span text=" "/>
                <Span text="bottom" className="bottom" fontSize="12"/>
                <Span text=" "/>
                <Span text="stretch" className="stretch" fontSize="26"/>
                <Span text=" "/>
                <Span text="text-top" className="text-top" fontSize="15"/>
                <Span text=" "/>
                <Span text="text-bottom" className="text-bottom" fontSize="12"/>
                <Span text=" "/>
                <Span text="baseline" className="baseline" fontSize="18"/>
            </FormattedString>
</Label>

But the result looks like this:
Bildschirmfoto 2020-07-22 um 10 30 00


An example with four FontAwesome icons vertical-align center

<Label color="black" backgroundColor="#f5f5f5" fontSize="25" marginTop="20">
            <FormattedString>
                <Span text="&#xf004;" className="fa-regular middle"/>
                <Span text="    "/>
                <Span text="&#xf02e;" className="fa-regular middle"/>
                <Span text="    "/>
                <Span text="&#xf005;" className="fa-regular middle"/>
                <Span text="    "/>
                <Span text="&#xf075;" className="fa-regular middle"/>
            </FormattedString>
</Label>

looks like this:

Bildschirmfoto 2020-07-22 um 10 34 48
Of course making 4 icons with the same size vertical aligned go center makes not much sense, but it should not look like this.


<Label color="black" backgroundColor="#f5f5f5" marginTop="20">
            <FormattedString>
                <Span text="&#xf005;" fontSize="30" className="fa-regular"/>
                <Span text="  "/>
                <Span text="Test" fontSize="15" className="middle"/>
            </FormattedString>
</Label>

Bildschirmfoto 2020-07-22 um 10 42 44


<Label color="black" backgroundColor="#f5f5f5" marginTop="20">
            <FormattedString>
                <Span text="Test" fontSize="30"/>
                <Span text="  "/>
                <Span text="Test" fontSize="15" className="top"/>
            </FormattedString>
</Label>

Bildschirmfoto 2020-07-22 um 10 38 40
The second span should align top, but does not.


When not using a css class for the vertical-alignment and using an inline-style instead, I get a visible effect at least, but still not the expected result.

<Label color="black" backgroundColor="#f5f5f5" marginTop="20">
            <FormattedString>
                <Span text="&#xf005;" fontSize="30" className="fa-regular"/>
                <Span text="  "/>
                <Span text="Test" fontSize="15" style="vertical-align: middle"/>
            </FormattedString>
</Label>

Bildschirmfoto 2020-07-22 um 10 37 12


Do you see a mistake on my side or do you have any working examples?

@felixkrautschuk just started to test this and i see the same issue

I'm also seeing strange behavior with this on android. Example:

Before adding vertical-align: middle:

<Button style="background-color: lightblue;">
    <FormattedString>
        <span [text]="iconStr" class="fas icon--small" style="color: black;background-color: red;"></span>
        <span text="   Go Back" style="background-color: greenyellow;"></span>
    </FormattedString>
</Button>

Result (this is close, but its pretty obvious without the colors that the items aren't vertically aligned together):
image

After adding vertical-align: middle:

<Button style="background-color: lightblue;">
        <FormattedString>
              <span [text]="iconStr" class="fas icon--small" style="color: black;background-color: red;"></span>
              <span text="   Go Back" style="vertical-align: middle;background-color: greenyellow;"></span>
        </FormattedString>
</Button>

Result:
image

On the bright side, having this set on both spans does seem to actually vertically align them relative to each other; it just happens to not be vertically aligned relative to the container:
image

Thinking about it, this seems like such a minor thing but it really adds a lot of polish when this is correct.

So i fixed it in a plugin of mine using a custom span implementation.
The to make it work is to know the maxFontSize used in all the spans. You can see the implemation here https://github.com/nativescript-community/ui-canvaslabel/blob/92bdf9b42ed99748f7bdd816f35d929600f4cb44/src/canvaslabel.android.ts#L39
Though it is not immediately possible to translate that in N spans.
N spans implementation is not the same so someone would need to look at this deeper.

This is still an issue, and it's been one for a few years. The choice is to 1) Have sloppy and unprofessional looking icon/text buttons, 2) Create a component that doesn't inherit from Button, e.g. two labels in a grid, which creates other problems. Seems like it should be pushed up on the priority list.

@mchallenger88 there is another solution. I have a component which handles that perfectly @nativescript-community/ui-canvaslabel
Just dont use it if you want:

  • auto sizing labels
  • clickable span

Thanks @farfromrefug! The benefit of the Button component is that it gives the user immediate feedback through the ripple and the click when it is tapped. That's what I meant when I said the Grid has other problems. Does your component have these?

@mchallenger88 In a sense you can achieve it. Myself use material design. So i use a cardview with a canvaslabel inside. The result is perfect but it mostly works best with a material design

I hadn't thought about using a cardview. I'll look into it. Thank you. :) But, again, why not either have a button that can be configured with both an icon and text, or have a span that can be vertically aligned?

@mchallenger88 you are welcome to implement it. Not that easy

I ended up using the MDRipple component in the community material components package to create a custom button to solve this problem. Basically this, has been working nicely for me:

<MDRipple width="100%" (tap)="onBtnTap()" [nsRouterLink]="nsRouterLink">
    <GridLayout columns="auto,auto" [horizontalAlignment]="alignment">
        <label *ngIf="icon" col="0" class="icon" [icon]="icon"></label>
        <label col="1" class="text" [text]="text"></label>
    </GridLayout>
</MDRipple>

@rbdnar thanks. I have done something similar, I just wish for something a little less verbose. :)

@rbdnar. I just implemented my component with MDRipple and I remember now why I stopped using it. There is a slight delay in the ripple when compared to the ripple in the Button component which is instantaneous. So if you're using both buttons and MDRipple on non-Button components, the user might even be more confused because he sees the instantaneous ripple in some buttons but a delayed one in others. I don't know if you have had the same experience.

@mchallenger88 Interesting. I hadn't noticed that in my application (currently just android). I will certainly keep an eye out since I do have a bit of a mix right now. Thanks!

@mchallenger88 you should not se e that behavior. I would advise you to so it with a cardview . it already has the elevation states you need to simulate a button.
BTW my material button component should have basic icon support. I added it a few weeks back.

@farfromrefug Thank you. I want a simple top bar menu button like the one attached. In this context I don't need elevation but that would be desired in other contexts. Do the revisions to your material button permit an icon side-by-side with text?

Also, I am seeing the same delay on the ripple effect in the CardView that I see applying the MDRipple to a Gridlayout. I could send a short vid if you want to see what I'm seeing. Thanks again.

IconButton

@farfromrefug Is there a similar button for ng? Also, I typically use icon fonts because they are so lightweight and scale with zero effort, which is why vertical span alignment would be so perfect.

@mchallenger88 look at the plugin readme. Now about icon font, not possible yet without that issue fixed (or my canvaslabel version)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

morningrat picture morningrat  路  67Comments

tjvantoll picture tjvantoll  路  58Comments

atanasovg picture atanasovg  路  50Comments

valentinstoychev picture valentinstoychev  路  136Comments

tjvantoll picture tjvantoll  路  46Comments