AndreiMisiukevich / TouchEffect

UI-responsive touch effects for Xamarin.Forms

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

iOS native touch effect may keep the pressed state when touch input moves away

globalnix opened this issue · comments

Reporting against package version 4.1.28

I'm experiencing a problem that is very similar to #35 but on iOS. If I add the touch effect to a control inside a scrollable container, then it is possible to drag my finger off the control without reverting the control's touch state to normal, leaving its appearance in a "pressed" state.

As noted above, this is similar to what was happening on Android in #35. I also experienced that problem, but the DisallowTouchThreshold property helpfully solved that. AFAIK there is no equivalent for iOS.

I have managed to come up with a workaround for iOS (see code below), but there are several problems that prevent me from using this in my project:

  1. I had to subclass ScrollView to create a new renderer
  2. It has to be included in the TouchEffect.iOS project
  3. PlatformTouchEff.HandleTouch has to be changed to internal

Of course, this workaround only works for ScrollView, so using the same logic I'd have to similarly subclass CollectionView, ListView, CarouselView etc.

Rather than the top-down approach of my solution where the antecedent scroll container handles the touch in all its children, I think it would be better to implement a solution where the child control hooks into the parent scrollcontainers's gesture events. My limited knowledge of iOS prevents me from thinking of a solution for this. Do you have any suggestions?

[assembly: ExportRenderer(typeof(ScrollViewExtended), typeof(ScrollViewExtendedRenderer))]
namespace TouchEffectSample.iOS
{
    public class ScrollViewExtendedRenderer : ScrollViewRenderer
    {
        public ScrollViewExtendedRenderer() : base()
        {
        }

        public override bool GestureRecognizerShouldBegin(UIGestureRecognizer gestureRecognizer)
        {
            HandleSubViewTouches(gestureRecognizer.View);
            return base.GestureRecognizerShouldBegin(gestureRecognizer);
        }

        private void HandleSubViewTouches(UIView view)
        {
            if (view.GestureRecognizers != null && view.GestureRecognizers.Any())
            {
                foreach (var gestureRecognizer in view.GestureRecognizers)
                {
                    if (gestureRecognizer is TouchUITapGestureRecognizer touchGestureRecognizer)
                    {
                        touchGestureRecognizer.HandleTouch(TouchStatus.Canceled);
                    }
                }
            }

            if (view.Subviews != null && view.Subviews.Any())
            {
                foreach (var subView in view.Subviews)
                {
                    HandleSubViewTouches(subView);
                }
            }
        }
    }
}

Hi. Frankly speaking, I have no idea how to fix that

Set DisallowTouchThreshold=1 for iOS (and update to latest version)

Hi Andrei, it's still not solved for me

Hi Andrei, it's still not solved for me

can you attach the sample with this issue? As I cannot reproduce it

Hi Andrei, I'm so sorry, maybe there's a cache bug or something. I tried to reinstall the package and it's working as expected

Hi Andrei, I'm so sorry, maybe there's a cache bug or something. I tried to reinstall the package and it's working as expected

I am glad to hear it :)