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); UpdateResizeHandlePosition(resizableFrame, resizeHandle); CanvasLayout.Children.Add(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) { // Устанавливаем новую позицию, прибавляя изменение по оси X и Y double x = startX + e.TotalX; double y = startY + e.TotalY; AbsoluteLayout.SetLayoutBounds(frame, new Rect(x, y, frame.Width, frame.Height)); } } // Обработчик для изменения размера объекта private void OnResizePanUpdated(object sender, PanUpdatedEventArgs e, Frame frame, BoxView resizeHandle) { if (e.StatusType == GestureStatus.Started) { // Запоминаем начальные размеры объекта startX = frame.Width; startY = frame.Height; } 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) { double x = AbsoluteLayout.GetLayoutBounds(frame).X + frame.WidthRequest - resizeHandle.WidthRequest; double y = AbsoluteLayout.GetLayoutBounds(frame).Y + frame.HeightRequest - resizeHandle.HeightRequest; 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); } } }