I am trying to make a label wrap inside of the Master page of a MasterDetail page. I thought it was the default behavior to wrap labels, but just in case I even made a custom renderer. I have confirmed that the custom renderer works (through debugging and adding a background to the label), so I assume there is something easy that I am missing. Can anybody take a look at my xaml and give me an idea why this label is not wrapping?
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyApp.Pages.NavigationDrawer.NavigationMenuMasterPage"
xmlns:statics="clr-namespace:MyApp.Statics;assembly=MyApp"
xmlns:multi="clr-namespace:MyApp.Pages.NavigationDrawer;assembly=MyApp"
Title="Navigation drawer"
Icon="hamburger.png"
BackgroundColor="White">
<ContentPage.Content>
<StackLayout VerticalOptions="FillAndExpand" HorizontalOptions="Center" Margin="0, 25, 0, 0">
<StackLayout Orientation="Horizontal" HorizontalOptions="Center">
<Image x:Name="connectionStatusImage" />
<Label x:Name="connectionStatusText" Margin="16, 0, 16, 0" YAlign="Center" FontSize="Medium"/>
</StackLayout>
<Label x:Name="changeConnectionStatusButton" TextColor="{x:Static statics:Palette.Orange}" XAlign="Center" FontAttributes="Bold" >
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="ChangeConnectionStatusClicked" NumberOfTapsRequired="1" />
</Label.GestureRecognizers>
</Label>
<StackLayout x:Name="SyncStatusStack" Orientation="Horizontal" Margin="0, 16, 16, 0" VerticalOptions="Center" >
<multi:MultiLineLabel x:Name="syncStatusText" MinimumWidthRequest="0" Margin="16, 0, 0, 0" Text="I want to write a really long string to see if it wraps" />
<Label x:Name="syncButton" MinimumWidthRequest="40" Text="SYNC" FontAttributes="Bold" YAlign="Center" HorizontalOptions="End" >
<Label.GestureRecognizers>
<TapGestureRecognizer x:Name="SyncGestureRecognizer" NumberOfTapsRequired="1" />
</Label.GestureRecognizers>
</Label>
</StackLayout>
<StackLayout x:Name="SyncStack" Orientation="Vertical" HorizontalOptions="Center" Margin="0, 16, 0, 0">
<ActivityIndicator x:Name="syncingIndicator" Margin="16, 0, 32, 0"/>
<Label x:Name="syncingText" />
</StackLayout>
<ListView x:Name="menuListView" VerticalOptions="FillAndExpand" SeparatorVisibility="None" Margin="0, 16, 0, 0">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Title}" TextColor="{x:Static statics:Palette.PrimaryText}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
And my (most likely unnecessary) custom label renderer:
using MyApp.iOS.Renderers;
using MyApp.Pages.NavigationDrawer;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(MultiLineLabel), typeof(MultiLineLabeliOSRenderer))]
namespace MyApp.iOS.Renderers
{
public class MultiLineLabeliOSRenderer : LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if (Control == null) return;
Control.LineBreakMode = UIKit.UILineBreakMode.WordWrap;
Control.Lines = 0;
}
}
}
Hmm not sure why, but you are correct setting lines to 0 and using word wrap should do the trick ( Multiple lines of text in UILabel )
I recently also implemented this with a custom renderer ( http://depblog.weblogs.us/2016/06/27/xamarin-forms-multi-line-label-custom-renderer-gotcha/ ) and used a number to indicate the exact amount of lines I would like to have.
That is being set into the Lines property and then the wrapping works.
Related
I am trying to disable scrolling in my collection view. The reason why I want to do that is there is a scroll view already in my XAML code. When I try to scroll all page elements on the page, collection view elements are also scrolled themselves but I don't want that.
<ScrollView>
<StackLayout Padding="20" Spacing="20" >
<Frame CornerRadius="15"
BackgroundColor="#A6EDB3"
VerticalOptions="StartAndExpand"
HeightRequest="200"
IsClippedToBounds="True"
Padding="0" >
<StackLayout Padding="10,5,10,5"
Orientation="Horizontal" >
<Image Source="settingsIcon"
HeightRequest="25"
WidthRequest="25"
Aspect="Fill" />
<Label Text="Filter"
FontSize="Medium"
VerticalTextAlignment="Center"
VerticalOptions="Center"/>
</StackLayout>
</Frame>
<Label Text="Vocabulary topics" TextColor="black" FontSize="20" FontAttributes="Bold" ></Label>
<CollectionView x:Name="topics" Scrolled="topics_Scrolled" VerticalScrollBarVisibility="Never" >
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Padding="0,10,0,10">
<Frame HasShadow="False"
HeightRequest="60"
CornerRadius="15"
BackgroundColor="{Binding BackgroundColor}"
HorizontalOptions="Fill" >
<StackLayout Orientation="Horizontal">
<Frame BackgroundColor="{Binding BoxColor}" WidthRequest="40" ></Frame>
<StackLayout>
<Label Text="{Binding Name}"></Label>
</StackLayout>
</StackLayout>
</Frame>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</ScrollView>
Having two scrolls on the same page is not the correct way.
Also if you just want to place items above/below your collectionView use the Header/Footer properties then!!
For instance, for the current design, your CollectionView could look something like below and work as you want it to.
<CollectionView Padding="20" x:Name="topics" Scrolled="topics_Scrolled" VerticalScrollBarVisibility="Never" >
<CollectionView.Header>
<StackLayout Spacing="20" >
<Frame CornerRadius="15"
BackgroundColor="#A6EDB3"
VerticalOptions="StartAndExpand"
HeightRequest="200"
IsClippedToBounds="True"
Padding="0" >
<StackLayout Padding="10,5,10,5"
Orientation="Horizontal" >
<Image Source="settingsIcon"
HeightRequest="25"
WidthRequest="25"
Aspect="Fill" />
<Label Text="Filter"
FontSize="Medium"
VerticalTextAlignment="Center"
VerticalOptions="Center"/>
</StackLayout>
</Frame>
<Label Text="Vocabulary topics" TextColor="black" FontSize="20" FontAttributes="Bold" ></Label>
</StackLayout>
</CollectionView.Header>
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Padding="0,10,0,10">
<Frame HasShadow="False"
HeightRequest="60"
CornerRadius="15"
BackgroundColor="{Binding BackgroundColor}"
HorizontalOptions="Fill" >
<StackLayout Orientation="Horizontal">
<Frame BackgroundColor="{Binding BoxColor}" WidthRequest="40" ></Frame>
<StackLayout>
<Label Text="{Binding Name}"></Label>
</StackLayout>
</StackLayout>
</Frame>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
Note: you might have to adjust the margin and padding properties for it to look the exact same. My code is just an example.
For more information on CollectionView check: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/collectionview/
You can use InputTransparent.
In your case what I would do would be to wrap the CollectionView in a <ContentView> as:
<ContentView InputTransparent="True"
x:Name="content">
<CollectionView ItemsSource="{Binding Items}"...>
...
</CollectionView>
</ContentView>
Create a scroll event to your scroll view:
<ScrollView Scrolled="ScrollView_Scrolled">
...
</ScrollView>
Then, with this event, make sure that the InputTransparent switches depending on the scroll position:
private void ScrollView_Scrolled(object sender, ScrolledEventArgs e)
{
var scrollView = sender as ScrollView;
// Get the height of your scroll view
var contentSize = scrollView.ContentSize.Height;
// Get the max position of the scrollview
var maxPos = contentSize - scrollView.Height;
// Compare it to the current position
if (Convert.ToInt16(e.ScrollY) >= Convert.ToInt16(maxPos))
{
// Switch input transparent value
content.InputTransparent = false;
}
else if (Convert.ToInt16(e.ScrollY) == 0)
{
content.InputTransparent = true;
}
}
This is perfectly fine to use two scrollable controls on the same page for what you want to do. And I don't think <CollectionView.Header> would give you the result you want.
I hope it was helpful! 🙂
I am trying to add an Indicator View style dots to my CarouselPage; However, the documentation I have found only shows how to use the new IndicatorView with CarouselView.
Is there anyway to use it with CarouselPage instead? If not, Is there anything similar to IndictorView that's used for CarouselPage? Here's my code:
<?xml version="1.0" encoding="utf-8"?>
<CarouselPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="Page.MainPage">
<ContentPage>
<StackLayout Padding="0,20,0,0">
<Image Source="LOGO.png"
HorizontalOptions="Center"
VerticalOptions="Center"
HeightRequest="195"
WidthRequest="205"
/>
<AbsoluteLayout HorizontalOptions="Center" VerticalOptions="Center">
<Image Source="bg.png"
AbsoluteLayout.LayoutBounds="0.35, 0.6, -1, 1"
AbsoluteLayout.LayoutFlags="PositionProportional"
HeightRequest="330"
WidthRequest="200"/>
<Image Source="Device.png"
AbsoluteLayout.LayoutBounds="0.45, 0.4, -1, -1"
AbsoluteLayout.LayoutFlags="PositionProportional"
HeightRequest="252"
WidthRequest="290"/>
</AbsoluteLayout>
<StackLayout>
<Label Text="Welcome"
HorizontalTextAlignment="Center"
VerticalTextAlignment="Center"
TextColor="White"
Padding="0,15"
Font="Bold,20"/>
<Label Text="This is page 1"
HorizontalTextAlignment="Center"
VerticalTextAlignment="Center"
FontSize="18"
Padding="25,0"
TextColor="White"/>
</StackLayout>
</StackLayout>
</ContentPage>
<ContentPage BackgroundColor="#3e454d">
<StackLayout BackgroundColor="#3e454d">
<AbsoluteLayout>
<Image Source="Map.png"
AbsoluteLayout.LayoutBounds="0.4, 0.7, -1, -1"
AbsoluteLayout.LayoutFlags="PositionProportional"
HeightRequest="330"
WidthRequest="205"/>
<Image Source="Device.png"
AbsoluteLayout.LayoutBounds="0.45, 0.7, -1, -1"
AbsoluteLayout.LayoutFlags="PositionProportional"
HeightRequest="282"
WidthRequest="340"/>
</AbsoluteLayout>
<StackLayout Padding="10,10">
<Label Text="Join US"
TextColor="White"
Padding="0,0,0,15"
Font="Bold,22"/>
<Label Text="This is Page 2"
HorizontalTextAlignment="Center"
FontSize="18"
TextColor="White"/>
</StackLayout>
</StackLayout>
</ContentPage>
</CarouselPage>
Use CarouselView instead of CarouselPage , embedd CarouselPage.Content to CarouselView.ItemLayout as mentioned in the documentation
Note that IndicatorView is different view, its not embedded in CarouselPage , even in CarouselView , you have to give the binding reference to CarouselView in order for it to work.
Also note that IndicatorView is still in Preview mode you need to set the experimental flag in order to make it work
Forms.SetFlags("IndicatorView_Experimental");
Also its showing Carouselview is in preview too(It was not, weird!)
so you may have to set experimental flag for that as well
Forms.SetFlags("CarouselView_Experimental");
I just can't understand why the background for my side menu on xamarin forms won't render the same on my xamarin.ios. Yet in other parts of the project my list views render and look the same when I use transparent backgrounds, I even tried copying and pasting the xaml code from other parts of the project where it does render the same, but still it does not work. In case anyone's wondering the side menu on ios was requested by the client.
Attached below I have 2 images showing how the side menu renders differently on the 2 platforms
Here's the Xaml code I'm using for my Side Menu:
<MasterDetailPage.Master>
<StackLayout Orientation="Vertical" BackgroundColor="Transparent" Spacing="0">
<StackLayout
HorizontalOptions="Fill"
Orientation="Horizontal"
VerticalOptions="Fill" BackgroundColor="Black" Padding="50, 50, 50, 50">
<StackLayout HorizontalOptions="Center" Orientation="Vertical">
<ffimageloading:CachedImage x:Name="ProfilePictureCircleImage"
LoadingPlaceholder="profile_image_placeholder.png"
ErrorPlaceholder="profile_image_placeholder.png"
DownsampleToViewSize="true"
FadeAnimationEnabled="true"
HeightRequest="65"
WidthRequest="65">
<ffimageloading:CachedImage.Transformations>
<fftransformations:CircleTransformation/>
</ffimageloading:CachedImage.Transformations>
</ffimageloading:CachedImage>
</StackLayout>
<StackLayout
HorizontalOptions="CenterAndExpand"
Orientation="Vertical"
VerticalOptions="CenterAndExpand">
<Label
x:Name="FullNameLabel"
FontSize="18"
HorizontalOptions="Center"
TextColor="White"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</StackLayout>
<BoxView HeightRequest="2" BackgroundColor="#D90B31"/>
<ListView
x:Name="NavigationMenuItems"
ItemSelected="OnMenuItemSelected"
BackgroundColor="{StaticResource TileColour}"
RowHeight="60"
SeparatorVisibility="None"
SeparatorColor="Transparent">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<!-- Main design for menu items -->
<StackLayout
Padding="20,10,0,10"
Orientation="Horizontal"
Spacing="20"
VerticalOptions="FillAndExpand"
BackgroundColor="Transparent">
<local:TintedCachedImage TintColor="{StaticResource SideMenuIconColor}"
Source="{Binding Icon}"
VerticalOptions="Center"
DownsampleToViewSize="true"
HeightRequest="19"
WidthRequest="19"/>
<Label
FontSize="15"
Text="{Binding Title}"
TextColor="{StaticResource SideMenuTextColor}"
VerticalOptions="Center" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
<NavigationPage />
</MasterDetailPage.Detail>
above are pictures illustrating how it looks across the 2 platforms.
Found the solution to this question on another stackoverflow thread I had to use a custom renderer:
public class CustomSideMenuRenderer: TabletMasterDetailRenderer
{
public override void ViewWillLayoutSubviews()
{
base.ViewWillLayoutSubviews();
var master = ViewControllers[0];
master.View.BackgroundColor = UIColor.Clear;
var detail = ViewController.ChildViewControllers[1];
}
}
I am not sure whether this is my problem or a problem with Xamarin.
On an iPad my application can load the page which contain a list of data in ListView.
The View Cell inside the ListView can be slightly complex. It contains a profile image, some smaller icons using, which are using FFImageLoading.
On iPad, when I tap a cell of the first page to go into the next page, which contains a list of data, it loads very smoothly.
On Android, when I tap on a cell to go into the next page, the detection of the tap is slow and the loading time of the ListView also very slow.
Is there anyway enhance the performance? I thought it was the data I loaded from SQLite. However, after I comment out the ItemsSource on ListView, the loading time is fine.
This is the datatemplate I've used for displaying the cell.
<ViewCell>
<ViewCell.View>
<StackLayout Spacing="0" Padding="0" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<StackLayout Orientation="Horizontal" Spacing="10" Padding="0" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<StackLayout Orientation="Horizontal" HorizontalOptions="StartAndExpand">
<controls:CircleImage
Style="{StaticResource profileImageStyle}"
Margin="10, 10, 10, 10"
Source="{Binding Source}"
BorderColor="White"
BorderThickness="2"
VerticalOptions="Center"
HorizontalOptions="Center">
<controls:CircleImage.GestureRecognizers>
<TapGestureRecognizer Tapped="OnChildDetailTapped" />
</controls:CircleImage.GestureRecognizers>
</controls:CircleImage>
<StackLayout VerticalOptions="Fill" Spacing="1" Padding="0,20,0,10" HorizontalOptions="StartAndExpand">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Tapped="OnChildDetailTapped" />
</StackLayout.GestureRecognizers>
<StackLayout
Orientation="Vertical"
VerticalOptions="Center"
HorizontalOptions="StartAndExpand">
<Label x:Name="childName" Text="{Binding DisplayName}" Style="{StaticResource normalFont}"> </Label>
<local:ChildInfoIconsView
Child="{Binding .}"
VerticalOptions="Fill">
</local:ChildInfoIconsView>
<Label
x:Name="childNotes"
Style="{StaticResource footnoteFont}"
Text="{Binding ChildNotes, StringFormat={x:Static local:AppResources.formatNotes}}"
IsVisible="{Binding HasChildNotes}">
</Label>
<Label
x:Name="noPickupReason"
Style="{StaticResource footnoteFont}"
Text="{Binding NoPickupReason, StringFormat={x:Static local:AppResources.formatNoPickupReason}}"
IsVisible="{Binding HasNoPickupReason}">
</Label>
<Label
x:Name="absentReason"
Style="{StaticResource footnoteFont}"
Text="{Binding AbsentReason, StringFormat={x:Static local:AppResources.formatAbsentReason}}"
IsVisible="{Binding HasAbsentReason}">
</Label>
</StackLayout>
</StackLayout>
</StackLayout>
<StackLayout Orientation="Horizontal" VerticalOptions="FillAndExpand" HorizontalOptions="End">
<StackLayout.Padding>
<OnIdiom x:TypeArguments="Thickness">
<OnIdiom.Phone>5, 20, 10, 20</OnIdiom.Phone>
<OnIdiom.Tablet>10, 30, 30, 30</OnIdiom.Tablet>
</OnIdiom>
</StackLayout.Padding>
<Image
Style="{StaticResource listviewButtonStyle}"
IsVisible="{Binding EnabledSigning, Source={x:Reference page}}"
Source="ic_action_yes.png"
VerticalOptions="FillAndExpand"
HorizontalOptions="End">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="OnAttend" />
</Image.GestureRecognizers>
<Image.Margin>
<OnIdiom x:TypeArguments="Thickness">
<OnIdiom.Phone>0, 0, 5, 0</OnIdiom.Phone>
<OnIdiom.Tablet>5, 5, 20, 5</OnIdiom.Tablet>
</OnIdiom>
</Image.Margin>
</Image>
<Image
Style="{StaticResource listviewButtonStyle}"
IsVisible="{Binding EnabledSigning, Source={x:Reference page}}"
Source="ic_action_no.png"
VerticalOptions="FillAndExpand"
HorizontalOptions="End">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="OnAbsent" />
</Image.GestureRecognizers>
<Image.Margin>
<OnIdiom x:TypeArguments="Thickness">
<OnIdiom.Phone>5, 0, 0, 0</OnIdiom.Phone>
<OnIdiom.Tablet>20, 5, 5, 5</OnIdiom.Tablet>
</OnIdiom>
</Image.Margin>
</Image>
</StackLayout>
</StackLayout>
</StackLayout>
</ViewCell.View>
</ViewCell>
Try setting a listview caching strategy to improve performance.
See here for more details
Be aware though that you may need to jump through some hoops to use RecycleElement with FFImageLoading. The issue is described here
Also, please post your data template so we can see if it can be simplified.
Use RecyclerView
https://blog.xamarin.com/recyclerview-highly-optimized-collections-for-android-apps/
OR
Use FFImageLoading
https://github.com/luberda-molinet/FFImageLoading
to optimize and for smoother scroll
Does anyone know if it's possible to create a CardView style (scrollable) list using Xamarin.Forms? We need it to render same on both iOS and Android. Also need to tweak properties like the shadow (to slightly raise each card)
Here is a nuget: https://github.com/tiger4589/Xamarin.Forms-CardView
Cardview control in Xamarin.Froms.
Install it in your shared project only and use the following import in your page's xaml:
xmlns:cardView="clr-namespace:CardView;assembly=CardView"
Just use the control in viewcell of your listview.
Example screenshot: each card is a row in listview
Following code is an usage example of above control:
<ListView
x:Name="listView"
Margin="0,8,0,0"
HasUnevenRows="True"
ItemTapped="Handle_ItemTapped"
ItemsSource="{Binding HouseholdDetail}"
SeparatorVisibility="None">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="8,8,8,8" Orientation="Vertical">
<cardView:CardView
BackgroundColor="White"
CardViewHasShadow="True"
HeightRequest="220">
<cardView:CardView.CardViewContent>
<StackLayout
Padding="10"
HorizontalOptions="Center"
Spacing="10"
VerticalOptions="Center">
<Image HeightRequest="96" Source="{Binding Image}" />
<BoxView
HeightRequest="1"
WidthRequest="275"
Color="LightGray" />
<Grid>
<Label
Grid.Row="0"
Grid.Column="0"
Margin="15,0,0,0"
FontSize="Medium"
Text="{Binding FullName}" />
<Label
Grid.Row="0"
Grid.Column="1"
Margin="0,0,15,0"
FontSize="Medium"
HorizontalTextAlignment="End"
Text="{Binding Relation}" />
</Grid>
<BoxView
HeightRequest="1"
WidthRequest="275"
Color="LightGray" />
<Grid>
<Label
Grid.Row="0"
Grid.Column="0"
Margin="15,0,0,0"
FontSize="Medium"
Text="{Binding LeavesAt}" />
<Label
Grid.Row="0"
Grid.Column="1"
Margin="0,0,15,0"
FontSize="Medium"
HorizontalTextAlignment="End"
Text="{Binding ArrivesAt}" />
</Grid>
</StackLayout>
</cardView:CardView.CardViewContent>
</cardView:CardView>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Here you may notice the freedom you have such as you can define to have shadow or not and design the whole layout of cardview using Xamarin default layouts.
Why not use a frame? i am put inside at the listview, a frame with grid.
and do something like this to get the style cardview you like.
public class CardView : Frame
{
public CardView()
{
if (Device.OS == TargetPlatform.iOS)
{
HasShadow = false;
OutlineColor = Color.Transparent;
BackgroundColor = Color.Transparent;
}
if (Device.OS == TargetPlatform.Android)
{
HasShadow = true;
OutlineColor = Color.Transparent;
BackgroundColor = Color.Transparent;
}
}
}
No need Third party library
it is support scrollable and pullrefresh
<StackLayout>
<ListView x:Name="ItemsListView"
ItemsSource="{Binding Items}"
VerticalOptions="FillAndExpand"
HasUnevenRows="true"
RefreshCommand="{Binding LoadItemsCommand}"
IsPullToRefreshEnabled="true"
IsRefreshing="{Binding IsBusy, Mode=OneWay}"
CachingStrategy="RecycleElement"
ItemSelected="OnItemSelected">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="10">
<Frame HasShadow="True" >
<StackLayout>
<Label Text="{Binding Text}"
LineBreakMode="NoWrap"
FontSize="16" />
<Label Text="{Binding Description}"
LineBreakMode="NoWrap"
FontSize="16" />
</StackLayout>
</Frame>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>