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

时间:2019-04-04 23:20:55

标签: xamarin xamarin.forms xamarin.android carousel renderer

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

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);

如何知道Child是哪个ScrollView

使用循环来检查这一点,

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

满足以下条件:“ 给定的表达式绝不是提供的(ScrollView)类型

所以!如何像在CarouselPage中那样优雅地禁用iOS的滑动/滚动?

更新:请参见sample solution

2 个答案:

答案 0 :(得分:1)

几件事。

对于 Android ,您要查找的视图不是ScrollView,而是ViewPager

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

此外,为什么还要使用VisualElementRenderer<CarouselPage>作为CustomCarouselPageRenderer的父类。而是像在iOS上那样使用CarouselPageRenderer

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

您的整个课堂看起来像这样:

[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即可进行滚动。

希望这会有所帮助。-

答案 1 :(得分:1)

Methods类中覆盖ViewPager

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上的这种行为的任何人。