using Microsoft.Maui.Controls; using Microsoft.Maui.Graphics; using System; namespace NotesDataAnalyst { public partial class ResizableCanvasPage : ContentPage { private const double InitialWidth = 150; private const double InitialHeight = 100; private double startX, startY; public ResizableCanvasPage() { InitializeComponent(); } // Метод для добавления объекта на холст private void AddResizableObject(double x, double y) { // Создание Frame для графического объекта var resizableFrame = new Frame { BackgroundColor = Colors.LightBlue, BorderColor = Colors.DarkBlue, CornerRadius = 8, WidthRequest = InitialWidth, HeightRequest = InitialHeight }; // Обработка перемещения объекта var panGesture = new PanGestureRecognizer(); panGesture.PanUpdated += (s, e) => OnDragPanUpdated(s, e, resizableFrame); resizableFrame.GestureRecognizers.Add(panGesture); // Создание ручки для изменения размера var resizeHandle = new BoxView { BackgroundColor = Colors.Gray, WidthRequest = 20, HeightRequest = 20 }; // Обработка изменения размера объекта var resizePanGesture = new PanGestureRecognizer(); resizePanGesture.PanUpdated += (s, e) => OnResizePanUpdated(s, e, resizableFrame, resizeHandle); resizeHandle.GestureRecognizers.Add(resizePanGesture); // Позиционирование объекта и ручки AbsoluteLayout.SetLayoutBounds(resizableFrame, new Rect(x, y, InitialWidth, InitialHeight)); CanvasLayout.Children.Add(resizableFrame); CanvasLayout.Children.Add(resizeHandle); UpdateResizeHandlePosition(resizableFrame, resizeHandle); } // Обработка перемещения объекта private void OnDragPanUpdated(object sender, PanUpdatedEventArgs e, Frame frame) { if (e.StatusType == GestureStatus.Started) { 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)); UpdateResizeHandlePosition(frame, CanvasLayout.Children[CanvasLayout.Children.IndexOf(frame) + 1] as BoxView); } } // Обработка изменения размера объекта private void OnResizePanUpdated(object sender, PanUpdatedEventArgs e, Frame frame, BoxView resizeHandle) { if (e.StatusType == GestureStatus.Started) { 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; UpdateResizeHandlePosition(frame, resizeHandle); } } // Метод для фиксации позиции ручки в углу объекта private void UpdateResizeHandlePosition(Frame frame, BoxView resizeHandle) { var frameBounds = AbsoluteLayout.GetLayoutBounds(frame); double x = frameBounds.X + frame.WidthRequest - resizeHandle.WidthRequest / 2; double y = frameBounds.Y + frame.HeightRequest - resizeHandle.HeightRequest / 2; AbsoluteLayout.SetLayoutBounds(resizeHandle, new Rect(x, y, resizeHandle.WidthRequest, resizeHandle.HeightRequest)); } // Добавление объектов на холст при запуске protected override void OnAppearing() { base.OnAppearing(); AddResizableObject(100, 100); AddResizableObject(400, 200); AddResizableObject(700, 400); } } }