Xamarin.Forms:CarouselPage中的水平ScrollView

时间:2018-07-04 10:33:41

标签: xamarin.forms xamarin.android scrollview custom-renderer

我在CarouselPage项目的ContentPage中有一个ScrollView( Horizo​​ntalMoveEnable = true; )。

我创建了自己的ZoomScrollViewRenderer,可以放大。我还致力于改善手势识别,以转到CarouselPage的另一页。

当我在ScrollView的开头(X位置= 0)并且向左滑动时,它应该转到左侧页面。当我在ScrollView的末尾(X位置= ContentSize.Width)并且向右滑动时,它应该转到右侧的页面。

问题在于,只有两次滑动后它才能工作,我不知道如何改善它。

希望我能解释我的问题。

请参阅我的ZoomScrollViewRender并帮助改进方法DispatchTouchEvent

public class ZoomScrollViewRenderer : ScrollViewRenderer
{
    private Context _context;

    private ScaleGestureDetector _scaleDetector;
    private bool _isScaleProcess = false;

    private float X1 { get; set; }
    private float X2 { get; set; }


    public ZoomScrollViewRenderer(Context context) : base(context)
    {
        this._context = context;
    }


    protected override void OnElementChanged(VisualElementChangedEventArgs e)
    {
        base.OnElementChanged(e);

        if (e.NewElement != null)
        {
            _scaleDetector = new ScaleGestureDetector(Context, new ClearScaleListener(
                scale =>
                {
                    var scrollView = (ZoomScrollView)Element;

                    var xRatio = scale.FocusX / Width;
                    var yRatio = scale.FocusY / Height;

                    scrollView.AnchorX = xRatio;
                    scrollView.AnchorY = yRatio;
                },
                scale =>
                {
                    _isScaleProcess = true;
                    var scrollView = (ZoomScrollView)Element;

                    var zoom = new Pinch(scale.ScaleFactor, scale.FocusX, scale.FocusY);
                    scrollView.OnZoom(zoom);
                }));
        }
    }


    public override bool DispatchTouchEvent(MotionEvent e)
    {
        var scrollView = (ZoomScrollView)Element;

        // Scale if 2 fingers on screen
        if (e.PointerCount == 2)
            return _scaleDetector.OnTouchEvent(e);

        // Ignore horizontal move when content stretched to the width of the screen
        if (!scrollView.HorizontalMoveEnable)
            return base.DispatchTouchEvent(e);

        // Detect first X position 
        if (MotionEventActions.Down == e.Action)
        {
            X1 = e.RawX;
            return base.DispatchTouchEvent(e);
        }

        if (_isScaleProcess)
        {
            //HACK:
            //Prevent letting any touch events from moving the scroll view until all fingers are up from zooming...This prevents the jumping and skipping around after user zooms.
            if (MotionEventActions.Up == e.Action)
                _isScaleProcess = false;
            return false;
        }


        // Detect second X position
        if (MotionEventActions.Up == e.Action
            || MotionEventActions.Cancel == e.Action)
        {
            X2 = e.RawX;
        }

        // Left or right swipe
        if (X2 - X1 > 0 && scrollView.IsStartScroll
            || X1 - X2 >= 0 && scrollView.IsEndScroll)
        {

            return base.OnTouchEvent(e);
        }

        return base.DispatchTouchEvent(e);
    }
}

ZoomScrollView.cs 在可移植项目中:

public class ZoomScrollView : ScrollView
    {
        public event EventHandler<Pinch> Zoom;


        public bool HorizontalMoveEnable { get; set; } = false;

        public ScrollOrientation ScrollOrientation
        {
            get => Orientation;
            set
            {
                if (value.Equals(Orientation))
                    return;
                Orientation = value;
            }
        }

        public bool IsStartScroll => Math.Abs(0 - ScrollX) < 10;

        public bool IsEndScroll => Math.Abs(ContentSize.Width - Width - ScrollX) < 10;



        public virtual void OnZoom(Pinch pinch)
        {
            Zoom?.Invoke(this, pinch);
        }
    }

0 个答案:

没有答案