因为C# Maui还没有把GridSplitter加入到正式支持,但是这个也不是很重要,自己实现一个就行了。继承Border可实现多种样式。
GridSplitter.cs代码
using Microsoft.Maui.Controls.Shapes;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Shares.Utility
{
public class GridSplitter : Border
{
private double positionX;
private double positionY;
public bool IsRowSplitter { get; set; }
public double CornerRadius { get; set; }
public GridSplitter()
{
// 添加拖拽手势识别器
var panGesture = new PanGestureRecognizer();
panGesture.PanUpdated += OnPanUpdated;
GestureRecognizers.Add(panGesture);
StrokeShape = new RoundRectangle { CornerRadius = CornerRadius };
}
private void OnPanUpdated(object? sender, PanUpdatedEventArgs e)
{
switch (e.StatusType)
{
case GestureStatus.Running:
var totalX = e.TotalX - positionX;
var totalY = e.TotalY - positionY;
UpdateGrid(totalX, totalY);
positionX = e.TotalX;
positionY = e.TotalY;
break;
case GestureStatus.Started:
case GestureStatus.Completed:
case GestureStatus.Canceled:
break;
}
}
public void UpdateGrid(double dragOffsetX, double dragOffsetY)
{
if (Parent as Grid == null)
{
return;
}
if (IsRowSplitter)
{
UpdateRow(dragOffsetY);
}
else
UpdateColumn(dragOffsetX);
(this.Parent as Grid)?.InvalidateMeasure(); // 触发重新布局
}
private void UpdateRow(double offsetY)
{
if (offsetY == 0)
{
return;
}
Grid? grid = Parent as Grid;
var row = Grid.GetRow(this);
int rowCount = grid!.RowDefinitions.Count();
if (rowCount <= 1 ||
row == 0 ||
row == rowCount - 1 ||
row + Grid.GetRowSpan(this) >= rowCount)
{
return;
}
RowDefinition rowAbove = grid.RowDefinitions[row - 1];
double actualHeight = GetRowDefinitionActualHeight(rowAbove) + offsetY;
if (actualHeight < 0)
{
actualHeight = 0;
}
rowAbove.Height = new GridLength(actualHeight);
}
private void UpdateColumn(double offsetX)
{
if (offsetX == 0)
{
return;
}
Grid? grid = Parent as Grid;
int column = Grid.GetColumn(this);
int columnCount = grid!.ColumnDefinitions.Count();
if (columnCount <= 1 ||
column == 0 ||
column == columnCount - 1 ||
column + Grid.GetColumnSpan(this) >= columnCount)
{
return;
}
ColumnDefinition columnLeft = grid.ColumnDefinitions[column - 1];
double actualWidth = GetColumnDefinitionActualWidth(columnLeft) + offsetX;
if (actualWidth < 0)
{
actualWidth = 0;
}
columnLeft.Width = new GridLength(actualWidth);
}
private double GetRowDefinitionActualHeight(RowDefinition row)
{
double actualHeight;
if (row.Height.IsAbsolute)
{
actualHeight = row.Height.Value;
}
else
{
actualHeight = (double)row.GetType().GetRuntimeProperties().First((p) => p.Name == "ActualHeight").GetValue(row)!;
if (actualHeight == 0)
{
Grid? grid = Parent as Grid;
foreach (var child in grid!.Children)
{
if (grid.GetRow(child)<grid.GetRow(this) && grid.GetColumn(child) == 0 && child is View v)
actualHeight += v.Height;
}
}
}
return actualHeight;
}
private double GetColumnDefinitionActualWidth(ColumnDefinition column)
{
double actualWidth;
if (column.Width.IsAbsolute)
{
actualWidth = column.Width.Value;
}
else
{
actualWidth = (double)column.GetType().GetRuntimeProperties().First((p) => p.Name == "ActualWidth").GetValue(column)!;
if (actualWidth == 0)
{
Grid? grid = Parent as Grid;
foreach (var child in grid!.Children)
{
if (grid.GetColumn(child) < grid.GetColumn(this) && grid.GetRow(child) == 0 && child is View v)
actualWidth += v.Width;
}
}
}
return actualWidth;
}
}
}
SplitWindow.xaml的代码如下
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:Shares.Utility;assembly=Shares" x:Class="MauiViews.MauiDemos.Book._03.SplitWindow" Title="SplitWindow" HeightRequest="300" WidthRequest="300"> <Grid RowDefinitions="*,auto, *" ColumnDefinitions="100,auto,100"> <Button Margin="3" Text="Left"/> <Button Grid.Column="2" Margin="3" Text="Right"/> <Button Grid.Row="2" Grid.Column="0" Margin="3" Text="Left"/> <Button Grid.Row="2" Grid.Column="2" Margin="3" Text="Right"/> <local:GridSplitter Grid.Row="1" Grid.ColumnSpan="3" BackgroundColor="DarkGray" CornerRadius="30" HeightRequest="6" IsRowSplitter="True"/> </Grid> </ContentPage>
对应的cs代码是默认,运行效果。

浙公网安备 33010602011771号