NoteMAUI/ResizableCanvasPage.xaml.cs
2024-11-10 23:04:15 +03:00

135 lines
4.7 KiB
C#

using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Layouts;
using System;
namespace NotesDataAnalyst
{
public partial class ResizableCanvasPage : ContentPage
{
private const double InitialWidth = 150;
private const double InitialHeight = 100;
private double startX, startY;
private bool isResizing;
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,
Padding = 0,
HasShadow = true
};
var content = 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
};
// Ñîçäàåì ñëîé AbsoluteLayout äëÿ ðó÷êè è ôðåéìà
var layout = new AbsoluteLayout();
AbsoluteLayout.SetLayoutBounds(resizableFrame, new Rect(0, 0, InitialWidth, InitialHeight));
layout.Children.Add(resizableFrame);
// Ïîçèöèîíèðóåì ðó÷êó
AbsoluteLayout.SetLayoutFlags(resizeHandle, AbsoluteLayoutFlags.PositionProportional);
AbsoluteLayout.SetLayoutBounds(resizeHandle, new Rect(1, 1, 20, 20));
layout.Children.Add(resizeHandle);
// Äîáàâëÿåì îáðàáîò÷èê ïåðåìåùåíèÿ
var panGesture = new PanGestureRecognizer();
panGesture.PanUpdated += (s, e) => OnDragPanUpdated(s, e, layout);
resizableFrame.GestureRecognizers.Add(panGesture);
// Äîáàâëÿåì îáðàáîò÷èê äëÿ èçìåíåíèÿ ðàçìåðà
var resizePanGesture = new PanGestureRecognizer();
resizePanGesture.PanUpdated += (s, e) => OnResizePanUpdated(s, e, layout);
resizeHandle.GestureRecognizers.Add(resizePanGesture);
// Óñòàíàâëèâàåì íà÷àëüíóþ ïîçèöèþ
AbsoluteLayout.SetLayoutBounds(layout, new Rect(x, y, InitialWidth, InitialHeight));
CanvasLayout.Children.Add(layout);
}
// Ëîãèêà ïåðåìåùåíèÿ
private void OnDragPanUpdated(object sender, PanUpdatedEventArgs e, AbsoluteLayout layout)
{
if (isResizing) return;
if (e.StatusType == GestureStatus.Started)
{
startX = AbsoluteLayout.GetLayoutBounds(layout).X;
startY = AbsoluteLayout.GetLayoutBounds(layout).Y;
}
else if (e.StatusType == GestureStatus.Running)
{
double x = startX + e.TotalX;
double y = startY + e.TotalY;
// Îáíîâëåíèå UI ÷åðåç Dispatcher
Dispatcher.Dispatch(() =>
{
AbsoluteLayout.SetLayoutBounds(layout, new Rect(x, y, layout.WidthRequest, layout.HeightRequest));
});
}
}
// Ëîãèêà èçìåíåíèÿ ðàçìåðà
private void OnResizePanUpdated(object sender, PanUpdatedEventArgs e, AbsoluteLayout layout)
{
isResizing = true;
if (e.StatusType == GestureStatus.Started)
{
startX = layout.WidthRequest;
startY = layout.HeightRequest;
}
else if (e.StatusType == GestureStatus.Running)
{
double newWidth = Math.Max(50, startX + e.TotalX);
double newHeight = Math.Max(50, startY + e.TotalY);
Dispatcher.Dispatch(() =>
{
layout.WidthRequest = newWidth;
layout.HeightRequest = newHeight;
});
}
else if (e.StatusType == GestureStatus.Completed || e.StatusType == GestureStatus.Canceled)
{
isResizing = false;
}
}
protected override void OnAppearing()
{
base.OnAppearing();
AddResizableObject(100, 100);
AddResizableObject(400, 200);
AddResizableObject(700, 400);
}
}
}