Nativescript: Make label span width of its content, then wrap at a max width

davecoffin picture davecoffin · Aug 30, 2016 · Viewed 8.7k times · Source

I am trying to create a messaging view with a layout similar to iMessage, where a chat "bubble" is the size of its content, until it gets to be a certain width. Like this: screenshot

With nativescript, I cant find a layout that will accommodate this. I tried using GridLayout, but the auto nature of the column appears to mean that it will be the size of the content, even if the content's size expands beyond the view.

<GridLayout width="100%" columns="40, auto" rows="auto, 20" class="msg them" visibility="{{is_me ? 'collapsed' : 'visible'}}">
    <Image class="authorimg" col="0" stretch="aspectFill" verticalAlignment="top" src="{{user.profile_photo ? user.profile_photo.sizes.tiny_square : ''}}" />
    <StackLayout class="msg_text" col="1">
        <Label text="{{message}}" textWrap="true" verticalAlignment="top" />
    </StackLayout>
    <Label class="msg_timestamp" text="{{author}}" verticalAlignment="top" row="1" colSpan="2" />
</GridLayout>

That produces this: screenshot

Notice the longer ones dont wrap, despite textWrap=true on the Label.

The other side of the coin is this:

<GridLayout width="100%" columns="40, *" rows="auto, 20" class="msg them" visibility="{{is_me ? 'collapsed' : 'visible'}}">
    <Image class="authorimg" col="0" stretch="aspectFill" verticalAlignment="top" src="{{user.profile_photo ? user.profile_photo.sizes.tiny_square : ''}}" />
    <StackLayout class="msg_text" col="1">
        <Label text="{{message}}" textWrap="true" verticalAlignment="top" />
    </StackLayout>
    <Label class="msg_timestamp" text="{{author}}" verticalAlignment="top" row="1" colSpan="2" />
</GridLayout>

The only difference being the columns in the gridlayout, in this case its set to * (use the rest of the available area). That however, produces this:

screenshot

Notice that the shorter messages span the whole width. I need something similar to width="auto" on the Label I guess. I cant figure out a layout that will accommodate the best of both implementations, small bubbles for little text, and wrapping bubbles for long text.

Answer

Tsvetan picture Tsvetan · Sep 1, 2016

using StackLayout will do the job:

<StackLayout>
  <StackLayout orientation="horizontal" style="padding: 5">
    <Image src="~/res/logo.png" width="50" height="50" verticalAlignment="top"/>
    <Label text="I am a message" textWrap="true" backgroundColor="red" />
  </StackLayout>
  <StackLayout orientation="horizontal" style="padding: 5">
    <Image src="~/res/logo.png" width="50" height="50" verticalAlignment="top"/>
    <Label text="This is a longer message, which is worth adding because then I can make sure that longer messages display properly in the messages view! They need to wrap, obviously!" backgroundColor="red" textWrap="true" />
  </StackLayout>
</StackLayout>

You should have in mind that layouts are not virtualized. This will make your app slow when there are large conversations. You can use list view instead.