Deep
Deep

Reputation: 11

.NET MAUI Conflict between Long press selection and CollectionView default selection and other gestures

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

Answers (1)

Serg Tomcat
Serg Tomcat

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

Related Questions