xamarin / Xamarin.Forms

Xamarin.Forms is no longer supported. Migrate your apps to .NET MAUI.
https://aka.ms/xamarin-upgrade
Other
5.62k stars 1.87k forks source link

[Bug Android] Scrolls conflicts with ScrollView(s) (CarouselView, CollectionView, ListView) #9315

Open Phenek opened 4 years ago

Phenek commented 4 years ago

Description

Got a strange interaction when scroll a CollectionView that is embedded inside a parent scrollView (CollectionView) on Android only. It's also affect CarouselView even if they are implemented with NestedScrollView and ListView.

Steps to Reproduce

  1. Create an Horizontal CarouselView (3 views) |↔|
  2. Incorpore on each view a Vertical CollectionView. | ↕ |
  3. On the header of those vertical collectionView, add a Header with an Horizontal CollectionView |↔|

Expected Behavior

Like in iOS, the embedded scrollView must have priority, where the deepest childScrollView should intercept the touch event (should scroll first). Also directions should not be affected. (an Horizontal ScrollView should not affect a vertical embedded ScrollView)

Actual Behavior

On Android it's anarchy of scroll conflicts. On iOS it's smooth!

Reproduction Link

Here the reproduction project =>ScrollConflicts.zip

Workaround

I did not find an efficient workaround for now.

Basic Information

Phenek commented 4 years ago

How touch event work on Android AndroidTouchEvents

This usual workaround should work (like on MapRenderer), but it doesn't.

        public override bool OnInterceptTouchEvent(MotionEvent ev)
        {
            Control.RequestDisallowInterceptTouchEvent(true);
            return base.OnInterceptTouchEvent(ev);
        }

There is no Control element inside the Renderers and the method RequestDisallowInterceptTouchEvent is not available inside the Renderers (CollectionView, CarouselView)

sarthak199526 commented 4 years ago

Any workaround for this ?

mjfreelancing commented 4 years ago

I think I have the same issue as described here. I have a CarouselView where each item is another View. On one of my views, a child element is a CollectionView. The CollectionView items are displayed but I cannot scroll them; instead, the CarouselView item is scrolled.

I'm also on Android. Is this the same as what is described in this issue?

PureWeen commented 4 years ago

These all come from components that implemented NestedScrollView interfaces so there's just something getting in the way with the nested elements orchestrating scroll interactions

balchen commented 4 years ago

We're facing the same issue. In our case, a WebView inside a CarouselView isn't (vertically) scrollable.

Phenek commented 4 years ago

https://github.com/xamarin/Xamarin.Forms/issues/8879

chaoyebugao commented 4 years ago

Having the same problem, one CarouselView with Horizontal CollectionView inside of it. CollectionView can not scroll but CarouselView, Android

tabrs commented 4 years ago

Same issue here with ListView inside CarouselView.

tabrs commented 4 years ago

Just one more thing. My structure is as follows

It does work with the first view, but have a scroll conflict with second and every other view no matter of type. Carousel is horizontally scrollable, its content is vertically scrollable. Hope it helps.

Any sight of a fix? I'm asking just because I would need to think that UI out some other way.

Thank you.

jivanro commented 4 years ago

I had the same problem and the following code helped me to alleviate the situation. (I have this view group hierarchy):

CarouselView StackLayout *ListView

You only have to create an Android Custom Render for ListView like this and you will see some difference right away:

I hope that helps.


/*** Code starts here ***//

[assembly: ExportRenderer(typeof(Xamarin.Forms.ListView), typeof(OneListViewRenderer))]
namespace Yournamespace
{
  public class OneListViewRenderer : ListViewRenderer
  {
    public OneListViewRenderer(Context context) : base(context)
   {
   }

    public override bool OnInterceptTouchEvent(Android.Views.MotionEvent ev)
    {
        if (ev.Action == MotionEventActions.Move)
        {
            // Disallow ScrollView to intercept touch Move events.
            this.Parent.RequestDisallowInterceptTouchEvent(true);

        }
         return base.OnInterceptTouchEvent(ev);

    }

 }
}
Phenek commented 4 years ago

@jivanro

it help a little but they are still some conflicts in which view start and should move at first..

AnnaBagriy commented 4 years ago

This one works perfectly fine:


[assembly: ExportRenderer(typeof(TouchEventListView), typeof(TouchEventListViewRender))]
namespace WinmanWarehouse.Droid.CustomRenderers
{
    public class TouchEventListViewRender : ListViewRenderer
    {
        public TouchEventListViewRender(Context context) : base(context)
        {
        }

        public override bool OnInterceptTouchEvent(Android.Views.MotionEvent ev)
        {
            switch (ev.Action & MotionEventActions.Mask)
            {
                case MotionEventActions.Down:
                    var listView = this.Control as Android.Widget.ListView;
                    listView.NestedScrollingEnabled = false;
                    break;
                case MotionEventActions.Move:
                    var listView1 = this.Control as Android.Widget.ListView;
                    listView1.NestedScrollingEnabled = true;
                    break;
                default:
                    break;
            }
            return base.OnInterceptTouchEvent(ev);
        }
    }
}

Taken from this forum https://forums.xamarin.com/discussion/173637/listview-inside-carouselview-scroll-vertical-is-almost-impossible
Phenek commented 3 years ago

@AnnaBagriy Thanks for the tips, but it works only for the vertical issue. All embedded possibility could have different issues related to this android bug.

@samhouts no milestone for this issue? Anyway, we hope that MAUI Android will get more support on this Gap between iOS/Android.