From c3fc86815608eedd434516efaa647b5aac8bda05 Mon Sep 17 00:00:00 2001 From: ARCHI86 Date: Mon, 11 Nov 2024 18:07:11 +0300 Subject: [PATCH] =?UTF-8?q?=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AppShell.xaml | 2 +- ResizableCanvasPage.xaml.cs | 114 +++++++++++++++++++----------------- 2 files changed, 61 insertions(+), 55 deletions(-) diff --git a/AppShell.xaml b/AppShell.xaml index 96d0e53..ec82c4e 100644 --- a/AppShell.xaml +++ b/AppShell.xaml @@ -10,7 +10,7 @@ - + diff --git a/ResizableCanvasPage.xaml.cs b/ResizableCanvasPage.xaml.cs index f206d16..47c8f62 100644 --- a/ResizableCanvasPage.xaml.cs +++ b/ResizableCanvasPage.xaml.cs @@ -1,6 +1,5 @@ using Microsoft.Maui.Controls; using Microsoft.Maui.Graphics; -using Microsoft.Maui.Layouts; using System; namespace NotesDataAnalyst @@ -10,7 +9,6 @@ namespace NotesDataAnalyst private const double InitialWidth = 150; private const double InitialHeight = 100; private double startX, startY; - private bool isResizing; public ResizableCanvasPage() { @@ -27,103 +25,111 @@ namespace NotesDataAnalyst CornerRadius = 8, WidthRequest = InitialWidth, HeightRequest = InitialHeight, - Padding = 0, - HasShadow = true + Padding = 0, // Óáèðàåì âíóòðåííèå îòñòóïû + Content = new Grid() // Èñïîëüçóåì Grid äëÿ äîáàâëåíèÿ ñîäåðæèìîãî è ðó÷êè }; - var content = new Label + // Ñîçäàåì ñîäåðæèìîå âíóòðè ôðåéìà + var content = new StackLayout { - Text = "Resizable Object", - HorizontalOptions = LayoutOptions.Center, - VerticalOptions = LayoutOptions.Center + BackgroundColor = Colors.LightBlue, + Children = + { + new Label { Text = "Resizable Object", HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center } + } }; - resizableFrame.Content = content; - - // Ñîçäàåì ðó÷êó äëÿ èçìåíåíèÿ ðàçìåðà var resizeHandle = new BoxView { BackgroundColor = Colors.Gray, WidthRequest = 20, - HeightRequest = 20, - HorizontalOptions = LayoutOptions.End, - VerticalOptions = LayoutOptions.End + HeightRequest = 20 }; - // Ñîçäàåì ñëîé AbsoluteLayout äëÿ ðó÷êè è ôðåéìà - var layout = new AbsoluteLayout(); - AbsoluteLayout.SetLayoutBounds(resizableFrame, new Rect(0, 0, InitialWidth, InitialHeight)); - layout.Children.Add(resizableFrame); + // Ñîçäàåì Grid âíóòðè Frame + var grid = (Grid)resizableFrame.Content; - // Ïîçèöèîíèðóåì ðó÷êó - AbsoluteLayout.SetLayoutFlags(resizeHandle, AbsoluteLayoutFlags.PositionProportional); - AbsoluteLayout.SetLayoutBounds(resizeHandle, new Rect(1, 1, 20, 20)); - layout.Children.Add(resizeHandle); + // Íàñòðîèì ñåòêó: äîáàâèì äâà ñòîëáöà è äâå ñòðîêè + grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Star }); + grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); // äëÿ ðó÷êè + grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Star }); + grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); // äëÿ ðó÷êè - // Äîáàâëÿåì îáðàáîò÷èê ïåðåìåùåíèÿ + // Äîáàâëÿåì ñîäåðæèìîå â ïåðâóþ ÿ÷åéêó (ñòîëáåö 0, ñòðîêà 0) + grid.Children.Add(content); // Áåç óêàçàíèÿ êîëîíîê/ñòðîê + + // Äîáàâëÿåì ðó÷êó â ïðàâûé íèæíèé óãîë (ñòîëáåö 1, ñòðîêà 1) + grid.Children.Add(resizeHandle); // Áåç óêàçàíèÿ êîëîíîê/ñòðîê + + // Óñòàíàâëèâàåì ñòðîêó è êîëîíêó äëÿ ðó÷êè + Grid.SetRow(resizeHandle, 1); + Grid.SetColumn(resizeHandle, 1); + + // Äîáàâëÿåì ïàíîðàìó äëÿ ïåðåìåùåíèÿ îáúåêòà var panGesture = new PanGestureRecognizer(); - panGesture.PanUpdated += (s, e) => OnDragPanUpdated(s, e, layout); + panGesture.PanUpdated += (s, e) => OnDragPanUpdated(s, e, resizableFrame); resizableFrame.GestureRecognizers.Add(panGesture); - // Äîáàâëÿåì îáðàáîò÷èê äëÿ èçìåíåíèÿ ðàçìåðà + // Äîáàâëÿåì ïàíîðàìó äëÿ èçìåíåíèÿ ðàçìåðà var resizePanGesture = new PanGestureRecognizer(); - resizePanGesture.PanUpdated += (s, e) => OnResizePanUpdated(s, e, layout); + resizePanGesture.PanUpdated += (s, e) => OnResizePanUpdated(s, e, resizableFrame, resizeHandle); resizeHandle.GestureRecognizers.Add(resizePanGesture); - // Óñòàíàâëèâàåì íà÷àëüíóþ ïîçèöèþ - AbsoluteLayout.SetLayoutBounds(layout, new Rect(x, y, InitialWidth, InitialHeight)); - CanvasLayout.Children.Add(layout); + // Óñòàíàâëèâàåì ïîçèöèþ ôðåéìà + AbsoluteLayout.SetLayoutBounds(resizableFrame, new Rect(x, y, InitialWidth, InitialHeight)); + CanvasLayout.Children.Add(resizableFrame); + + // Îáíîâëÿåì ïîçèöèþ ðó÷êè + UpdateResizeHandlePosition(resizableFrame, resizeHandle); } - // Ëîãèêà ïåðåìåùåíèÿ - private void OnDragPanUpdated(object sender, PanUpdatedEventArgs e, AbsoluteLayout layout) + private void OnDragPanUpdated(object sender, PanUpdatedEventArgs e, Frame frame) { - if (isResizing) return; - if (e.StatusType == GestureStatus.Started) { - startX = AbsoluteLayout.GetLayoutBounds(layout).X; - startY = AbsoluteLayout.GetLayoutBounds(layout).Y; + startX = AbsoluteLayout.GetLayoutBounds(frame).X; + startY = AbsoluteLayout.GetLayoutBounds(frame).Y; } else if (e.StatusType == GestureStatus.Running) { double x = startX + e.TotalX; double y = startY + e.TotalY; + AbsoluteLayout.SetLayoutBounds(frame, new Rect(x, y, frame.WidthRequest, frame.HeightRequest)); - // Îáíîâëåíèå UI ÷åðåç Dispatcher - Dispatcher.Dispatch(() => - { - AbsoluteLayout.SetLayoutBounds(layout, new Rect(x, y, layout.WidthRequest, layout.HeightRequest)); - }); + // Îáíîâëÿåì ïîçèöèþ ðó÷êè + var resizeHandle = (BoxView)((Grid)frame.Content).Children[1]; + UpdateResizeHandlePosition(frame, resizeHandle); } } - // Ëîãèêà èçìåíåíèÿ ðàçìåðà - private void OnResizePanUpdated(object sender, PanUpdatedEventArgs e, AbsoluteLayout layout) + private void OnResizePanUpdated(object sender, PanUpdatedEventArgs e, Frame frame, BoxView resizeHandle) { - isResizing = true; if (e.StatusType == GestureStatus.Started) { - startX = layout.WidthRequest; - startY = layout.HeightRequest; + startX = frame.WidthRequest; + startY = frame.HeightRequest; } else if (e.StatusType == GestureStatus.Running) { double newWidth = Math.Max(50, startX + e.TotalX); double newHeight = Math.Max(50, startY + e.TotalY); + frame.WidthRequest = newWidth; + frame.HeightRequest = newHeight; - Dispatcher.Dispatch(() => - { - layout.WidthRequest = newWidth; - layout.HeightRequest = newHeight; - }); - } - else if (e.StatusType == GestureStatus.Completed || e.StatusType == GestureStatus.Canceled) - { - isResizing = false; + // Îáíîâëÿåì ïîçèöèþ ðó÷êè ïîñëå èçìåíåíèÿ ðàçìåðîâ + UpdateResizeHandlePosition(frame, resizeHandle); } } + private void UpdateResizeHandlePosition(Frame frame, BoxView resizeHandle) + { + var frameBounds = AbsoluteLayout.GetLayoutBounds(frame); + double x = frameBounds.X + frame.WidthRequest - resizeHandle.WidthRequest; + double y = frameBounds.Y + frame.HeightRequest - resizeHandle.HeightRequest; + + AbsoluteLayout.SetLayoutBounds(resizeHandle, new Rect(x, y, resizeHandle.WidthRequest, resizeHandle.HeightRequest)); + } + protected override void OnAppearing() { base.OnAppearing();