如何在 Android 中禁用轮播页面滚动

How to disable Carousel Page scrolling in Android

使用自定义渲染器可以在 iOS 上禁用 CarouselPage 的滑动手势,如下所示:

using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly: ExportRenderer(typeof(CarouselPage), typeof(CustomCarouselPageRenderer))]
namespace App.iOS
{
    public class CustomCarouselPageRenderer : CarouselPageRenderer
    {
        protected override void OnElementChanged(VisualElementChangedEventArgs e)
        {
            base.OnElementChanged(e);

            UIView view = this.NativeView;
            UIScrollView scrollView = (UIKit.UIScrollView)view.Subviews[0];
            scrollView.ScrollEnabled = false;
        }
    }
}

如何在 Android 上完成相同的操作?

using Android.Content;
using XamFormsApp.Droid.Renderers;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(CarouselPage), typeof(CustomCarouselPageRenderer))]
namespace StixApp.Droid.Renderers
{
    public class CustomCarouselPageRenderer : VisualElementRenderer<CarouselPage>
    {
        public CustomCarouselPageRenderer(Context context) : base(context)
        {
        }

        protected override void OnElementChanged(ElementChangedEventArgs<CarouselPage> e)
        {
            base.OnElementChanged(e);
            var view = this.RootView;
            X
            X
        }
    }
}

似乎无法以同样的方式访问 Subviews。可以像这样访问 Children

Android.Views.View view = (Android.Views.View)GetChildAt(i);

如果有的话,如何知道哪个 ChildScrollView

使用循环来检查这个,像这样,

for (int i = 0; i < ChildCount; ++i)
{
    Android.Views.View view = (Android.Views.View)GetChildAt(i);
    if (view is ScrollView)
    {
    }
}

产生以下结果:“给定的表达式绝不是提供的 (ScrollView) 类型

所以!如何像 iOS 中那样优雅地禁用 CarouselPage swipe/scrolling?

更新:请参阅sample solution

几件事。

对于 Android,您正在寻找的视图不是 ScrollView,而是 ViewPager

可以使用 GetChildAt 方法在索引 0 下找到它。

此外,您为什么使用 VisualElementRenderer<CarouselPage> 作为 CustomCarouselPageRenderer 的父级 class。而是像使用 iOS 一样使用 CarouselPageRenderer

最后一件事是在 Android 上无法禁用 ViewPager 的滚动。要获得此行为,您可以收听 Touch 事件。将 TouchEventArgs 的 Handled 属性 设置为 true 将防止滚动发生。

你的整个 class 看起来像:

[assembly: ExportRenderer(typeof(CarouselPage), typeof(CustomCarouselPageRenderer))]
namespace StixApp.Droid.Renderers
{
    public class CustomCarouselPageRenderer : CarouselPageRenderer
    {
        private bool _canScroll = false;

        public CustomCarouselPageRenderer(Context context) : base(context)
        {
        }

        public CustomCarouselPageRenderer()
        {
        }

        protected override void OnElementChanged(ElementChangedEventArgs<CarouselPage> e)
        {
            base.OnElementChanged(e);

            if (this.ChildCount > 0  && this.GetChildAt(0) is ViewPager viewPager)
            {
                viewPager.Touch -= ViewPagerTouched;
                viewPager.Touch += ViewPagerTouched;
            }
        }

        private void ViewPagerTouched(object sender, TouchEventArgs e)
        {
            e.Handled = !_canScroll;
        }
    }
}

只需将 _canScroll 的值更改为 true 即可允许滚动。

希望对您有所帮助。-

已在 ViewPager 中覆盖 Methods class:

public class NonSwipeableViewPager : ViewPager
{    
    public override bool OnTouchEvent(MotionEvent e)
    {
        return false;
    }

    public override bool OnInterceptTouchEvent(MotionEvent ev)
    {
        return false;
    }

    public override bool ExecuteKeyEvent(KeyEvent ev)
    {
        return false;
    }
}

CarouselPageRenderer 的更改:

class 声明中:

public class MyCarouselPageRenderer : VisualElementRenderer<CarouselPage>
{
    NonSwipeableViewPager _viewPager;
}

OnElementChanged中:

protected override void OnElementChanged(ElementChangedEventArgs<CarouselPage> e)
{
    _viewPager = new NonSwipeableViewPager(Context);
}

注意:CarouselPageAdapterCarouselPageRendererMeasureSpecFactoryObjectJavaBoxPageContainer 都必须从 Xamarin.Forms github 以启用自定义 CarouselPageRenderer 实施。所有这些都在 github 示例中,但希望这对未来的访问者来说更清楚。

注意 2:我想强调的是,我们试图实现的真实行为可能最好使用 NavigationPage 来完成,因为这使我们可以随时轻松地弹出和推送任何和所有页面,而无需解决滑动问题问题。话虽这么说,但愿此解决方案可以帮助在 CarouselPage.

上需要此行为的任何人