xamarin坐标似乎被重置

时间:2018-04-11 12:39:39

标签: android xamarin scroll touch skiasharp

这是我第一次尝试使用xamarin应用程序。我目前只针对Android。

该应用是以圆圈绘制的转喻日历。我正在使用skiasharp来完成我的所有绘图。我的问题是我一直在尝试根据文档实现滚动和缩放缩放。如果我使用制动点运行,那么代码(至少滚动)似乎可行。但是没有制动点,图像就会不断重新设置回屏幕中心。我不能为我的生活找出原因。

这是绘制日历的OnCanvasViewPaintSurface方法

        void OnCanvasViewPaintSurface(object sender, SkiaSharp.Views.Android.SKPaintSurfaceEventArgs args)
    {

        _info = args.Info;
        _surface = args.Surface;
        _canvas = _surface.Canvas;

        _canvas.Clear();

        if (Xtranslation == 0 && Ytranslation == 0)
            System.Diagnostics.Debug.WriteLine("back to 0 again? WTF?");

        _canvas.Translate(Xtranslation, Ytranslation);
        _canvas.Scale(Scale);

        string resourceID = "DruidCraftCalendar.Assets.calendar2.png";
        Assembly assembly = GetType().GetTypeInfo().Assembly;

        var cx = (_info.Width - Utility.GetWidthValueFromPercentage(_info, 99)) / 2;
        var cy = (_info.Height - Utility.GetWidthValueFromPercentage(_info, 99)) / 2;

        using (var stream = assembly.GetManifestResourceStream(resourceID))
        using (var bitmap = SKBitmap.Decode(stream))
        using (var paint = new SKPaint())
        {
            _canvas.DrawBitmap(bitmap, SKRect.Create(cx, cy, Utility.GetWidthValueFromPercentage(_info, 99), Utility.GetWidthValueFromPercentage(_info, 99)), paint);
        }

        CalendarRenderer.DrawCalendar(_info, _canvas, _calendar);
}

不是很多。绘制日历的最后一个调用在它下面有一组方法来绘制日历,这里有一些代表该类中的东西的方法

        private static void BuildDayRings(SKImageInfo info, SKCanvas canvas, IDayModel day, IMonthModel month)
    {
        float outerRingPercentageWidth = 31;
        float innerRingPercentageWidth = 26;

        var arcPainter = new SKPaint
        {
            Color = SKColors.Black,
            Style = SKPaintStyle.Stroke,
            StrokeWidth = 2
        };

        var dayLabelPainter = new SKPaint
        {
            Color = Color.FromRgb(0, 0, 0).ToSKColor(),
            Style = SKPaintStyle.StrokeAndFill,
            StrokeWidth = 2,
            TextSize = Utility.GetWidthValueFromPercentage(info, 2.5f)
        };

        info = BuildOuterDayRing(info, canvas, outerRingPercentageWidth, arcPainter);
        info = BuildInnerDayRing(info, canvas, innerRingPercentageWidth, arcPainter);

        CircleShape[] outerRingPegPoints = GetOuterPegPoints(info, canvas, outerRingPercentageWidth);
        CircleShape[] innerRingPegPoints = GetInnerPegPoints(info, canvas, innerRingPercentageWidth);

        ConnectDayRingCrossover(canvas, arcPainter, outerRingPegPoints, innerRingPegPoints);
        CreateDayLabels(info, canvas, arcPainter, dayLabelPainter, outerRingPegPoints, innerRingPegPoints);
        SetActiveDayPeg(info, canvas, day, month, outerRingPegPoints, innerRingPegPoints);
    }

    private static void SetActiveDayPeg(SKImageInfo info, SKCanvas canvas, IDayModel day, IMonthModel month, CircleShape[] outerRingPegPoints, CircleShape[] innerRingPegPoints)
    {
        ColourActiveDayPeg(day, month, outerRingPegPoints, innerRingPegPoints);
        DrawDayPegPoints(info, canvas, outerRingPegPoints, innerRingPegPoints);
    }

    private static void DrawDayPegPoints(SKImageInfo info, SKCanvas canvas, CircleShape[] outerRingPegPoints, CircleShape[] innerRingPegPoints)
    {
        DrawOutterRingPegPoints(canvas, outerRingPegPoints);
        DrawInnerRingPegPoints(info, canvas, innerRingPegPoints);
    }

    private static void DrawInnerRingPegPoints(SKImageInfo info, SKCanvas canvas, CircleShape[] innerRingPegPoints)
    {
        for (int i = 0; i <= innerRingPegPoints.Length - 1; i++)
        {
            DrawPegPointsWithOutOfPlaceFirstPoint(info, canvas, innerRingPegPoints, i);

        }
    }
........

        private static void DrawMonthRing(SKImageInfo info, SKCanvas canvas, IMonthModel month)
    {
        var monthRing = ElementDrawer.CreateRing(info, canvas, Utility.GetWidthValueFromPercentage(info, (float)21), new Color(255, 255, 255), false);
        monthRing.FillColor = new Color(255, 255, 0, 0);
        var monthPegPoints = ElementDrawer.CreatePegPoints(info, canvas, monthRing, 13, ((Math.PI * 2) / 13) / 2);

        var monthLabelRing = ElementDrawer.CreateRing(info, canvas, Utility.GetWidthValueFromPercentage(info, (float)19.5), new Color(255, 255, 255), false);

        var monthLabelPoints = ElementDrawer.CreatePegPoints(info, canvas, monthLabelRing, 13, ((Math.PI * 2) / 13) / 2);
        float rotation = 74;
        monthPegPoints[month.Get() - 1].FillColor = new Color(255, 0, 0);
        for (int i = 0; i <= monthPegPoints.Length - 1; i++)
        {
            SKPaint txtPaint1 = new SKPaint()
            {
                Color = Color.FromRgb(255, 255, 255).ToSKColor(),
                Style = SKPaintStyle.Fill,
                StrokeWidth = 1,
                TextSize = Utility.GetWidthValueFromPercentage(info, 2.2f)
            };
            SKPaint txtPaint2 = new SKPaint()
            {
                Color = Color.FromRgb(0, 0, 0).ToSKColor(),
                Style = SKPaintStyle.Stroke,
                StrokeWidth = 2,
                TextSize = Utility.GetWidthValueFromPercentage(info, 2.2f)
            };

            canvas.DrawCircle(monthPegPoints[i].x, monthPegPoints[i].y, monthPegPoints[i].Radius, GetPointPainter(monthPegPoints[i]));
            SKRect textbounds = new SKRect();
            var labelText = month.GetMonthName(i + 1);
            txtPaint1.MeasureText(labelText, ref textbounds);
            canvas.Save();
            canvas.RotateDegrees(rotation, monthLabelPoints[i].x, monthLabelPoints[i].y);
            canvas.DrawText(labelText, monthLabelPoints[i].x, monthLabelPoints[i].y + (textbounds.Height / 2), txtPaint1);
            canvas.DrawText(labelText, monthLabelPoints[i].x, monthLabelPoints[i].y + (textbounds.Height / 2), txtPaint2);
            canvas.Restore();
            rotation = rotation - 27.69f;
        }
    }

和元素抽屉

public class ElementDrawer
{
    public static CircleShape GetPegPointTemplate(SKImageInfo info)
    {
        var pegPoint = new CircleShape();
        pegPoint.Radius = (info.Width / 100) * (float)0.7;
        pegPoint.FillColor = Color.FromRgb(90,90,90);
        return pegPoint;
    }

    public static CircleShape[] CreatePegPoints(SKImageInfo info, SKCanvas canvas, CircleShape ring, int points, double offset = 0)
    {
        CircleShape[] pegPoints = new CircleShape[points];
        for (var i = 0; i < points; i++)
        {
            float x = Convert.ToSingle(((info.Width) / 2) + ring.Radius * Math.Sin(Math.PI + offset + (2 * Math.PI * i / points)));
            float y = Convert.ToSingle(((info.Height) / 2) + ring.Radius * Math.Cos(Math.PI + offset + (2 * Math.PI * i / points)));
            var point = GetPegPointTemplate(info);
            point.x = x;
            point.y = y;
            pegPoints[i] = point;
        }
        return pegPoints;
    }

    public static CircleShape CreateRing(SKImageInfo info, SKCanvas canvas, float radius, Color color, bool draw, bool fill = false)
    {
        var ring = new CircleShape();
        ring.Radius = radius;
        ring.OutlineColor = color;

        SKPaint paint = new SKPaint
        {
            Style = SKPaintStyle.Stroke,
            Color = ring.OutlineColor.ToSKColor(),
            StrokeWidth = 2
        };
        if (fill == true)
            paint.Style = SKPaintStyle.Fill;

        if (draw)
            canvas.DrawCircle(info.Width / 2, info.Height / 2, ring.Radius, paint);
        return ring;
    }
}

回到活动中,这是我处理滚动的方式

      private void ProcessTouchEvent(long id, MotionEventActions type, SKPoint location)
    {
        switch (type)
        {
            case MotionEventActions.Down:
            case MotionEventActions.Pointer2Down:
            case MotionEventActions.Pointer1Down:    
                touchDictionary.Add(id, new TouchManipulationInfo
                {
                    PreviousPoint = location,
                    NewPoint = location
                });
                break;
            case MotionEventActions.Move:
                TouchManipulationInfo info = touchDictionary[id];
                info.NewPoint = location;
                Manipulate();
                info.PreviousPoint = info.NewPoint;
                break;
            case MotionEventActions.Up:
            case MotionEventActions.Pointer2Up:
            case MotionEventActions.Pointer1Up:    
                touchDictionary[id].NewPoint = location;
                //Manipulate();
                touchDictionary.Remove(id);
                break;
            case MotionEventActions.Cancel:
                touchDictionary.Remove(id);
                break;

        }
    }

    public SKMatrix Matrix = SKMatrix.MakeIdentity();

    private void Manipulate()
    {
        TouchManipulationInfo[] infos = new TouchManipulationInfo[touchDictionary.Count];
        touchDictionary.Values.CopyTo(infos, 0);
        SKMatrix touchMatrix = SKMatrix.MakeIdentity();

        if (infos.Length == 1)
        {
            SKPoint prevPoint = infos[0].PreviousPoint;
            SKPoint newPoint = infos[0].NewPoint;
            SKPoint pivotPoint = Matrix.MapPoint(_info.Width / 2, _info.Height /2);

            OneFingerManipulate(prevPoint, newPoint, pivotPoint);
        }
        else if (infos.Length >= 2)
        {
            int pivotIndex = infos[0].NewPoint == infos[0].PreviousPoint ? 0 : 1;
            SKPoint pivotPoint = Matrix.MapPoint(_info.Width / 2, _info.Height / 2);
            SKPoint newPoint = infos[1 - pivotIndex].NewPoint;
            SKPoint prevPoint = infos[1 - pivotIndex].PreviousPoint;

            TwoFingerManipulate(prevPoint, newPoint, pivotPoint);
        }
    }

    private void OneFingerManipulate(SKPoint prevPoint, SKPoint newPoint, SKPoint pivotPoint)
    {
        Xtranslation = newPoint.X - prevPoint.X;
        Ytranslation = newPoint.Y - prevPoint.Y;
    }

我还把所有代码放在github上,因为我知道这不是帮助我的最简单的问题。我一直在寻找基类上的其他方法是否正在重置事物,但我找不到任何东西。有谁有任何想法?

https://github.com/radicalgeek/DruidcraftCalendar/tree/master/DruidCraftCalendar

0 个答案:

没有答案