How to center list items of listview? - xaml

Is there a way to center list items of listview? I want header to take the whole width of page list items to take only a certain amount, for example 800 pixels or 60 percent of the screen, etc. It seems that the list wants that list items width would be the same as list's and it's header. I tried to horizontally center items but it does not work and I do not want to use margins because it kills the performance. Any suggestions?
<Grid>
<ListView HorizontalOptions="FillAndExpand">
<ListView.Header>
<StackLayout HorizontalOptions="Fill"
BackgroundColor="Yellow"
HeightRequest="300">
<Label Text="Header"
FontSize="72"
HorizontalOptions="Center"
VerticalOptions="Center"
TextColor="Black"/>
</StackLayout>
</ListView.Header>
<ListView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>One</x:String>
<x:String>One</x:String>
<x:String>One</x:String>
<x:String>One</x:String>
<x:String>One</x:String>
<x:String>One</x:String>
<x:String>One</x:String>
<x:String>One</x:String>
<x:String>One</x:String>
<x:String>One</x:String>
<x:String>One</x:String>
<x:String>One</x:String>
<x:String>One</x:String>
<x:String>One</x:String>
<x:String>One</x:String>
<x:String>One</x:String>
<x:String>One</x:String>
<x:String>One</x:String>
<x:String>One</x:String>
</x:Array>
</ListView.ItemsSource>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout HorizontalOptions="Center"
WidthRequest="800"
BackgroundColor="Green">
<Label Text="{Binding . }"
HeightRequest="20"
BackgroundColor="DimGray"
HorizontalOptions="Center"
TextColor="Black"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>

You can't make the listview's item really center. But you can make it looks like center.
You can try to make the stacklayout fill the view cell and set the label's background and width to make it looks like center. Such as:
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout HorizontalOptions="Fill">
<Label Text="{Binding . }"
WidthRequest="400"
HeightRequest="20"
BackgroundColor="Pink"
HorizontalOptions="Center"
TextColor="Black"
HorizontalTextAlignment="Center"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
And the result picture:

Related

Carousal view with multiple items without databinding

How do I set static text as Carousal view items instead of doing data binding? Here in the below code I am trying to have Page 2 appear when the user swipes to the left. This code says The property ItemTemplate is set more than once
<StackLayout Margin="10">
<CarouselView>
<CarouselView.ItemTemplate>
<DataTemplate>
<Grid>
<Label Text="Page 1"/>
</Grid>
</DataTemplate>
</CarouselView.ItemTemplate>
<CarouselView.ItemTemplate>
<DataTemplate>
<Grid>
<Label Text="Page 2"/>
</Grid>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</StackLayout>
If you want to set the items statically in xaml itself without data binding you can use Array markup extension of type string:
<StackLayout Margin="10">
<CarouselView>
<CarouselView.ItemsSource>
<x:Array Type="{x:Type sys:String}">
<sys:String>Page 1</sys:String>
<sys:String>Page 2</sys:String>
</x:Array>
</CarouselView.ItemsSource>
<CarouselView.ItemTemplate>
<DataTemplate>
<Grid>
<Label Text="{Binding .}" />
</Grid>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</StackLayout>
PS: Don't forget to add the required xaml namespace:
xmlns:sys="clr-namespace:System;assembly=mscorlib"

Xamarin Style IndicatorView to look like TabbedPage

I have a problem. I recently had this problem: Xamarin forms Add button in TabbedPage, but that is fixed using the accepted anwser. In short, I am using a CarouselView and an IndicatorView, so I can have an overlay over multiple screens. Both the views replace my TabbedPage, but the IndicatorView needs to look like the TabbedPageBar. The only good page about styling an IndicatorView was this one: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/indicatorview.
Here is the page I have:
<StackLayout AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="All"
Padding="0"
Spacing="0">
<IndicatorView x:Name="indicatorView">
<IndicatorView.IndicatorTemplate>
<DataTemplate>
<StackLayout HorizontalOptions="FillAndExpand">
<Frame Margin="10">
<Label/>
</Frame>
</StackLayout>
</DataTemplate>
</IndicatorView.IndicatorTemplate>
</IndicatorView>
<CarouselView ItemTemplate="{StaticResource templateSelector}"
IndicatorView="indicatorView">
<CarouselView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>1</x:String>
<x:String>2</x:String>
<x:String>3</x:String>
</x:Array>
</CarouselView.ItemsSource>
</CarouselView>
</StackLayout>
Now how can I let the IndicatorView look like a TabbedPageBar?
I think the key point here is remove the Shadow and CornerRadius of Frame, then you can customize the layout in the Frame. Here is an example:
<IndicatorView x:Name="indicatorView" >
<IndicatorView.IndicatorTemplate>
<DataTemplate>
<StackLayout HorizontalOptions="FillAndExpand" Spacing="0">
<Frame HasShadow="False" CornerRadius="0">
<StackLayout Orientation="Vertical">
<Image Source="Images"/>
<Label Text="123" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand"/>
</StackLayout>
</Frame>
</StackLayout>
</DataTemplate>
</IndicatorView.IndicatorTemplate>
</IndicatorView>

Keep ListView.Header anchored/sticky/frozen to top when scrolling

How to keep the built-in Header of a ListView frozen to the top when scrolling vertically down through the ListView items?
Before flagging as duplicate: I tried to apply answers in Keep ListView.HeaderTemplate visible/static/sticky in UWP for Xamarin.Forms targeting Android without success.
Short code sample:
<ListView ItemsSource="{Binding MyList}"
HasUnevenRows="True"
SeparatorVisibility="Default"
CachingStrategy="RecycleElement">
<ListView.Header>
<Label HorizontalTextAlignment="Center"
FontAttributes="Bold"
Text="Header Title"/>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding Name}"/>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Here is an alternative approach to this if the list isn't long
<StackLayout>
<Label HorizontalTextAlignment="Center"
FontAttributes="Bold"
Text="Header Title"/>
<StackLayout BindableLayout.ItemsSource="{Binding MyList}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<StackLayout>
<Label Text="{Binding Name}"/>
<!-- boxview as separator -->
<BoxView HeightRequest="1" Color="Aqua" HorizontalOptions="FillAndExpand"/>
</StackLayout>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</StackLayout>

How to set margin around ImageCell in Xamarin.Forms?

I want to have some space around the Image cell items of a ListView:
<StackLayout>
<ListView ItemsSource="{Binding Items}" HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ImageCell Text="{Binding Title}" ImageSource="{Binding Image}" TextColor="Black" DetailColor="Gray"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
but there's no Margin property available for the ImageCell?
EDIT
I did what cvanbeek suggested before posting the question:
<DataTemplate>
<StackLayout Padding="5">
<ImageCell Text="{Binding Title}" ImageSource="{Binding Image}" TextColor="Black" DetailColor="Gray"/>
</StackLayout>
</DataTemplate>
but I got this exception:
Unhandled Exception:
System.InvalidCastException: Specified cast is not valid.
in the OnCreate method in MainActivity.cs
DataTemplate definition
Only View can be put inside DataTemplate, however StackLayout is Layout.
Use a ViewCell instead , it is more flexible and controllable.
<ListView >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="20" Orientation="Horizontal" >
<Label Margin="20" Text="123"/>
<Image Source="Assets/StoreLogo.png"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

Set platform specific control to only one platform in xamarin forms

I have a page that contains a listview and Search bar control. There is a custom listview for android. My code as following:
<ContentPage.Content>
<ContentView>
<OnPlatform x:TypeArguments="View">
<OnPlatform.iOS>
<StackLayout Spacing="0">
<SearchBar x:Name="IosSearch"
Placeholder="Search"
TextChanged="IosSearchBar_OnTextChanged"
SearchButtonPressed="OnSearch" BackgroundColor="#19588F">
</SearchBar>
<ListView x:Name="EmpListViewIos"
ItemsSource="{Binding EmpModel.GroupedItems}"
ItemSelected="OnItemSelected"
SeparatorVisibility="Default">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="8">
<StackLayout Spacing="4" Orientation="Horizontal">
<Label Text="{Binding FullName}" FontSize="15" TextColor="Gray" LineBreakMode="NoWrap"/>
</StackLayout>
<StackLayout Spacing="4" Orientation="Horizontal">
<Label Text="{Binding Department}" FontSize="Small" TextColor="#F68933" LineBreakMode="WordWrap"/>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</OnPlatform.iOS>
<OnPlatform.Android>
<StackLayout x:Name="androidListView">
<SearchBar x:Name="DroidSearch"
Placeholder="Search"
TextChanged="DroidSearchBar_OnTextChanged"
SearchButtonPressed="OnSearch" BackgroundColor="#19588F">
</SearchBar>
<local:CustomListView x:Name="customListView"
Items="{Binding EmpModel.Items}"
VerticalOptions="FillAndExpand" MyListItemSelected="nativeListView_ItemSelected"
SeparatorColor="Black">
</local:MyListView>
</StackLayout>
</OnPlatform.Android>
<OnPlatform.WinPhone>
<StackLayout Spacing="0">
<SearchBar x:Name="WinSearch"
Placeholder="Search"
TextChanged="WinSearchBar_OnTextChanged"
SearchButtonPressed="OnSearch" BackgroundColor="#19588F">
</SearchBar>
<ListView x:Name="EmpListViewWin"
ItemsSource="{Binding EmpModel.GroupedItems}"
ItemSelected="OnItemSelected"
SeparatorVisibility="Default">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="8">
<StackLayout Spacing="4" Orientation="Horizontal">
<Label Text="{Binding FullName}" FontSize="15" TextColor="Gray" LineBreakMode="NoWrap"/>
</StackLayout>
<StackLayout Spacing="4" Orientation="Horizontal">
<Label Text="{Binding Department}" FontSize="Small" TextColor="#F68933" LineBreakMode="WordWrap"/>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</OnPlatform.WinPhone>
</OnPlatform>
</ContentView>
</ContentPage.Content>
</ContentPage>
As the representation of data is different due to that I am required custom listview for android according to it's layout defined. The above code works fine. The only problem is the redundancy, the search bar control is common for all platform but when I put the search bar control above the <ContentView> it doesn't work throws exception. Similarly the ListView is common for ios and windows only there is custom listview for android but I am forced to repeat the code for windows also same as android.
Can anyone suggest a more efficient way to achieve this. How can I apply platform specific condition only for android and common for windows and ios.
You could share the iOS and WinPhone views using a static resource:
<ContentPage>
<ContentPage.ResourceDictionary>
<StackLayout x:Key="iosOrWpView">
...
</StackLayout>
</ContentPage.ResourceDictionary>
<ContentView>
<OnPlatform x:TypeArguments="View" iOS="{StaticResource iosOrWpView}"
WinPhone="{StaticResource iosOrWpView}">
<OnPlatform.Android>
<StackLayout x:Name="androidListView">
...
</StackLayout>
</OnPlatform.Android>
</OnPlatform>
</ContentView>
<ContentPage>