Cross platform listview swipe in xamarin forms - xamarin

I am looking for a cross platform swipe on ListView to perform an action such as opening a menu or deleting an item.
Has anyone implemented such a scenario? I would like to for instance delete an item when swiping on item to left.
I need to support all platforms: ios/droid/win

The easiest way would be to use the built-in Context Actions, this allows you to show menu items when your list item is swiped on iOS or long pressed on Android
<ListView x:Name="ContextDemoList">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.ContextActions>
<MenuItem Clicked="OnMore" CommandParameter="{Binding .}"
Text="More" />
<MenuItem Clicked="OnDelete" CommandParameter="{Binding .}"
Text="Delete" IsDestructive="True" />
</ViewCell.ContextActions>
<StackLayout Padding="15,0">
<Label Text="{Binding title}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
https://developer.xamarin.com/guides/xamarin-forms/user-interface/listview/interactivity/#Context_Actions
If swiping is a requirement for both platforms, or you need to do an action when the item is swiped (Instead of showing menu items) then i'd recommend SyncFucion's listview control, it is available with a Community licence and it offers more flexibility
<syncfusion:SfListView x:Name="listView" AllowSwiping="True">
<syncfusion:SfListView.LeftSwipeTemplate>
<DataTemplate x:Name="LeftSwipeTemplate">
<Grid>
<Grid BackgroundColor="#009EDA" HorizontalOptions="Fill" VerticalOptions="Fill" Grid.Column="0">
<Grid VerticalOptions="Center" HorizontalOptions="Center">
<Image Grid.Column="0"
Grid.Row="0"
BackgroundColor="Transparent"
HeightRequest="35"
WidthRequest="35"
Source="Favorites.png" />
</Grid>
</Grid>
</Grid>
</DataTemplate>
</syncfusion:SfListView.LeftSwipeTemplate>
</syncfusion:SfListView>
https://help.syncfusion.com/xamarin/sflistview/swiping

You can use SwipeView and wrap it in a ListView.
<ListView
ItemsSource="{Binding Items}"
SelectionMode="None"
CachingStrategy="RecycleElement"
RowHeight="110"
HeightRequest="1000"
BackgroundColor="White"
IsPullToRefreshEnabled="True"
Refreshing="OnRefresh">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<SwipeView>
<SwipeView.GestureRecognizers>
<TapGestureRecognizer
Tapped="OnTapped"
NumberOfTapsRequired="1" />
</SwipeView.GestureRecognizers>
<SwipeView.RightItems>
<SwipeItems>
<SwipeItem
Text="Edit"
IconImageSource="edit_icon.png"
BackgroundColor="Green"
Invoked="OnEdit" />
<SwipeItem
Text="Delete"
IconImageSource="delete_icon.png"
BackgroundColor="Red"
Invoked="OnDelete" />
</SwipeItems>
</SwipeView.RightItems>
<SwipeView.Content>
:
</SwipeView.Content>
</SwipeView>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
From: https://github.com/xamarin/Xamarin.Forms/issues/9089

Related

Separator Lines in Xamarin Forms ListView are only between items on iOS

I have a Xamarin Forms Listview with a GroupHeader:
<ListView x:Name="listView"
ios:ListView.SeparatorStyle="FullWidth"
AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="All"
ItemsSource="{Binding Items}"
IsGroupingEnabled="true"
SeparatorVisibility="Default"
IsPullToRefreshEnabled="False"
SeparatorColor="Red"
SelectionMode="None"
Footer=""
BackgroundColor="Transparent">
<ListView.GroupHeaderTemplate>
<DataTemplate>
<TextCell Text="Header Cell"/>
</DataTemplate>
</ListView.GroupHeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="Item Cell"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
On iOS the separator line (red) is only visible between the items, but not between header and items:
On Android the line is also between Header and items:
I only found some suggestions to remove the separator lines on iOS (Setting SeparatorColor transparent).
How can i get the android behavior on iOS?
You can use BoxView to achieve the effect you want, modify your code as follows:
<ListView x:Name="listView"
AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="All"
ItemsSource="{Binding Items}"
IsGroupingEnabled="True"
SeparatorVisibility="None"
SelectionMode="None"
Footer=""
BackgroundColor="Transparent">
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<Label Text="Header Cell" Margin="0,10,0,0"/>
<BoxView HeightRequest="0.5" Color="Red" HorizontalOptions="FillAndExpand" Margin="0,8,0,0"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<Label Text="Item Cell" Margin="0,10,0,0"/>
<BoxView HeightRequest="0.5" Color="Red" HorizontalOptions="FillAndExpand" Margin="0,5,0,0"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

Xamarin Forms CollectionView Last item not showing properly

I have a simple horizontal CollectionView which works fine except that the last item is not showing properly and i have to force scroll it to see it.
I tried all kinds of padding and margins but the only property that will make it show is if make ItemSpacing="20" or bigger. The problem is that, if i added more items, the issue still will show again and this is a dynamic list.
this is the code for the stacklayout under the content page directly.
<StackLayout VerticalOptions="Center" HorizontalOptions="FillAndExpand">
<StackLayout BackgroundColor="LightGray" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" >
<CollectionView HeightRequest="40" VerticalOptions="Fill" HorizontalOptions="Fill" Margin="5" >
<CollectionView.ItemsLayout>
<LinearItemsLayout Orientation="Horizontal" ItemSpacing="10"/>
</CollectionView.ItemsLayout>
<CollectionView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>Open (Item)</x:String>
<x:String>Side Menu</x:String>
<x:String>How to?</x:String>
<x:String>Back/Cancel</x:String>
<x:String>Logout</x:String>
<x:String>Yes/No</x:String>
<x:String>App Info</x:String>
</x:Array>
</CollectionView.ItemsSource>
<CollectionView.ItemTemplate>
<DataTemplate>
<Frame BackgroundColor="White" BorderColor="DarkCyan" CornerRadius="20" HasShadow="False" Padding="10" Margin="0">
<Label Text="{Binding}" TextColor="DarkCyan"/>
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</StackLayout>

How to change backgroundcolor of GroupDisplayBinding in Xamarin Forms?

I am trying to change the background color of GroupDisplayBinding only that is inside the list view without affecting the list. As you can see in the image, the background is lightgray, also I want to change the margin of it too if that's possible.
<ListView
IsVisible="{Binding ShowList}"
IsGroupingEnabled="True"
HasUnevenRows="True"
SelectionMode="None"
SeparatorVisibility="None"
BackgroundColor="#ffffff"
GroupDisplayBinding="{Binding GroupName}"
GroupShortNameBinding="{Binding ShortName}"
ItemsSource="{Binding List}">
<ListView.Behaviors>
<behaviors:EventToCommandBehavior Command="{Binding ListItemTappedCommand}"
EventName="ItemTapped" />
</ListView.Behaviors>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Frame HasShadow="False"
CornerRadius="0"
Margin="2"
Padding="10"
BackgroundColor="#ffffff"
BorderColor="#000000">
<StackLayout Orientation="Horizontal"
Spacing="0"
Padding="0"
Margin="0">
<Label Text="{Binding Name}"
HorizontalOptions="StartAndExpand"
Style="{StaticResource ListTextStyle}"
TextColor="#2278B5"/>
<Label Text=">"
Style="{StaticResource ListTextStyle}"
TextColor="#2278B5"
HorizontalOptions="End"
FontSize="24" />
</StackLayout>
</Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
We could take it one step further and implement our own custom header cell with a nice background color.
The demo is very simple and just contains a Label, which binds to GroupName and I am placing it inside of a StackLayout with a bit of custom padding and a background color.
<ListView IsVisible="{Binding ShowList}"
IsGroupingEnabled="True"
HasUnevenRows="True"
SelectionMode="None"
SeparatorVisibility="None"
BackgroundColor="#ffffff"
GroupDisplayBinding="{Binding GroupName}"
GroupShortNameBinding="{Binding ShortName}"
ItemsSource="{Binding List}">
// set the appearance of Header here as you want
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell Height="25">
<StackLayout VerticalOptions="FillAndExpand" Padding="5" BackgroundColor="#3498DB">
<Label Text="{Binding GroupName}" TextColor="White" Margin="10" VerticalOptions="Center"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
<ListView.ItemTemplate>
//...
</ListView.ItemTemplate>
</ListView>

Xamarin.Forms: Custom Context Actions For Android

Hi i have a list view in which i added ContextActions.
i need to change Text Size, color and alignment of menu item in context actions,
also i want to increase width of context action on which menu item is appearing?
Thanks in advance.
<ListView.ItemTemplate>
<DataTemplate>
<customControls:ExtendedViewCell SelectedBackgroundColor="Transparent" >
<ViewCell.ContextActions>
<MenuItem Text="Call" />
<MenuItem Text="Delete" IsDestructive="True" />
</ViewCell.ContextActions>
<ViewCell.View>
<StackLayout HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand" Orientation="Vertical"
Padding="4" Spacing="8">
<Label TextColor="OrangeRed" Text="{Binding Title}" />
<Label TextColor="Blue" Text="{Binding Subtitle} "/>
</StackLayout>
</ViewCell.View>
</customControls:ExtendedViewCell>
</DataTemplate>
</ListView.ItemTemplate>
After you change the content of the cell, call ForceUpdateSize()
https://learn.microsoft.com/en-us/dotnet/api/Xamarin.Forms.Cell.ForceUpdateSize?view=xamarin-forms

Xamarin.Forms Add a GestureRecognizer to an Image in a ListView

I am trying to add a tap gesture to an Image within a ListView
The following Image renders correctly in the ListView without the Image.GestureRecognizers section, but with it, the ListView does not render anything at all (no error message). To clarify this, there is also a Label in the ListView and that does not render either.
<Image x:Name="newsImage" VerticalOptions="End" HeightRequest="200" WidthRequest="200" Aspect="AspectFill" Source="{Binding Imageurllarge}">
<Image.GestureRecognizers>
<TapGestureRecognizer
Tapped="OnTapGestureRecognizerTapped"
NumberOfTapsRequired="1" />
</Image.GestureRecognizers>
</Image>
I took this from - http://developer.xamarin.com/guides/cross-platform/xamarin-forms/working-with/gestures/ (assume this example is for not listview image, but assumed it should work within a listview).
Also (as per comment suggestion)
<Image.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding TapCommand}"
CommandParameter="newsImage" />
Does not seem to fair any better.
If anyone has an example of how to add this in the code behind (without a viewmodel is fine) then that will do.
You can use the DataTemplate in the ListView and inside the DataTemplate have a Grid then add the UI elements. In the given sample, I am showing the Name, contact number and Image, I have used the GestureRecognizers on the Image. Try this:
<ListView x:Name="myListView" ItemsSource="{Binding Contacts}" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell Height="75">
<Grid Padding="5">
<Grid.RowDefinitions>
<RowDefinition Height="20"></RowDefinition>
<RowDefinition Height="20"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30" />
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="80"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Image Source="user_img.png" Grid.Column="0" Grid.RowSpan="2" VerticalOptions="CenterAndExpand"/>
<Label Grid.Row="0" Grid.Column="1" Font="16" Text="{Binding DisplayName}" LineBreakMode="TailTruncation"></Label>
<Label Grid.Row="1" Grid.Column="1" Font="12" Text="{Binding Number}" LineBreakMode="TailTruncation"></Label>
<Image Grid.Row="0" Grid.RowSpan="3" Grid.Column="2" Source="add.png" Aspect="AspectFill">
<Image.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding AddCommand}"
CommandParameter="{Binding Number}" />
</Image.GestureRecognizers>
</Image>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I have had success with TapGestureRecognizer in uses like this one by specifying it in XAML with its own x:Name attribute, then adding a tap handler in code.
Example markup:
<Image.GestureRecognizers>
<TapGestureRecognizer x:Name="tapImage" NumberOfTapsRequired="1" />
</Image.GestureRecognizers>
Then in code something like:
this.tapImage.Tapped += async (object sender, EventArgs e) => {
... // Do whatever is wanted here
}
The handler need not necessarily be marked async, it is just common for my uses that something async is happening in there, like a confirm dialog or scanning a bar code.
You can also attach a gesture recognizer to an image inside a listview. The gesture recognizer can bind to a command in a view model
<ListView x:Name="ExampleList" SeparatorVisibility="None" VerticalOptions="Start" HeightRequest="{Binding HeightRequest}"
HasUnevenRows="True"
CachingStrategy="RecycleElement"
ItemsSource="{Binding FeedItems}"
IsPullToRefreshEnabled="True"
RefreshCommand="{Binding LoadItemsCommand}"
IsRefreshing="{Binding IsBusy, Mode=OneWay}">
<ListView.ItemTemplate >
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<StackLayout Orientation="Vertical">
<Label Text="{Binding TimeAgo}" FontSize="8"></Label>
<StackLayout Orientation="Horizontal">
<Image Source="Accept.png" HeightRequest="30" WidthRequest="45" IsVisible="{Binding IsAccepted, Converter={StaticResource inverse}}">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Source={StaticResource sampleViewModel}, Path=AcceptCommand}" CommandParameter="{Binding RequestID}" />
</Image.GestureRecognizers>
</Image>
</StackLayout>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

Resources