From 36560bcf7169d91cd5d42d117de553bd1bb557f3 Mon Sep 17 00:00:00 2001 From: Hannes Klose Date: Fri, 22 Oct 2021 13:57:03 +0200 Subject: [PATCH 1/5] Fixed drawing outside of DrawingView control --- .../DrawingView/Renderer/DrawingViewRenderer.android.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.android.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.android.cs index 66f1a1ab4..929acdfcf 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.android.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.android.cs @@ -124,10 +124,11 @@ public override bool OnTouchEvent(MotionEvent e) drawPath.MoveTo(touchX, touchY); break; case MotionEventActions.Move: - if (touchX > 0 && touchY > 0) + if (touchX > 0 && touchY > 0 && touchX < drawCanvas!.Width && touchY < drawCanvas.Height) + { drawPath.LineTo(touchX, touchY); - - currentLine!.Points.Add(new Point(touchX, touchY)); + currentLine!.Points.Add(new Point(touchX, touchY)); + } break; case MotionEventActions.Up: Parent?.RequestDisallowInterceptTouchEvent(false); From 3cc47369095823e7b9046490446c8a4e28e429af Mon Sep 17 00:00:00 2001 From: Vladislav Antonyuk Date: Wed, 8 Dec 2021 09:42:31 +0200 Subject: [PATCH 2/5] NormalizePoints --- ...rin.CommunityToolkit.Sample.Android.csproj | 6 ++ .../Renderer/DrawingViewRenderer.android.cs | 80 ++++++++++++++----- 2 files changed, 64 insertions(+), 22 deletions(-) diff --git a/samples/XCT.Sample.Android/Xamarin.CommunityToolkit.Sample.Android.csproj b/samples/XCT.Sample.Android/Xamarin.CommunityToolkit.Sample.Android.csproj index c6b2498ef..c5e0c009f 100644 --- a/samples/XCT.Sample.Android/Xamarin.CommunityToolkit.Sample.Android.csproj +++ b/samples/XCT.Sample.Android/Xamarin.CommunityToolkit.Sample.Android.csproj @@ -32,6 +32,12 @@ DEBUG; prompt 4 + false + false + false + false + false + true diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.android.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.android.cs index e9511980d..4f374cb35 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.android.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.android.cs @@ -1,5 +1,5 @@ -using System.ComponentModel; -using System.Linq; +using System.Collections.Generic; +using System.ComponentModel; using Android.Content; using Android.Graphics; using Android.Views; @@ -84,15 +84,7 @@ protected override void OnDraw(Canvas? canvas) { base.OnDraw(canvas); - foreach (var line in Element.Lines) - { - var path = new Path(); - path.MoveTo((float)line.Points[0].X, (float)line.Points[0].Y); - foreach (var (x, y) in line.Points) - path.LineTo((float)x, (float)y); - - canvas?.DrawPath(path, drawPaint); - } + Draw(Element.Lines, canvas); canvas?.DrawBitmap(canvasBitmap!, 0, 0, canvasPaint); canvas?.DrawPath(drawPath, drawPaint); @@ -125,10 +117,9 @@ public override bool OnTouchEvent(MotionEvent e) break; case MotionEventActions.Move: if (touchX > 0 && touchY > 0 && touchX < drawCanvas!.Width && touchY < drawCanvas.Height) - { drawPath.LineTo(touchX, touchY); - currentLine!.Points.Add(new Point(touchX, touchY)); - } + + currentLine!.Points.Add(new Point(touchX, touchY)); break; case MotionEventActions.Up: Parent?.RequestDisallowInterceptTouchEvent(false); @@ -161,6 +152,39 @@ public override bool OnInterceptTouchEvent(MotionEvent ev) return base.OnInterceptTouchEvent(ev); } + IList NormalizePoints(IList points) + { + var newPoints = new List(); + foreach (var point in points) + { + var pointX = point.X; + var pointY = point.Y; + if (pointX < 0) + { + pointX = 0; + } + + if (pointX > drawCanvas?.Width) + { + pointX = drawCanvas?.Width ?? 0; + } + + if (point.Y < 0) + { + pointY = 0; + } + + if (pointY > drawCanvas?.Height) + { + pointY = drawCanvas?.Height ?? 0; + } + + newPoints.Add(new Point(pointX, pointY)); + } + + return newPoints; + } + void LoadLines() { drawCanvas!.DrawColor(Element.BackgroundColor.ToAndroid(), PorterDuff.Mode.Clear!); @@ -168,18 +192,30 @@ void LoadLines() var lines = Element.Lines; if (lines.Count > 0) { - foreach (var line in lines) + Draw(lines, drawCanvas, drawPath); + } + + Invalidate(); + } + + void Draw(IEnumerable lines, Canvas? canvas, Path? path = null) + { + foreach (var line in lines) + { + path ??= new Path(); + var points = NormalizePoints(line.Points); + path.MoveTo((float)points[0].X, (float)points[0].Y); + foreach (var (x, y) in points) { - drawPath.MoveTo((float)line.Points[0].X, (float)line.Points[0].Y); - foreach (var (x, y) in line.Points) - drawPath.LineTo((float)x, (float)y); + var pointX = (float)x; + var pointY = (float)y; - drawCanvas.DrawPath(drawPath, drawPaint); - drawPath.Reset(); + path.LineTo(pointX, pointY); } - } - Invalidate(); + canvas?.DrawPath(path, drawPaint); + path.Reset(); + } } protected override void Dispose(bool disposing) From af0739de5bce9bd3cdadcaa8105e757ce9dc4217 Mon Sep 17 00:00:00 2001 From: Vladislav Antonyuk Date: Wed, 8 Dec 2021 10:41:45 +0200 Subject: [PATCH 3/5] Fix Samples --- .../Pages/Views/DrawingViewPage.xaml | 3 +-- .../Pages/Views/DrawingViewPage.xaml.cs | 25 ++++++++++--------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/samples/XCT.Sample/Pages/Views/DrawingViewPage.xaml b/samples/XCT.Sample/Pages/Views/DrawingViewPage.xaml index 927dddf27..033fd4187 100644 --- a/samples/XCT.Sample/Pages/Views/DrawingViewPage.xaml +++ b/samples/XCT.Sample/Pages/Views/DrawingViewPage.xaml @@ -3,8 +3,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:views="clr-namespace:Xamarin.CommunityToolkit.UI.Views;assembly=Xamarin.CommunityToolkit" x:Class="Xamarin.CommunityToolkit.Sample.Pages.Views.DrawingViewPage" - xmlns:pages="clr-namespace:Xamarin.CommunityToolkit.Sample.Pages" - xmlns:viewsVodel="clr-namespace:Xamarin.CommunityToolkit.Sample.ViewModels.Views;assembly=Xamarin.CommunityToolkit.Sample"> + xmlns:pages="clr-namespace:Xamarin.CommunityToolkit.Sample.Pages"> diff --git a/samples/XCT.Sample/Pages/Views/DrawingViewPage.xaml.cs b/samples/XCT.Sample/Pages/Views/DrawingViewPage.xaml.cs index c812f8f6a..52bb7a9ae 100644 --- a/samples/XCT.Sample/Pages/Views/DrawingViewPage.xaml.cs +++ b/samples/XCT.Sample/Pages/Views/DrawingViewPage.xaml.cs @@ -9,12 +9,11 @@ namespace Xamarin.CommunityToolkit.Sample.Pages.Views { public partial class DrawingViewPage : BasePage { - static Random random = new Random(); + static readonly Random random = new(); public DrawingViewPage() { InitializeComponent(); - DrawingViewControl.Lines = GenerateLines(5); DrawingViewControl.DrawingLineCompletedCommand = new Command(line => { Logs.Text += "GestureCompletedCommand executed" + Environment.NewLine; @@ -25,7 +24,14 @@ public DrawingViewPage() BindingContext = this; } - void LoadPointsButtonClicked(object sender, EventArgs e) => DrawingViewControl.Lines = GenerateLines(50); + void LoadPointsButtonClicked(object sender, EventArgs e) + { + DrawingViewControl.Lines.Clear(); + foreach (var line in GenerateLines(2)) + { + DrawingViewControl.Lines.Add(line); + } + } void DisplayHiddenLabelButtonClicked(object sender, EventArgs e) => HiddenPanel.IsVisible = !HiddenPanel.IsVisible; @@ -38,7 +44,7 @@ void GetCurrentDrawingViewImageClicked(object sender, EventArgs e) void GetImageClicked(object sender, EventArgs e) { - var lines = GenerateLines(10); + var lines = GenerateLines(2); DrawImage(lines.ToList()); } @@ -65,7 +71,7 @@ ObservableCollection GeneratePoints(int count) var points = new ObservableCollection(); for (var i = 0; i < count; i++) { - points.Add(new Point(random.Next(1, 100), random.Next(1, 100))); + points.Add(new Point(random.Next(1, (int)DrawingViewControl.Width), random.Next(1, (int)DrawingViewControl.Height))); } return points; @@ -77,8 +83,7 @@ void DrawImage(List lines) GestureImage.Source = ImageSource.FromStream(() => stream); } - private void AddNewLine(object sender, EventArgs e) - { + void AddNewLine(object sender, EventArgs e) => DrawingViewControl.Lines.Add(new Line() { Points = GeneratePoints(10), @@ -87,11 +92,7 @@ private void AddNewLine(object sender, EventArgs e) EnableSmoothedPath = true, Granularity = 5 }); - } - void ClearLines_Clicked(System.Object sender, System.EventArgs e) - { - DrawingViewControl.Lines.Clear(); - } + void ClearLines_Clicked(object sender, EventArgs e) => DrawingViewControl.Lines.Clear(); } } \ No newline at end of file From cc7a73707b70a505cff4a256236c37d762e39b79 Mon Sep 17 00:00:00 2001 From: Brandon Minnick <13558917+brminnick@users.noreply.github.com> Date: Wed, 8 Dec 2021 11:24:55 -0800 Subject: [PATCH 4/5] Remove Null Forgiving Operator, `!` --- .../Renderer/DrawingViewRenderer.android.cs | 50 ++++++++++++------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.android.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.android.cs index 4f374cb35..237d7c723 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.android.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.android.cs @@ -49,13 +49,18 @@ public DrawingViewRenderer(Context context) protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) { base.OnElementPropertyChanged(sender, e); - if (e.PropertyName == DrawingView.LinesProperty.PropertyName) - LoadLines(); + + if (e.PropertyName == DrawingView.LinesProperty.PropertyName + && drawCanvas is not null) + { + LoadLines(drawCanvas); + } } protected override void OnElementChanged(ElementChangedEventArgs e) { base.OnElementChanged(e); + if (e.NewElement != null) { SetBackgroundColor(Element.BackgroundColor.ToAndroid()); @@ -65,7 +70,11 @@ protected override void OnElementChanged(ElementChangedEventArgs e) } } - void OnLinesCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) => LoadLines(); + void OnLinesCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) + { + if (drawCanvas is not null) + LoadLines(drawCanvas); + } protected override void OnSizeChanged(int w, int h, int oldw, int oldh) { @@ -73,25 +82,32 @@ protected override void OnSizeChanged(int w, int h, int oldw, int oldh) const int minH = 1; w = w < minW ? minW : w; h = h < minH ? minH : h; + base.OnSizeChanged(w, h, oldw, oldh); canvasBitmap = Bitmap.CreateBitmap(w, h, Bitmap.Config.Argb8888!)!; drawCanvas = new Canvas(canvasBitmap); - LoadLines(); + LoadLines(drawCanvas); } protected override void OnDraw(Canvas? canvas) { base.OnDraw(canvas); - Draw(Element.Lines, canvas); + if (canvas is not null) + { + Draw(Element.Lines, canvas); - canvas?.DrawBitmap(canvasBitmap!, 0, 0, canvasPaint); - canvas?.DrawPath(drawPath, drawPaint); + canvas.DrawBitmap(canvasBitmap!, 0, 0, canvasPaint); + canvas.DrawPath(drawPath, drawPaint); + } } public override bool OnTouchEvent(MotionEvent e) { + if (drawCanvas is null) + throw new System.InvalidOperationException($"{nameof(drawCanvas)} must be initialized before {nameof(OnTouchEvent)}"); + var touchX = e.GetX(); var touchY = e.GetY(); @@ -112,18 +128,18 @@ public override bool OnTouchEvent(MotionEvent e) } }; - drawCanvas!.DrawColor(Element.BackgroundColor.ToAndroid(), PorterDuff.Mode.Clear!); + drawCanvas.DrawColor(Element.BackgroundColor.ToAndroid(), PorterDuff.Mode.Clear!); drawPath.MoveTo(touchX, touchY); break; case MotionEventActions.Move: - if (touchX > 0 && touchY > 0 && touchX < drawCanvas!.Width && touchY < drawCanvas.Height) + if (touchX > 0 && touchY > 0 && touchX < drawCanvas.Width && touchY < drawCanvas.Height) drawPath.LineTo(touchX, touchY); - currentLine!.Points.Add(new Point(touchX, touchY)); + currentLine?.Points.Add(new Point(touchX, touchY)); break; case MotionEventActions.Up: Parent?.RequestDisallowInterceptTouchEvent(false); - drawCanvas!.DrawPath(drawPath, drawPaint); + drawCanvas.DrawPath(drawPath, drawPaint); drawPath.Reset(); if (currentLine != null) { @@ -185,9 +201,9 @@ IList NormalizePoints(IList points) return newPoints; } - void LoadLines() + void LoadLines(in Canvas drawCanvas) { - drawCanvas!.DrawColor(Element.BackgroundColor.ToAndroid(), PorterDuff.Mode.Clear!); + drawCanvas.DrawColor(Element.BackgroundColor.ToAndroid(), PorterDuff.Mode.Clear!); drawPath.Reset(); var lines = Element.Lines; if (lines.Count > 0) @@ -198,7 +214,7 @@ void LoadLines() Invalidate(); } - void Draw(IEnumerable lines, Canvas? canvas, Path? path = null) + void Draw(IEnumerable lines, in Canvas canvas, Path? path = null) { foreach (var line in lines) { @@ -213,7 +229,7 @@ void Draw(IEnumerable lines, Canvas? canvas, Path? path = null) path.LineTo(pointX, pointY); } - canvas?.DrawPath(path, drawPaint); + canvas.DrawPath(path, drawPaint); path.Reset(); } } @@ -225,10 +241,10 @@ protected override void Dispose(bool disposing) if (disposing) { - drawCanvas!.Dispose(); + drawCanvas?.Dispose(); drawPaint.Dispose(); drawPath.Dispose(); - canvasBitmap!.Dispose(); + canvasBitmap?.Dispose(); canvasPaint.Dispose(); if (Element != null) Element.Lines.CollectionChanged -= OnLinesCollectionChanged; From bfee2739582fbd20798aacc119a63eb8bb63c541 Mon Sep 17 00:00:00 2001 From: Vladislav Antonyuk Date: Thu, 9 Dec 2021 12:23:55 +0200 Subject: [PATCH 5/5] Fix warnings --- .../Renderer/DrawingViewRenderer.android.cs | 33 ++++++++----------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.android.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.android.cs index 237d7c723..ab88316ef 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.android.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.android.cs @@ -50,11 +50,8 @@ protected override void OnElementPropertyChanged(object sender, PropertyChangedE { base.OnElementPropertyChanged(sender, e); - if (e.PropertyName == DrawingView.LinesProperty.PropertyName - && drawCanvas is not null) - { - LoadLines(drawCanvas); - } + if (e.PropertyName == DrawingView.LinesProperty.PropertyName) + LoadLines(); } protected override void OnElementChanged(ElementChangedEventArgs e) @@ -70,11 +67,7 @@ protected override void OnElementChanged(ElementChangedEventArgs e) } } - void OnLinesCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) - { - if (drawCanvas is not null) - LoadLines(drawCanvas); - } + void OnLinesCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) => LoadLines(); protected override void OnSizeChanged(int w, int h, int oldw, int oldh) { @@ -87,7 +80,7 @@ protected override void OnSizeChanged(int w, int h, int oldw, int oldh) canvasBitmap = Bitmap.CreateBitmap(w, h, Bitmap.Config.Argb8888!)!; drawCanvas = new Canvas(canvasBitmap); - LoadLines(drawCanvas); + LoadLines(); } protected override void OnDraw(Canvas? canvas) @@ -105,9 +98,6 @@ protected override void OnDraw(Canvas? canvas) public override bool OnTouchEvent(MotionEvent e) { - if (drawCanvas is null) - throw new System.InvalidOperationException($"{nameof(drawCanvas)} must be initialized before {nameof(OnTouchEvent)}"); - var touchX = e.GetX(); var touchY = e.GetY(); @@ -124,22 +114,22 @@ public override bool OnTouchEvent(MotionEvent e) { Points = new System.Collections.ObjectModel.ObservableCollection() { - new Point(touchX, touchY) + new (touchX, touchY) } }; - drawCanvas.DrawColor(Element.BackgroundColor.ToAndroid(), PorterDuff.Mode.Clear!); + drawCanvas?.DrawColor(Element.BackgroundColor.ToAndroid(), PorterDuff.Mode.Clear!); drawPath.MoveTo(touchX, touchY); break; case MotionEventActions.Move: - if (touchX > 0 && touchY > 0 && touchX < drawCanvas.Width && touchY < drawCanvas.Height) + if (touchX > 0 && touchY > 0 && touchX < drawCanvas?.Width && touchY < drawCanvas?.Height) drawPath.LineTo(touchX, touchY); currentLine?.Points.Add(new Point(touchX, touchY)); break; case MotionEventActions.Up: Parent?.RequestDisallowInterceptTouchEvent(false); - drawCanvas.DrawPath(drawPath, drawPaint); + drawCanvas?.DrawPath(drawPath, drawPaint); drawPath.Reset(); if (currentLine != null) { @@ -168,7 +158,7 @@ public override bool OnInterceptTouchEvent(MotionEvent ev) return base.OnInterceptTouchEvent(ev); } - IList NormalizePoints(IList points) + IList NormalizePoints(IEnumerable points) { var newPoints = new List(); foreach (var point in points) @@ -201,8 +191,11 @@ IList NormalizePoints(IList points) return newPoints; } - void LoadLines(in Canvas drawCanvas) + void LoadLines() { + if (drawCanvas is null) + return; + drawCanvas.DrawColor(Element.BackgroundColor.ToAndroid(), PorterDuff.Mode.Clear!); drawPath.Reset(); var lines = Element.Lines;