Reputation: 11
I have a collectionview and I want to enable selection only on longpress and once the long press is enabled I don't want any gestures to be invoked on that image or item in collectionview.
If tapped any item during longpress it should select/deselect the item.
Problem: Now on longpress the item is selected and if tap any item in UI it is deselecting the checkmark because the state is changing to Normal.
<DataTemplate x:Key="GridTemplate">
<Grid Margin="5,5" >
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="CommonStates">
<VisualState Name="Normal">
<VisualState.Setters>
<Setter TargetName="SelectionBorder" Property="BackgroundColor" Value="LightGray"/>
<Setter TargetName="SelectionImage" Property="IsVisible" Value="False" />
</VisualState.Setters>
</VisualState>
<VisualState Name="Selected">
<VisualState.Setters>
<Setter TargetName="SelectionBorder" Property="BackgroundColor" Value="{StaticResource Primary}"/>
<Setter Property="BackgroundColor" Value="White"/>
<Setter TargetName="SelectionImage" Property="IsVisible" Value="True" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Image Source="{Binding AbsolutePath}" HeightRequest="200" WidthRequest="200" Aspect="Fill" ZIndex="0">
<Image.Behaviors>
<toolkit:TouchBehavior LongPressCommand="{Binding BindingContext.LongPressCommand, Source={x:Reference VideosView}}" LongPressCommandParameter="{Binding .}" LongPressDuration="1000" LongPressCompleted="OnLongPressCompleted" PressedOpacity="0.6" PressedAnimationEasing="{x:Static Easing.CubicInOut}" PressedScale="0.75" />
</Image.Behaviors>
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding BindingContext.VideoTapCommand, Source={x:Reference VideoCollectionView}}" CommandParameter="{Binding AbsolutePath}" >
</TapGestureRecognizer>
</Image.GestureRecognizers>
</Image>
<Label ZIndex="1" Text="{Binding Duration}" TextColor="{StaticResource White}" FontSize="14" FontAttributes="Bold" VerticalOptions="End" HorizontalOptions="Start" Margin="10,12" >
<Label.Shadow>
<Shadow Brush="{StaticResource Black}"
Offset="3,3"
Radius="11"
Opacity="0.9" />
</Label.Shadow>
</Label>
<Border x:Name="SelectionBorder" Margin="0,0,14,14" Style="{StaticResource SelectionBorder}">
<Image x:Name="SelectionImage" Source="Images/selection.svg" Style="{StaticResource SelectionImage}"/>
</Border>
</Grid>
</DataTemplate>
private void OnLongPress(FileInfo selectedItem)
{
IsMediaLongPressed = true;
bool isSelected = SelectedItems.Contains(selectedItem, _fileInfoComparer);
switch(selectedItem.MediaType)
{
case GlobalConstants.Mediatype_Image:
PhotosOnLongPressHandled?.Invoke(selectedItem);
break;
case GlobalConstants.Mediatype_Video:
CollectionViewSelectionMode = SelectionMode.Multiple;
VideosOnLongPressHandled?.Invoke(selectedItem);
break;
case GlobalConstants.Mediatype_Audio:
AudioOnLongPressHandled.Invoke(selectedItem);
break;
}
}
async void OnLongPressCompleted(object sender, EventArgs e)
{
await Task.Delay(300);
_mediaViewModel.IsMediaLongPressed = false;
_mediaViewModel.IsDebouncing = false;
}
Tried to manually unsubscribe selection change events and making the longpress flag false but that is making normal flow error prone.
Upvotes: 1
Views: 130
Reputation: 933
Tried to find workaround and couldn't find any. The only way I discover is to use the same touch-behavior for clicks and rely on "CurrentInteractionStatus", which will be "Completed" after longtap trigger.
<Grid.Behaviors>
<toolkit:TouchBehavior LongPressCompleted="LongPress_Handler" TouchGestureCompleted="Tap_Handler" LongPressDuration="750"/>
</Grid.Behaviors>
.
private void LongPress_Handler(object sender, CommunityToolkit.Maui.Core.LongPressCompletedEventArgs e)
{
Console.WriteLine("Long Tap!");
}
private void Tap_Handler(object sender, CommunityToolkit.Maui.Core.TouchGestureCompletedEventArgs e)
{
var stackItem = (View)sender;
var touch = (CommunityToolkit.Maui.Behaviors.TouchBehavior)stackItem.Behaviors[0];
if (touch.CurrentInteractionStatus == CommunityToolkit.Maui.Core.TouchInteractionStatus.Started)
{
Console.WriteLine("Normal tap!");
}
}
If you find more reliable ways, please share.
Upvotes: 0