This commit is contained in:
ARCHI86 2024-11-11 18:07:11 +03:00
parent 5dbd13040f
commit c3fc868156
2 changed files with 61 additions and 55 deletions

View file

@ -10,7 +10,7 @@
<!-- Главная страница приложения --> <!-- Главная страница приложения -->
<FlyoutItem Title="Главная" Icon="add.png"> <FlyoutItem Title="Главная" Icon="add.png">
<ShellContent ContentTemplate="{DataTemplate local:GraphPage}" /> <ShellContent ContentTemplate="{DataTemplate local:ResizableCanvasPage}" />
</FlyoutItem> </FlyoutItem>
<!-- Выпадающий список категорий --> <!-- Выпадающий список категорий -->

View file

@ -1,6 +1,5 @@
using Microsoft.Maui.Controls; using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics; using Microsoft.Maui.Graphics;
using Microsoft.Maui.Layouts;
using System; using System;
namespace NotesDataAnalyst namespace NotesDataAnalyst
@ -10,7 +9,6 @@ namespace NotesDataAnalyst
private const double InitialWidth = 150; private const double InitialWidth = 150;
private const double InitialHeight = 100; private const double InitialHeight = 100;
private double startX, startY; private double startX, startY;
private bool isResizing;
public ResizableCanvasPage() public ResizableCanvasPage()
{ {
@ -27,103 +25,111 @@ namespace NotesDataAnalyst
CornerRadius = 8, CornerRadius = 8,
WidthRequest = InitialWidth, WidthRequest = InitialWidth,
HeightRequest = InitialHeight, HeightRequest = InitialHeight,
Padding = 0, Padding = 0, // Óáèðàåì âíóòðåííèå îòñòóïû
HasShadow = true Content = new Grid() // Èñïîëüçóåì Grid äëÿ äîáàâëåíèÿ ñîäåðæèìîãî è ðó÷êè
}; };
var content = new Label // Ñîçäàåì ñîäåðæèìîå âíóòðè ôðåéìà
var content = new StackLayout
{ {
Text = "Resizable Object", BackgroundColor = Colors.LightBlue,
HorizontalOptions = LayoutOptions.Center, Children =
VerticalOptions = LayoutOptions.Center {
new Label { Text = "Resizable Object", HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center }
}
}; };
resizableFrame.Content = content;
// Ñîçäàåì ðó÷êó äëÿ èçìåíåíèÿ ðàçìåðà
var resizeHandle = new BoxView var resizeHandle = new BoxView
{ {
BackgroundColor = Colors.Gray, BackgroundColor = Colors.Gray,
WidthRequest = 20, WidthRequest = 20,
HeightRequest = 20, HeightRequest = 20
HorizontalOptions = LayoutOptions.End,
VerticalOptions = LayoutOptions.End
}; };
// Ñîçäàåì ñëîé AbsoluteLayout äëÿ ðó÷êè è ôðåéìà // Ñîçäàåì Grid âíóòðè Frame
var layout = new AbsoluteLayout(); var grid = (Grid)resizableFrame.Content;
AbsoluteLayout.SetLayoutBounds(resizableFrame, new Rect(0, 0, InitialWidth, InitialHeight));
layout.Children.Add(resizableFrame);
// Ïîçèöèîíèðóåì ðó÷êó // Íàñòðîèì ñåòêó: äîáàâèì äâà ñòîëáöà è äâå ñòðîêè
AbsoluteLayout.SetLayoutFlags(resizeHandle, AbsoluteLayoutFlags.PositionProportional); grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Star });
AbsoluteLayout.SetLayoutBounds(resizeHandle, new Rect(1, 1, 20, 20)); grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); // äëÿ ðó÷êè
layout.Children.Add(resizeHandle); 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(); var panGesture = new PanGestureRecognizer();
panGesture.PanUpdated += (s, e) => OnDragPanUpdated(s, e, layout); panGesture.PanUpdated += (s, e) => OnDragPanUpdated(s, e, resizableFrame);
resizableFrame.GestureRecognizers.Add(panGesture); resizableFrame.GestureRecognizers.Add(panGesture);
// Äîáàâëÿåì îáðàáîò÷èê äëÿ èçìåíåíèÿ ðàçìåðà // Äîáàâëÿåì ïàíîðàìó äëÿ èçìåíåíèÿ ðàçìåðà
var resizePanGesture = new PanGestureRecognizer(); 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); resizeHandle.GestureRecognizers.Add(resizePanGesture);
// Óñòàíàâëèâàåì íà÷àëüíóþ ïîçèöèþ // Óñòàíàâëèâàåì ïîçèöèþ ôðåéìà
AbsoluteLayout.SetLayoutBounds(layout, new Rect(x, y, InitialWidth, InitialHeight)); AbsoluteLayout.SetLayoutBounds(resizableFrame, new Rect(x, y, InitialWidth, InitialHeight));
CanvasLayout.Children.Add(layout); CanvasLayout.Children.Add(resizableFrame);
// Îáíîâëÿåì ïîçèöèþ ðó÷êè
UpdateResizeHandlePosition(resizableFrame, resizeHandle);
} }
// Ëîãèêà ïåðåìåùåíèÿ private void OnDragPanUpdated(object sender, PanUpdatedEventArgs e, Frame frame)
private void OnDragPanUpdated(object sender, PanUpdatedEventArgs e, AbsoluteLayout layout)
{ {
if (isResizing) return;
if (e.StatusType == GestureStatus.Started) if (e.StatusType == GestureStatus.Started)
{ {
startX = AbsoluteLayout.GetLayoutBounds(layout).X; startX = AbsoluteLayout.GetLayoutBounds(frame).X;
startY = AbsoluteLayout.GetLayoutBounds(layout).Y; startY = AbsoluteLayout.GetLayoutBounds(frame).Y;
} }
else if (e.StatusType == GestureStatus.Running) else if (e.StatusType == GestureStatus.Running)
{ {
double x = startX + e.TotalX; double x = startX + e.TotalX;
double y = startY + e.TotalY; double y = startY + e.TotalY;
AbsoluteLayout.SetLayoutBounds(frame, new Rect(x, y, frame.WidthRequest, frame.HeightRequest));
// Îáíîâëåíèå UI ÷åðåç Dispatcher // Îáíîâëÿåì ïîçèöèþ ðó÷êè
Dispatcher.Dispatch(() => var resizeHandle = (BoxView)((Grid)frame.Content).Children[1];
{ UpdateResizeHandlePosition(frame, resizeHandle);
AbsoluteLayout.SetLayoutBounds(layout, new Rect(x, y, layout.WidthRequest, layout.HeightRequest));
});
} }
} }
// Ëîãèêà èçìåíåíèÿ ðàçìåðà private void OnResizePanUpdated(object sender, PanUpdatedEventArgs e, Frame frame, BoxView resizeHandle)
private void OnResizePanUpdated(object sender, PanUpdatedEventArgs e, AbsoluteLayout layout)
{ {
isResizing = true;
if (e.StatusType == GestureStatus.Started) if (e.StatusType == GestureStatus.Started)
{ {
startX = layout.WidthRequest; startX = frame.WidthRequest;
startY = layout.HeightRequest; startY = frame.HeightRequest;
} }
else if (e.StatusType == GestureStatus.Running) else if (e.StatusType == GestureStatus.Running)
{ {
double newWidth = Math.Max(50, startX + e.TotalX); double newWidth = Math.Max(50, startX + e.TotalX);
double newHeight = Math.Max(50, startY + e.TotalY); double newHeight = Math.Max(50, startY + e.TotalY);
frame.WidthRequest = newWidth;
frame.HeightRequest = newHeight;
Dispatcher.Dispatch(() => // Îáíîâëÿåì ïîçèöèþ ðó÷êè ïîñëå èçìåíåíèÿ ðàçìåðîâ
{ UpdateResizeHandlePosition(frame, resizeHandle);
layout.WidthRequest = newWidth;
layout.HeightRequest = newHeight;
});
}
else if (e.StatusType == GestureStatus.Completed || e.StatusType == GestureStatus.Canceled)
{
isResizing = false;
} }
} }
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() protected override void OnAppearing()
{ {
base.OnAppearing(); base.OnAppearing();