Xamarin iOS - 缩放后绘制到图像上

时间:2014-01-09 19:31:45

标签: ios uiimageview drawing xamarin scale

我有一个应用程序,用户可以在加载的图像上自由绘制。他选择了铅笔颜色,并开始绘制图像。

除此之外,他还可以用手指向下和向上缩放图像,这就是我遇到问题的地方。

缩放后,当绘制到图像上时,它变得模糊,并且奇怪地缩小..

扩展代码:

void ScaleImage (UIPinchGestureRecognizer gestureRecognizer)
        {
            AdjustAnchorPoint (gestureRecognizer);
            if (gestureRecognizer.State == UIGestureRecognizerState.Began || gestureRecognizer.State == UIGestureRecognizerState.Changed) {
                gestureRecognizer.View.Transform *= CGAffineTransform.MakeScale (gestureRecognizer.Scale, gestureRecognizer.Scale);
                gestureRecognizer.Scale = 1;
            }
        }

绘图代码:

public override void TouchesBegan (NSSet touches, UIEvent evt)
            {
                base.TouchesBegan (touches, evt);

                if (!canDraw)
                    return;

                UITouch touch = (UITouch)touches.AnyObject;
                lastPoint = touch.LocationInView (MyImageView);
            }

public override void TouchesMoved (NSSet touches, UIEvent evt)
        {
            base.TouchesMoved (touches, evt);

            if (!canDraw)
                return;

            UITouch touch       = (UITouch)touches.AnyObject;
            PointF currentPoint = touch.LocationInView (MyImageView);

            UIGraphics.BeginImageContext (MyImageView.Frame.Size);

            MyImageView.Image.Draw (new RectangleF (
                0, 0,
                MyImageView.Frame.Size.Width,
                MyImageView.Frame.Size.Height));

            CGContext ctx = UIGraphics.GetCurrentContext ();
            ctx.SetLineCap (CGLineCap.Round);
            ctx.SetLineWidth (5.0f);
            ctx.SetRGBStrokeColor (red, green, blue, 1);

            CGPath path = new CGPath ();
            path.MoveToPoint(MyImageView.Transform, lastPoint.X, lastPoint.Y);
            path.AddLineToPoint (MyImageView.Transform, currentPoint.X, currentPoint.Y);
            ctx.AddPath (path);
            ctx.DrawPath (CGPathDrawingMode.Stroke);

            MyImageView.Image = UIGraphics.GetImageFromCurrentImageContext ();
            UIGraphics.EndImageContext ();

            lastPoint = currentPoint;
        }

提前致谢!

1 个答案:

答案 0 :(得分:3)

我通过使用Bezier Paths而不是Core Graphics来实现它。

您可以在此处找到有关Bezier路径的一些背景信息: https://developer.apple.com/library/ios/documentation/2ddrawing/conceptual/drawingprintingios/BezierPaths/BezierPaths.html

由于我想实现一个Undo按钮,我创建了一个用于存储该行颜色的Class,以及相应的Path:

public class VESLine{
public UIBezierPath Path {
    get;
    set;
}

public UIColor Color {
    get;
    set;
}

public byte Index {
    get;
    set;
}
}

相应地修改了TouchesBegan事件,以创建新的UIBezierPath对象,将其存储在数组中,连同其颜色和索引以及触摸位置:

public override void TouchesBegan (MonoTouch.Foundation.NSSet touches, UIEvent evt)
{
    IndexCount++;

    UIBezierPath path   = new UIBezierPath ();
    path.LineWidth      = 5.0f;

    UITouch touch   = (UITouch)touches.AnyObject;
    previousPoint1  = touch.PreviousLocationInView (this);

    PointF p = touch.LocationInView (this);
    path.MoveTo (p);

    InvokeOnMainThread (() => {
        this.SetNeedsDisplay ();
    });

    currentPath = path;

    VESLine line = new VESLine () {
        Path    = currentPath, 
        Color   = StrokeColor,
        Index   = IndexCount 
    };
    lines.Add(line);
}

TouchesMoved事件也被修改,通过使用QuadCurve而不是常规线创建平滑的线路径。我还调用SetNeedsDisplay方法来强制进行视图绘制:

public override void TouchesMoved (MonoTouch.Foundation.NSSet touches, UIEvent evt)
{
    UITouch touch   = (UITouch)touches.AnyObject;
    PointF p        = touch.LocationInView (this);

    if (Math.Abs (p.X - previousPoint1.X) >= 4 ||
        Math.Abs (p.Y - previousPoint1.Y) >= 4) {

        PointF cP = new PointF ((p.X + previousPoint1.X) / 2, (p.Y + previousPoint1.Y) / 2);

        currentPath.AddQuadCurveToPoint (cP, previousPoint1);
        previousPoint1 = p;
    }
    else
        currentPath.AddLineTo (p);

    InvokeOnMainThread (() => {
        this.SetNeedsDisplay ();
    });
}

TouchesEndedTouchesCancelled将重绘视图:

public override void TouchesEnded (MonoTouch.Foundation.NSSet touches, UIEvent evt)
{
    InvokeOnMainThread (() => {
        this.SetNeedsDisplay ();
    });
}

public override void TouchesCancelled (MonoTouch.Foundation.NSSet touches, UIEvent evt)
{
    InvokeOnMainThread (() => {
        this.SetNeedsDisplay ();
    });
}

最后,重写Draw方法以迭代路径数组,使用相应的颜色绘制每个路径:

public override void Draw (System.Drawing.RectangleF rect)
{
    foreach (VESLine p in lines) {
        p.Color.SetStroke ();
        p.Path.Stroke ();
    }
}