How to wrap Label in FlexLayout - xaml

I am working with Xamarin Cross-platform, my primary target platform is UWP and secondary iOS.
I am trying to use FlexLayout within a ListView which may contain long label texts which I want to wrap within the FlexLayout Basis defined.
Here is the code I have written so far: I am using static data for simplicity, real data will be bonded dynamically.
<ListView.ItemTemplate>
<FlexLayout Direction="Row" Wrap="Wrap" Margin="0,10,0,10">
<StackLayout Orientation="Horizontal" FlexLayout.Basis="300">
<Label Text="1. Label header"/>
<Label Text="Label Value"></Label>
</StackLayout>
<StackLayout Orientation="Horizontal" FlexLayout.Basis="300">
<Label Text="2. Label header"/>
<Label Text="Label Value"></Label>
</StackLayout>
<StackLayout Orientation="Horizontal" FlexLayout.Basis="300">
<Label Text="3.A long Label header"/>
<Label Text="Label Value"></Label>
</StackLayout>
<StackLayout Orientation="Horizontal" FlexLayout.Basis="300">
<Label Text="4.A very loooooong Label header with long value"/>
<Label Text="A long Label Value"></Label>
</StackLayout>
<StackLayout Orientation="Horizontal" FlexLayout.Basis="300">
<Label Text="5. Label header"/>
<Label Text="Label Value"></Label>
</StackLayout>
<StackLayout Orientation="Horizontal" FlexLayout.Basis="300">
<Label Text="6. Label header"/>
<Label Text="Label Value"></Label>
</StackLayout>
<StackLayout Orientation="Horizontal" FlexLayout.Basis="300">
<Label Text="7. Label header"/>
<Label Text="Label Value"></Label>
</StackLayout>
<StackLayout Orientation="Horizontal" FlexLayout.Basis="300">
<Label Text="8. Label header"/>
<Label Text="Label Value"></Label>
</StackLayout>
<StackLayout Orientation="Horizontal" FlexLayout.Basis="300">
<Label Text="9. Label header"/>
<Label Text="Label Value"></Label>
</StackLayout>
<StackLayout Orientation="Horizontal" FlexLayout.Basis="300">
<Label Text="10. Label header"/>
<Label Text="Label Value"></Label>
</StackLayout>
</FlexLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
This produces the following output:
Sample output
We can see that data of fourth stack (4.A very loooooong Label header with long value) is truncated.
But I want my output to be something like this: Desired Output
Things to remember here are:
I want to make maximum use of the space.
I don't prefer to use Wrap Layout.
The data can be of any length and I cannot define a minimum or maximum length of it.
The data is dynamic which will be bound at runtime, used static data here just for simplicity.
Want to have an equal width of every stack in every row, height must change according to data requirements.

I want to make maximum use of the space.
In my understanding, you are utilizing the max space available.
I don't prefer to use Wrap Layout.
Never heard of a wrap layout in xamarin forms but here if you mean you don't want to use LineBreakMode, then that is the only way possible for achieving your requirement.
The data can be of any length and I cannot define a minimum or maximum length of it.
That does not matter much the problem is not with the flex layout but the label setting the labels LineBreakMode property will do the trick
Where ever you feel that the text will be too long add something like this:
<Label ..... LineBreakMode="WordWrap"/>
The data is dynamic which will be bound at runtime, used static data here just for simplicity.
That changes nothing until your XAML is well written it will not behave weirdly
Want to have an equal width of every stack in every row, height must change according to data requirements.
In this case, I would suggest you wrap the StackLayout inside a Grid rather than a FlexLayout and then make the RowDefinitions, set to Auto so they fit themselves as per the need.

Related

First Label within StackLayout wraps to second line when second label is longer than the remaining space

Within a grid I want to display 2 labels next to each other. A static label of "Reason:" and a bound label that displays the reason description, like so;
<StackLayout
Grid.Row="4" Grid.Column="3"
Spacing="0" Orientation="Horizontal" HorizontalOptions="StartAndExpand">
<Label
Text="{i18n:Translate reason}" HorizontalOptions="Start"
HorizontalTextAlignment="Start"
Style="{StaticResource ListSubItemStyle}" Margin="0,0,10,0" />
<Label
Text="{Binding ReasonCodeDescription}" HorizontalOptions="StartAndExpand"
HorizontalTextAlignment="Start" LineBreakMode="TailTruncation"
Style="{StaticResource ListSubItemStyle}" Margin="0,0,0,0" />
</StackLayout>
When the ReasonCodeDescription is longer than the space left on the line it causes the "reason" label to wrap to a new line;
I have tried altering the "spacing", "margin", "padding", "horizontal*" attributes and different "linebreakmode"s to no avail.
I want it to look like the first line albeit with the extra wording truncated;
You have "StartAndExpand" on the wrong label. You have told second label to be "greedy" when there is a conflict. Move that to first label:
<Label Text="{i18n:Translate reason}" HorizontalOptions="StartAndExpand"
<Label Text=... HorizontOptions="Start"
If that doesn't fix, use nested Grid:
<Grid Grid.Row="4" Grid.Column="3" ColumnDefinitions="Auto,*" />
<Label Grid.Column="0" Text="{i18n:Translate reason}" .. />
<Label Grid.Column="1" Text.. />
</Grid>

Why is the Image.Margin in a CollectionView template not creating visual space?

We have a ListView bound to a List of objects of a type called Trial. Each Trial has a property, called Pictures, that is a List of objects of a type, Picture, that represents an image and some metadata. We are using a horizontal CollectionView within the ListView item template to display thumbnails of the images, if any. The problem is in getting a little space between the images. We've tried setting a Margin property value on the Image in the CollectionView item template, but the images are still appearing right next to each other as seen in the illustration.
This is the XAML describing the ListView:
<ListView x:Name="trialsListView"
ItemsSource="{Binding .}"
ItemTapped="Handle_ItemTapped"
CachingStrategy="RecycleElement"
HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="20">
<Label
Text="{Binding Prompt}"
BackgroundColor="{Binding TrialType, Converter={StaticResource TrialTypeToColorConverter}}"
Padding="5" />
<Label Text="{Binding Response}" />
<CollectionView
BindingContext="{Binding Pictures}"
ItemsSource="{Binding .}"
ItemsLayout="HorizontalList"
HeightRequest="{Binding Count, Converter={StaticResource PicturesCountToHeightConverter}}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Image
HeightRequest="80"
Source="{Binding PictureName, Converter={StaticResource PictureNameToImageSourceConverter}}"
Margin="10" />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
And this is an example of output (from an iOS device):
I suppose we can enclose the Image in a Frame or some layout, but that feels like a 90s web hack. Surely there is a right way to get some spacing without resorting to adding screen elements? What do I not yet understand here?

Using TextCell in a StackLayout in a ListView

Why can I not use a TextCell like this in a ListView item template? When I use it the rows render but they are empty.
<ListView ItemsSource="{Binding Courses}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Vertical">
<TextCell Text="{Binding Title}" Detail="{Binding SubTitle}"></TextCell>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
When using a Label I can see the text contents in each row:
<ListView ItemsSource="{Binding Courses}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Vertical">
<Label Text="{Binding Title}"></Label>
<Label Text="{Binding SubTitle}"></Label>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Is there anyway I can use the TextCell inside the list item template? I am trying to build a more complext layout inside the StackLayout and it would be greatly simplified if I could re-use the Title/Detail structure of the TextCell.
According to the Xamarin.Forms Cell Reference, cells are only designed to be added to ListViews or TableViews. In particular, it says:
However Cell is not a visual element, it just describes a template for
creating a visual element.
So it cannot be added directly to the children of a StackLayout. You will have to create a ViewCell with a custom template for that.. You can probably look at the source code on Github to find out the proper spacing that a TextCell uses between it's Text and TextDetail labels, to keep it consistent.
You Can Use Stack Layout in a text cell!
Here is the way for using it.
<TextCell>
<TextCell.BindingContext>
<StackLayout Orientation="Horizontal" >
<Label Text="{Binding Name}"
HorizontalOptions="CenterAndExpand" TextColor="Black"/>
<Label Text="{Binding Description}"
HorizontalOptions="CenterAndExpand" TextColor="Black"/>
<Label Text="{Binding Price}"
HorizontalOptions="CenterAndExpand" TextColor="Black"/>
</StackLayout>
</TextCell.BindingContext>
</TextCell>

Add shadow to a Label - Xamarin.Forms

I would like to add drop shadow to a Label. This label is overlapped in the Page, like an always visible control that opens a filtering page.
Please find a gif attached with my screen:
Here's my XAML:
<!-- **** Filter button **** -->
<Label
Margin="0,0,10,10"
WidthRequest="50"
HeightRequest="50"
HorizontalOptions="End"
VerticalOptions="End"
HorizontalTextAlignment="Center"
VerticalTextAlignment="Center"
FontSize="30"
Style="{DynamicResource FilterAction}"
Text=""
BackgroundColor="{StaticResource ComplementColor}"
FontFamily="{x:Static artina:FontAwesome.FontName}"
TextColor="White">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding btn_open_filter_businesses_click}" />
</Label.GestureRecognizers>
</Label>
<templates:Badge
BadgeText="{Binding number_of_filters_selected}"
BadgeTextColor="White"
BadgeBackgroundColor="#1DBDFF"
HorizontalOptions="End"
VerticalOptions="End"
TranslationX="-4"
TranslationY="-4"
IsVisible="{Binding number_of_filters_selected, Converter={StaticResource filterVis}"
x:Name="filtersCountBagde">
<templates:Badge.GestureRecognizers>
<TapGestureRecognizer Command="{Binding btn_open_filter_businesses_click}" />
</templates:Badge.GestureRecognizers>
</templates:Badge>
I would like something like Gmail, find the example below:
Any help would be appreciated.
You can use Xamarin Effects to achieve a shadow on your button. There is a code sample that you can download here which should get you started:
Shadow Effect
It will involve creating platform-specific implementations for your shadow.
You could also try the idea put forward in this similar question.

Xamarin.Forms Vertical StackLayout in ListView displays only one (first) Child

<ListView
ItemsSource="{Binding Messages}"
Grid.ColumnSpan="2"
HeightRequest="100">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout>
<Label
Text="{Binding When}"
XAlign="Center"/>
<StackLayout
BackgroundColor="Gray"
Orientation="Vertical"
VerticalOptions="Center">
<Label
Text="{Binding Message}"
XAlign="Start"/>
<Label
Text="{Binding Sender}"
XAlign="Start"
TextColor="Red"/>
</StackLayout>
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I am rendering a custom ListView in Xamarin.Forms application. The StackLayout which contains two Labels (to which "Message" and "Sender" has been bound), currently displays only one child. With the code above, it displays only "Message". If I change code to be
<StackLayout
BackgroundColor="Gray"
Orientation="Vertical"
VerticalOptions="Center">
<Label
Text="{Binding Sender}"
XAlign="Start"
TextColor="Red"/>
<Label
Text="{Binding Message}"
XAlign="Start"/>
</StackLayout>
it displays only sender. In short it is displaying only first child. What have I done wrong here ?
Issue was similar to what #Grisha had pointed out. RowHeight was proving to be lesser, and the second StackLayout was getting clipped.
The solution was to set HasUnevenRows property of the ListView to be TRUE. Thus, RowHeight was calculated automatically.