dotnet / maui

.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.
https://dot.net/maui
MIT License
22k stars 1.72k forks source link

SwipeView Events - (SwipeView)sender.Open does not work #22153

Open Quaybe opened 4 months ago

Quaybe commented 4 months ago

Description

Trying to open a swipe view programatically by using the OnSwipeChanging and/or OnSwipeEnded events sender in code behind. I was doing this to try to get around the threshold value bug which has been in backlog for almost 2 years now:

https://github.com/dotnet/maui/issues/6016

Unfortunately, came across this bug while trying to avoid that bug...

Steps to Reproduce

The code is simple. Start a new .NET MAUI project and add the following in the code behind:

double offset;
private void OnSwipeChanging(object sender, SwipeChangingEventArgs e)
{
    var swipe = (SwipeView)sender;
    offset = e.Offset;

    if (offset <= -40)
        swipe.Open(OpenSwipeItem.RightItems);
}

private void OnSwipeEnded(object sender, SwipeEndedEventArgs e)
{
    var swipe = (SwipeView)sender;

    if (offset < -40)
        swipe.Open(OpenSwipeItem.RightItems);
}

For MainPage.xaml, add the swipeview somewhere in the vertical stack layout:

<SwipeView SwipeChanging="OnSwipeChanging" SwipeEnded="OnSwipeEnded">
    <SwipeView.RightItems>
        <SwipeItems>
            <SwipeItem Text="Favorite"
                                             IconImageSource="favorite.png"
                                             BackgroundColor="LightGreen"
                                             Invoked="OnFavoriteSwipeItemInvoked" />
            <SwipeItem Text="Delete"
                                             IconImageSource="delete.png"
                                             BackgroundColor="LightPink"
                                             Invoked="OnDeleteSwipeItemInvoked" />
        </SwipeItems>
    </SwipeView.RightItems>
    <Grid HeightRequest="60"
                  WidthRequest="300"
          BackgroundColor="LightGray">
        <Label Text="SwipeView"
                             HorizontalOptions="Center"
                             VerticalOptions="Center" />
    </Grid>
</SwipeView>

Begin debug and observe that swipe.Open() does nothing.

I could've made the repro more obvious, but please note you should only swipe -40 over and then stop and let go. You can place a break point on line 40 or 48 to verify you have swiped more than -40 to the left. Basically at any point after the letter "e" in "Favorite" is fully visible but before you get too far into the red of the Delete button. Don't let the swipe open on its own, if that makes sense. At this point, the swipe.Open() triggers, which you can verify with a break point, but the issue is the swipe does not open when calling the swipe.Open().

Link to public reproduction project repository

https://github.com/Quaybe/SwipeViewIssue

Version with bug

8.0.21 SR4.1

Is this a regression from previous behavior?

Not sure, did not test other versions

Last version that worked well

Unknown/Other

Affected platforms

Android

Affected platform versions

Android 13. Have not tested others.

Did you find any workaround?

No response

Relevant log output

No response

PureWeen commented 4 months ago

/similarissues

github-actions[bot] commented 4 months ago

Hi I'm an AI powered bot that finds similar issues based off the issue title.

Please view the issues below to see if they solve your problem, and if the issue describes your problem please consider closing this one and thumbs upping the other issue to help us prioritize it. Thank you!

Open similar issues:

Closed similar issues:

Note: You can give me feedback by thumbs upping or thumbs downing this comment.

Quaybe commented 4 months ago

Hi I'm an AI powered bot that finds similar issues based off the issue title.

Please view the issues below to see if they solve your problem, and if the issue describes your problem please consider closing this one and thumbs upping the other issue to help us prioritize it. Thank you!

Open similar issues:

Closed similar issues:

Note: You can give me feedback by thumbs upping or thumbs downing this comment.

The two open issues are regarding iOS only and Windows only, where they each state that whatever is broken works fine on the other OS's. In my case it's not working on Android, but I haven't tested iOS due to the connection to my MacPro breaking from bugged VS updates. Seems like this doesn't work on any OS and maybe all should be combined?

jaosnz-rep commented 4 months ago

Verified on 17.10 Preview 6(8.0.21), the issue does not repro on Android 13 and iOS platform. image

Quaybe commented 4 months ago

Verified on 17.10 Preview 6(8.0.21), the issue does not repro on Android 13 and iOS platform.

I am using 17.10.0 Preview 6 and Android 13. The issue persists and is reproducible using sample project. Please make sure you are not just swiping all the way over and opening the swipe view. You should only swipe -40 over then stop and let go. You can place a break point on line 40 or 48 to verify you have swiped more than -40 to the left. Basically at any point after the letter "e" in "Favorite" is fully visible but before you get too far into the red of the Delete button. Don't let the swipe open on its own, if that makes sense. At this point, the swipe.Open() triggers, which you can verify with a break point, but the issue is the swipe does not open when calling the swipe.Open().

jaosnz-rep commented 4 months ago

Verified on 17.10 Preview 6(8.0.21), the issue does not repro on Android 13 and iOS platform.

I am using 17.10.0 Preview 6 and Android 13. The issue persists and is reproducible using sample project. Please make sure you are not just swiping all the way over and opening the swipe view. You should only swipe -40 over then stop and let go. You can place a break point on line 40 or 48 to verify you have swiped more than -40 to the left. Basically at any point after the letter "e" in "Favorite" is fully visible but before you get too far into the red of the Delete button. Don't let the swipe open on its own, if that makes sense. At this point, the swipe.Open() triggers, which you can verify with a break point, but the issue is the swipe does not open when calling the swipe.Open().

Thanks for your reply, I can repro this problem by referring to your description.

phunkeler commented 4 months ago

Unfortunately, I don't have much to add here other than to say;

I have this same requirement (that is, to reduce the swipe gesture distance required to reveal all of the LeftItems or RightItems. We can have between 1 and 5 items that take-up the entire width of the SwipeView, which includes setting Threshold=0, but our users are finding that they have to swipe "too far" to reveal them all) and am running into this issue when attempting the "programmatic-open" workaround. In Xamarin, we used a custom SwipeViewRenderer to effectively reduce the OpenSwipeThresholdPercentage const but are hesitant to try this approach w/ the new handler architecture (I see a lot more code to have to copy and maintain).

It'd be great if the SwipeView exposed this member publicly, but I suppose that might have been the original intent of the Threshold property.

I did find a pretty nasty workaround that involves placing a SwipeGestureRecognizer on the SwipeView and setting it's Threshold property. However, the swipe items aren't revealed until after the swipe gesture is recognized and this probably isn't something we should be doing.

<SwipeView>
    <SwipeView.GestureRecognizers>
        <SwipeGestureRecognizer
            Direction="Left"
            Swiped="OnSwiped"
            Threshold="40"
            />
    </SwipeView.GestureRecognizers>
    ...

swipe_bug

In the repro project, I noticed that removing the call to swipe.Open from OnSwipeChanging (so that it only sets the offset field) causes the first programmatic open call, from OnSwipeEnded, to succeed. Subsequent attempts will continue to fail. If I put the SwipeView in a CollectionView and use this same pattern for each item, I notice that the swipe.Open call succeeds for each item's first attempt.

private double _offset;
public double Offset
{
    get => _offset;
    set
    {
        _offset = value;
        OnPropertyChanged(nameof(Offset));
    }
}

private void OnSwipeChanging(object sender, SwipeChangingEventArgs e)
{
    if (sender is SwipeView && e.SwipeDirection == SwipeDirection.Left)
    {
        Offset = e.Offset;
    }
}

private void OnSwipeEnded(object sender, SwipeEndedEventArgs e)
{
    if (sender is SwipeView swipe 
        && e.SwipeDirection == SwipeDirection.Left 
        && Offset < -40)
    {
        swipe.Open(OpenSwipeItem.RightItems);
    }
}

swipe_bug_5

Quaybe commented 4 months ago

Interesting stuff, and annoying 😄 thanks for commenting with the extra info!

phunkeler commented 4 months ago

Interesting stuff, and annoying 😄 thanks for commenting with the extra info!

Very frustrating, indeed. We couldn't find an easy solution so decided to copy all of MAUI's MauiSwipeView/SwipeViewHandler code just to change the value of OpenSwipeThresholdPercentage. Not a happy bunch today...