显示片段后存储画布图纸以供使用

时间:2019-05-09 07:51:53

标签: c# xamarin.android skiasharp

我有问题。在我的MainActivity中,单击按钮时会调用片段。片段之一是带有TriangleGrid的SkiaSharp画布。当您单击三角形时,它将更改该三角形的颜色。现在,当我第一次访问SkiaSharp片段时,一切都可以按我的要求正确加载,但是当我转到另一个页面然后返回SkiaSharp画布时,整个画布为空白。当您点击三角形时,三角形仍然充满,但是TriangleGrid消失了。也是之前单击的三角形,最后一个除外。这是我的代码中最重要的部分。

这是完整 MainActivity:

public class MainActivity : FragmentActivity
{
    Dictionary<string, TriangleRegistryObject> TriangleRegistry = new Dictionary<string, TriangleRegistryObject>();

    //ALL FRAGMENTS
    private Android.Support.V4.App.Fragment CurrentFragment;
    private int CurrentFragmentNum;
    private int PreviousFragmentNum;
    private Shape_Selection ShapeSelectionFragment;
    private Shape_Formation ShapeFormationFragment;

    private string Direction;


    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);

        ActionBar.SetCustomView(Resource.Layout.setup_nav_bar);
        ActionBar.SetDisplayShowCustomEnabled(true);
        ((Toolbar)ActionBar.CustomView.Parent).SetContentInsetsAbsolute(0, 0);
        SetContentView(Resource.Layout.activity_main);

        Button btnBack = FindViewById<Button>(Resource.Id.btnBack);
        Button btnNext = FindViewById<Button>(Resource.Id.btnNext);

        btnBack.Click += btnBack_Click;
        btnNext.Click += btnNext_Click;



        ShapeSelectionFragment = new Shape_Selection();
        ShapeFormationFragment = new Shape_Formation();

        var trans = SupportFragmentManager.BeginTransaction();
        trans.Add(Resource.Id.fragmentContainer, ShapeFormationFragment, "Shape_Formation");
        trans.Hide(ShapeFormationFragment);
        trans.Add(Resource.Id.fragmentContainer, ShapeSelectionFragment, "Shape_Selection");
        //trans.Hide(ShapeSelectionFragment);
        trans.Commit();

        CurrentFragmentNum = 1;
        Direction = "Startup";
        ShowFragment(CurrentFragmentNum, 1, Direction);
    }

    private void ShowFragment (int CurrentFragmentNum, int PreviousFragmentNum, string Direction)
    {
        Android.Support.V4.App.Fragment fragment = null;
        Android.Support.V4.App.Fragment PreviousFragment = null;

        switch (CurrentFragmentNum)
        {
            case 1:
                fragment = ShapeSelectionFragment;
                break;
            case 2:
                fragment = ShapeFormationFragment;
                break;
        }

        switch (PreviousFragmentNum)
        {
            case 1:
                PreviousFragment = ShapeSelectionFragment;
                break;
            case 2:
                PreviousFragment = ShapeFormationFragment;
                break;
        }


        var trans = SupportFragmentManager.BeginTransaction();


        switch (Direction)
        {
            case "Forwards":
                trans.SetCustomAnimations(Resource.Animation.slide_in_right, Resource.Animation.slide_out_left);
                break;
            case "Backwards":
                trans.SetCustomAnimations(Resource.Animation.slide_in_left, Resource.Animation.slide_out_right);
                break;
        }

        trans.Replace(Resource.Id.fragmentContainer, fragment);
        trans.Hide(PreviousFragment);
        trans.Show(fragment);
        trans.AddToBackStack(null);
        trans.Commit();

        CurrentFragment = fragment;
        if(CurrentFragment == ShapeSelectionFragment)
        {
            CurrentFragmentNum = 1;
        }
        else if (CurrentFragment == ShapeFormationFragment)
        {
            CurrentFragmentNum = 2;
        }
    }

    public void btnBack_Click(object sender, EventArgs e)
    {
        if (CurrentFragmentNum > 1)
        {
            PreviousFragmentNum = CurrentFragmentNum;
            CurrentFragmentNum -= 1;
            Direction = "Backwards";
            ShowFragment(CurrentFragmentNum, PreviousFragmentNum, Direction);
        }
    }

    public void btnNext_Click(object sender, EventArgs e)
    {
        if (CurrentFragmentNum < 2)
        {
            PreviousFragmentNum = CurrentFragmentNum;
            CurrentFragmentNum += 1;
            Direction = "Forwards";
            ShowFragment(CurrentFragmentNum, PreviousFragmentNum, Direction);
        }
    }
}

这是完整 Shape_Formation.cs:

public class Shape_Formation : Android.Support.V4.App.Fragment, IOnTouchListener
{
    private SKCanvasView skiaView;
    private SKPaint TriangleFillColor;
    private string Action { get; set; }

    Dictionary<string, TriangleRegistryObject> TriangleRegistry = new Dictionary<string, TriangleRegistryObject>();

    private int UnscaledWidth;
    private int UnscaledHeight;

    private int TrianglesPerUpperRow;
    private int TrianglesPerLowerRow;
    private int TrianglesVisiblePerRow = 4;
    private int CurrentRow = 0;

    private float TriangleWidth;
    private float TriangleRowHeight;


    //ALL SHAPE PATHS
    private SKPath TriangleGridPath = new SKPath();
    private SKPath TrianglePath = new SKPath();

    //================//
    // PAINT VARIANTS //
    //================//

    SKPaint TriangleGridPaint = new SKPaint
    {
        Style = SKPaintStyle.Stroke,
        Color = SKColors.White,
        StrokeWidth = 3
    };

    SKPaint SelectTrianglePaint = new SKPaint
    {
        Style = SKPaintStyle.Fill,
        Color = SKColors.Blue
    };

    SKPaint UnselectTrianglePaint = new SKPaint
    {
        Style = SKPaintStyle.Fill,
        Color = SKColor.Parse("#0e2a56")
    };

    SKPaint BackgroundPaint = new SKPaint
    {
        Style = SKPaintStyle.Fill,
        Color = SKColor.Parse("#0e2a56")
    };

    SKPaint FocusedTrianglePaint = new SKPaint
    {
        Style = SKPaintStyle.Fill,
        Color = SKColors.LightGray
    };


    //=======================//
    // END OF PAINT VARIANTS //
    //=======================//

    public override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
    }

    public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        View view = inflater.Inflate(Resource.Layout.setup_shape_formation, container, false);

        skiaView = view.FindViewById<SKCanvasView>(Resource.Id.skiaView);
        skiaView.SetOnTouchListener(this);
        skiaView.PaintSurface += PaintSurface;

        return view;
    }

    private void PaintSurface(object sender, SKPaintSurfaceEventArgs e)
    {

        //==============//
        // CANVAS SETUP //
        //==============//

        SKCanvas canvas = e.Surface.Canvas;

        //SOME VARIABLES OF SCREEN SIZE
        UnscaledWidth = e.Info.Width;
        UnscaledHeight = e.Info.Height;

        //=====================//
        // END OF CANVAS SETUP //
        //=====================//


        if (TriangleFillColor != null)
        {
            canvas.DrawPath(TrianglePath, TriangleFillColor);
            canvas.DrawPath(TrianglePath, TriangleGridPaint);
        }


        //====================//
        // DRAW TRIANGLE GRID //
        //====================//

        int TriangleCount = 0;

        TriangleWidth = UnscaledWidth / TrianglesVisiblePerRow;
        TriangleRowHeight = (float)Math.Sqrt(Math.Pow(TriangleWidth, 2) - (Math.Pow((UnscaledWidth / (TrianglesVisiblePerRow * 2)), 2)));

        CurrentRow = 1;
        float X_Start_CooridnateUpperRow = 0;
        float Y_Start_CooridnateUpperRow = 0;

        float X_Start_CooridnateLowerRow = -(TriangleWidth / 2);
        float Y_Start_CooridnateLowerRow = TriangleRowHeight;

        SKPaint TriangleBorderPaint;

        //DRAW MULTIPLE ROWS
        while (Y_Start_CooridnateUpperRow <= UnscaledHeight)
        {

            TrianglesPerUpperRow = 5;
            TrianglesPerLowerRow = 5;

            //SET THE TRIANGLE COUNTER FOR BOTH ROWS
            int TriangleUpperCountOnRow = 0;
            int TriangleLowerCountOnRow = 0;


            //DRAW THE UPPER ROW OF TRIANGLES
            while (TriangleUpperCountOnRow < TrianglesPerUpperRow)
            {
                float x1 = X_Start_CooridnateUpperRow;
                float y1 = Y_Start_CooridnateUpperRow;
                float x2 = X_Start_CooridnateUpperRow + TriangleWidth;
                float y2 = y1;
                float x3 = X_Start_CooridnateUpperRow + TriangleWidth / 2;
                float y3 = TriangleRowHeight * (CurrentRow);

                TriangleGridPath = new SKPath();
                TriangleGridPath.MoveTo(x1, y1);
                TriangleGridPath.LineTo(x2, y2);
                TriangleGridPath.LineTo(x3, y3);
                TriangleGridPath.LineTo(x1, y1);
                TriangleGridPath.Close();

                TriangleRegistryObject value;
                TriangleRegistry.TryGetValue(TriangleCount.ToString(), out value);

                if (value == null)
                {
                    if (x1 > UnscaledWidth ||
                        x2 > UnscaledWidth ||
                        x3 > UnscaledWidth ||
                        x1 < 0 ||
                        x2 < 0 ||
                        x3 < 0 ||
                        y1 > UnscaledHeight ||
                        y2 > UnscaledHeight ||
                        y3 > UnscaledHeight)
                    {
                        TriangleBorderPaint = BackgroundPaint;
                        TriangleRegistry[TriangleCount.ToString()] = new TriangleRegistryObject { x1 = x1, y1 = y1, x2 = x2, y2 = y2, x3 = x3, y3 = y3, Selected = false, Visible = false };
                    }
                    else
                    {
                        TriangleBorderPaint = TriangleGridPaint;
                        TriangleRegistry[TriangleCount.ToString()] = new TriangleRegistryObject { x1 = x1, y1 = y1, x2 = x2, y2 = y2, x3 = x3, y3 = y3, Selected = false, Visible = true };
                    }

                    canvas.DrawPath(TriangleGridPath, TriangleBorderPaint);
                }

                TriangleCount += 1;
                TriangleUpperCountOnRow += 1;
                X_Start_CooridnateUpperRow += TriangleWidth;

            }

            //DRAW THE LOWER ROW OF TRIANGLES
            while (TriangleLowerCountOnRow < TrianglesPerLowerRow)
            {
                float x1 = X_Start_CooridnateLowerRow;
                float y1 = Y_Start_CooridnateLowerRow;
                float x2 = X_Start_CooridnateLowerRow + TriangleWidth;
                float y2 = y1;
                float x3 = X_Start_CooridnateLowerRow + (TriangleWidth / 2);
                float y3 = TriangleRowHeight * (CurrentRow - 1);

                TriangleGridPath = new SKPath();
                TriangleGridPath.MoveTo(x1, y1);
                TriangleGridPath.LineTo(x2, y2);
                TriangleGridPath.LineTo(x3, y3);
                TriangleGridPath.LineTo(x1, y1);
                TriangleGridPath.Close();

                TriangleRegistryObject value;
                TriangleRegistry.TryGetValue(TriangleCount.ToString(), out value);

                if (value == null)
                {
                    if (x1 > UnscaledWidth ||
                        x2 > UnscaledWidth ||
                        x3 > UnscaledWidth ||
                        x1 < 0 ||
                        x2 < 0 ||
                        x3 < 0 ||
                        y1 > UnscaledHeight ||
                        y2 > UnscaledHeight ||
                        y3 > UnscaledHeight)
                    {
                        TriangleBorderPaint = BackgroundPaint;
                        TriangleRegistry[TriangleCount.ToString()] = new TriangleRegistryObject { x1 = x1, y1 = y1, x2 = x2, y2 = y2, x3 = x3, y3 = y3, Selected = false, Focused = false, Visible = false };
                    }
                    else
                    {
                        TriangleBorderPaint = TriangleGridPaint;
                        TriangleRegistry[TriangleCount.ToString()] = new TriangleRegistryObject { x1 = x1, y1 = y1, x2 = x2, y2 = y2, x3 = x3, y3 = y3, Selected = false, Focused = false, Visible = true };
                    }

                    canvas.DrawPath(TriangleGridPath, TriangleBorderPaint);
                }

                TriangleCount += 1;
                TriangleLowerCountOnRow += 1;
                X_Start_CooridnateLowerRow += TriangleWidth;
            }

            CurrentRow += 1;

            if ((CurrentRow - 1) % 2 != 0)
            {
                X_Start_CooridnateUpperRow = -(TriangleWidth / 2);
                X_Start_CooridnateLowerRow = 0;
            }
            else
            {
                X_Start_CooridnateUpperRow = 0;
                X_Start_CooridnateLowerRow = -(TriangleWidth / 2);
            }

            Y_Start_CooridnateUpperRow += TriangleRowHeight;
            Y_Start_CooridnateLowerRow += TriangleRowHeight;

        }

        //==============================//
        // END OF DRAWING TRIANGLE GRID //
        //==============================//

    }

    public override void OnDestroy()
    {
        skiaView.PaintSurface -= PaintSurface;
        base.OnDestroy();
    }


    private void DrawTrianglePath(double x1, double y1, double x2, double y2, double x3, double y3, string key, string Action)
    {
        bool ChangedState = true;

        var Triangle = TriangleRegistry[key];
        if (Triangle.Visible == true)
        {
            if (Triangle.Selected == false)
            {
                if (Action == "Selected")
                {
                    Triangle.Selected = true;
                    TriangleRegistry[key] = Triangle;
                    TriangleFillColor = SelectTrianglePaint;
                }
                else if (Action == "Focused")
                {
                    if (Triangle.Focused == false)
                    {
                        Triangle.Focused = true;
                        TriangleRegistry[key] = Triangle;
                        TriangleFillColor = FocusedTrianglePaint;
                    }
                }

            }
            else
            {
                Triangle.Selected = false;
                TriangleFillColor = UnselectTrianglePaint;
            }

            if (ChangedState == true)
            {
                TrianglePath = new SKPath();
                TrianglePath.MoveTo((float)Triangle.x1, (float)Triangle.y1);
                TrianglePath.LineTo((float)Triangle.x2, (float)Triangle.y2);
                TrianglePath.LineTo((float)Triangle.x3, (float)Triangle.y3);
                TrianglePath.LineTo((float)Triangle.x1, (float)Triangle.y1);
                TrianglePath.Close();

                skiaView.Invalidate();
            }
        }
    }

    public bool OnTouch(View v, MotionEvent e)
    {
        if (e.Action == MotionEventActions.Down)
        {

            var X_Clicked = e.GetX();
            var Y_Clicked = e.GetY();

            bool TriangleFound = false;

            while (TriangleFound == false)
            {
                foreach (KeyValuePair<string, TriangleRegistryObject> row in TriangleRegistry.ToList())
                {
                    if (isInside(row.Value.x1, row.Value.y1, row.Value.x2, row.Value.y2, row.Value.x3, row.Value.y3, X_Clicked, Y_Clicked))
                    {
                        TriangleFound = true;
                        Action = "Selected";
                        DrawTrianglePath(row.Value.x1, row.Value.y1, row.Value.x2, row.Value.y2, row.Value.x3, row.Value.y3, row.Key, Action);
                    }
                }
            }
        }

        return true;
    }

    static double area(double x1, double y1, double x2, double y2, double x3, double y3)
    {
        return Math.Abs((x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)) / 2.0);
    }

    static bool isInside(double x1, double y1, double x2, double y2, double x3, double y3, double x, double y)
    {
        double A = area(x1, y1, x2, y2, x3, y3);
        double A1 = area(x, y, x2, y2, x3, y3);
        double A2 = area(x1, y1, x, y, x3, y3);

        /* Calculate area of triangle PAB */
        double A3 = area(x1, y1, x2, y2, x, y);

        /* Check if sum of A1, A2 and A3 is same as A */
        return (A == A1 + A2 + A3);
    }
}

有人可以帮助我解决这个问题吗??

1 个答案:

答案 0 :(得分:1)

您可以在ShowFragment中看到以下代码行:

trans.Replace(Resource.Id.fragmentContainer, fragment);
    trans.Hide(PreviousFragment);
    trans.Show(fragment);
    trans.AddToBackStack(null);
    trans.Commit();

您使用replace,它将破坏您之前在Resource.Id.fragmentContainer中添加的片段,因此它无法存储画布,这里您只想显示和隐藏之前添加的片段,您可以像这样进行更改(这不会破坏片段而是隐藏并显示):

trans.Hide(PreviousFragment);
trans.Show(fragment);
trans.Commit();