Forum Xamarin.Forms

xamarin forms label in a scroll view pinch and zoom android

I need a label with large text like a article which needs pinch to zoom capability for that I have written a ZoomableScrollview which works fine in IOS and Windows but not in android. Please see the code below.

Code in PCL

public class ZoomableScrollView:ScrollView
{
    public static readonly BindableProperty MinimumZoomScaleProperty = BindableProperty.Create("MinimumZoomScale", typeof(float), typeof(ZoomableScrollView), default(float));

    public float MinimumZoomScale
    {
        get { return (float)GetValue(MinimumZoomScaleProperty); }
        set { SetValue(MinimumZoomScaleProperty, value); }
    }
    public static readonly BindableProperty MaximumZoomScaleProperty = BindableProperty.Create("MaximumZoomScale", typeof(float), typeof(ZoomableScrollView), default(float));

    public float MaximumZoomScale
    {
        get { return (float)GetValue(MaximumZoomScaleProperty); }
        set { SetValue(MaximumZoomScaleProperty, value); }
    }
}

IOS renderer

public class ZoomableScrollViewRenderer : ScrollViewRenderer
{
    protected override void OnElementChanged(VisualElementChangedEventArgs e)
    {
        base.OnElementChanged(e);
        if (e.NewElement == null)
            return;

        if (e.OldElement == null)
        {
            ZoomableScrollView zsv = Element as ZoomableScrollView;
            this.MinimumZoomScale = zsv.MinimumZoomScale;
            this.MaximumZoomScale = zsv.MaximumZoomScale;
            this.ViewForZoomingInScrollView += (UIScrollView sv) => { return this.Subviews[0]; };
        }
    }
}

Windows renderer

 public class ZoomableScrollViewRenderer:ScrollViewRenderer
{
    protected override void OnElementChanged(ElementChangedEventArgs<ScrollView> e)
    {
        base.OnElementChanged(e);
        if (e.NewElement == null)
            return;

        if (e.OldElement == null)
        {
            ZoomableScrollView zsv = Element as ZoomableScrollView;
            this.Control.ZoomMode = Windows.UI.Xaml.Controls.ZoomMode.Enabled;
            this.Control.MinZoomFactor = zsv.MinimumZoomScale;
            this.Control.MaxZoomFactor = zsv.MaximumZoomScale;
        }
    }
}

Android renderer

public class ZoomableScrollViewRenderer:ScrollViewRenderer
{
    float originalDistanceX, currentdistanceX, originalDistanceY, currentdistanceY;
    bool IsPinching = false;
    double currentScale;
    TeluguLabel lbl;
    ScrollView svMain, svSub;

    protected override void OnElementChanged(VisualElementChangedEventArgs e)
    {
        base.OnElementChanged(e);
        svMain = ((ScrollView)e.NewElement);
        lbl = svMain.Content as TeluguLabel;
        svSub = new ScrollView();
        svSub.Orientation = ScrollOrientation.Horizontal;
        svSub.Content = lbl;
        svMain.Content = svSub;
        lbl.AnchorX = 0;
        lbl.AnchorY = 0;

    }
    public override bool OnTouchEvent(MotionEvent e)
    {
        if (e.PointerCount > 1)
        {
            IsPinching = true;
            currentScale = lbl.Scale;
            originalDistanceX = Math.Abs(e.GetX(0) - e.GetX(1));
            originalDistanceY = Math.Abs(e.GetY(0) - e.GetY(1));
        }
        else
        {
            IsPinching = false;
        }
        return base.OnTouchEvent(e);
    }
    public override bool DispatchTouchEvent(Android.Views.MotionEvent e)
    {
        switch (e.Action)
        {
            case MotionEventActions.Down:
                this.Parent.RequestDisallowInterceptTouchEvent(true);
                break;
            case MotionEventActions.Move:
                if(IsPinching && e.PointerCount > 1)
                {
                    currentdistanceX = Math.Abs(e.GetX(0) - e.GetX(1));
                    currentdistanceY = Math.Abs(e.GetY(0) - e.GetY(1));
                    if (originalDistanceX < currentdistanceX || originalDistanceY < currentdistanceY)
                        lbl.Scale = currentScale + 0.01;
                    else if (originalDistanceX > currentdistanceX || originalDistanceY > currentdistanceY)
                        lbl.Scale = currentScale - 0.01;
                }
                break;
            case MotionEventActions.Up:
                this.Parent.RequestDisallowInterceptTouchEvent(false);
                break;
        }
        return base.DispatchTouchEvent(e);
    }


}

in android I was able to achieve zoom to some extent but the scrolling in not smooth, but I compromised for it. Now the problem is the text is getting stripped in the label. Somebody please help me my app itself is for reading which is he basic feature not working. Thanks in advance

Best Answer

Answers

Sign In or Register to comment.