-
-
Notifications
You must be signed in to change notification settings - Fork 142
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #568 from enisn/grid-layout
Introduce GridLayout
- Loading branch information
Showing
10 changed files
with
352 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
<?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" | ||
x:Class="UraniumApp.Pages.GridLayoutPage" | ||
xmlns:m="clr-namespace:UraniumUI.Icons.MaterialSymbols;assembly=UraniumUI.Icons.MaterialSymbols" | ||
xmlns:uranium="http://schemas.enisn-projects.io/dotnet/maui/uraniumui" | ||
xmlns:material="http://schemas.enisn-projects.io/dotnet/maui/uraniumui/material" | ||
Title="GridLayoutPage"> | ||
<ContentPage.Resources> | ||
|
||
<x:String x:Key="DocLink">https://enisn-projects.io/docs/en/uranium/latest/themes/material/components/TextField</x:String> | ||
<x:String x:Key="SourceCode"> | ||
<![CDATA[ | ||
<uranium:GridLayout> | ||
<BoxView Color="Blue" /> | ||
<BoxView Color="Green" /> | ||
<BoxView Color="Yellow" /> | ||
<BoxView Color="Red" /> | ||
</uranium:GridLayout> | ||
]]> | ||
</x:String> | ||
<x:String x:Key="SourceCode2"> | ||
<![CDATA[ | ||
<uranium:GridLayout RowCount="3" ColumnCount="3" ColumnGridLength="*" RowGridLength="120" ColumnSpacing="16" RowSpacing="16"> | ||
<BoxView Color="DarkBlue" /> | ||
<BoxView Color="Blue" /> | ||
<BoxView Color="LightBlue" /> | ||
<BoxView Color="Green" /> | ||
<BoxView Color="Yellow" /> | ||
<BoxView Color="Orange" /> | ||
<BoxView Color="Red" /> | ||
<BoxView Color="Pink" /> | ||
</uranium:GridLayout> | ||
]]> | ||
</x:String> | ||
</ContentPage.Resources> | ||
<ScrollView> | ||
<VerticalStackLayout Padding="20"> | ||
|
||
<Label Text="GridLayout" FontSize="Title" /> | ||
<Label Text="UraniumUI.Layouts" FontSize="Micro" Opacity=".6" /> | ||
|
||
<HorizontalStackLayout Padding="0,20"> | ||
<Button Text="Documentation" Command="{x:Static uranium:Commands.OpenLinkCommand}" CommandParameter="{StaticResource DocLink}" StyleClass="OutlinedButton" ImageSource="{FontImageSource Glyph={x:Static m:MaterialSharp.File_open}, FontFamily=MaterialSharp, Color={AppThemeBinding {StaticResource OnBackground}, Dark={StaticResource OnBackgroundDark}}}" /> | ||
<Button Text="Source" StyleClass="OutlinedButton" IsEnabled="False" ImageSource="{FontImageSource Glyph={x:Static m:MaterialSharp.Code}, FontFamily=MaterialSharp, Color={AppThemeBinding {StaticResource OnBackground}, Dark={StaticResource OnBackgroundDark}}}" /> | ||
</HorizontalStackLayout> | ||
|
||
<Label Text="GridLayout is a variation of MAUI Grid with a set of features. You can build a perfect grid without dealing with Grid.Row and Grid.Column properties. You can also bind dynamic items to the grid." /> | ||
|
||
<Border StyleClass="SurfaceContainer,Rounded"> | ||
<VerticalStackLayout> | ||
<uranium:GridLayout> | ||
<uranium:GridLayout.Resources> | ||
<Style TargetType="BoxView"> | ||
<Setter Property="MinimumWidthRequest" Value="120" /> | ||
<Setter Property="MinimumHeightRequest" Value="120" /> | ||
</Style> | ||
</uranium:GridLayout.Resources> | ||
<BoxView Color="Blue" /> | ||
<BoxView Color="Green" /> | ||
<BoxView Color="Yellow" /> | ||
<BoxView Color="Red" /> | ||
</uranium:GridLayout> | ||
|
||
<uranium:ExpanderView> | ||
<uranium:ExpanderView.Header> | ||
<Label Text="Source Code (XAML)" Margin="10" /> | ||
</uranium:ExpanderView.Header> | ||
<uranium:CodeView HeightRequest="120" SourceCode="{StaticResource SourceCode}"/> | ||
</uranium:ExpanderView> | ||
</VerticalStackLayout> | ||
</Border> | ||
|
||
<BoxView StyleClass="Divider" /> | ||
|
||
<Border StyleClass="SurfaceContainer,Rounded"> | ||
<VerticalStackLayout> | ||
<uranium:GridLayout RowCount="3" ColumnCount="3" ColumnGridLength="*" RowGridLength="120" ColumnSpacing="16" RowSpacing="16"> | ||
<BoxView Color="DarkBlue" /> | ||
<BoxView Color="Blue" /> | ||
<BoxView Color="LightBlue" /> | ||
<BoxView Color="Green" /> | ||
<BoxView Color="Yellow" /> | ||
<BoxView Color="Orange" /> | ||
<BoxView Color="Red" /> | ||
<BoxView Color="Pink" /> | ||
</uranium:GridLayout> | ||
|
||
<uranium:ExpanderView> | ||
<uranium:ExpanderView.Header> | ||
<Label Text="Source Code (XAML)" Margin="10" /> | ||
</uranium:ExpanderView.Header> | ||
<uranium:CodeView HeightRequest="120" SourceCode="{StaticResource SourceCode2}"/> | ||
</uranium:ExpanderView> | ||
</VerticalStackLayout> | ||
</Border> | ||
|
||
<BoxView StyleClass="Divider" /> | ||
|
||
</VerticalStackLayout> | ||
</ScrollView> | ||
</ContentPage> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
namespace UraniumApp.Pages; | ||
|
||
public partial class GridLayoutPage : ContentPage | ||
{ | ||
public GridLayoutPage() | ||
{ | ||
InitializeComponent(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
# GridLayout | ||
|
||
The `GridLayout` is a layout that arranges its children in a grid. It is similar to the MAUI Grid, but it manages the layout of its children automatically. The `GridLayout` is a good choice when you want to create a grid of items that can be manages dynamically without defaling with **Grid.Row** and **Grid.Column** properties for each item. Each item you place inside GridLayout will be automatically placed in the next cell of the grid. | ||
|
||
|
||
## Usage | ||
|
||
It is defined in `UraniumUI.Layouts` namespace. You can use it in XAML like this: | ||
|
||
```xml | ||
xmlns:uranium="http://schemas.enisn-projects.io/dotnet/maui/uraniumui" | ||
``` | ||
|
||
Then you can use it with `uranium:GridLayout` tag. | ||
|
||
```xml | ||
<uranium:GridLayout> | ||
<BoxView Color="Blue" /> | ||
<BoxView Color="Green" /> | ||
<BoxView Color="Yellow" /> | ||
<BoxView Color="Red" /> | ||
</uranium:GridLayout> | ||
``` | ||
|
||
The above code will create a grid with 2 columns and 2 rows. The first BoxView will be placed in the first cell, the second BoxView will be placed in the second cell, the third BoxView will be placed in the third cell, and the fourth BoxView will be placed in the fourth cell. | ||
|
||
|
||
## Properties | ||
|
||
- **ColumnCount**: The number of columns in the grid. Default value is 2. | ||
- **RowCount**: The number of rows in the grid. Default value is 2. | ||
- **RowSpacing**: The spacing between rows. Default value is 0. | ||
- **ColumnSpacing**: The spacing between columns. Default value is 0. | ||
- **RowGridLength**: The height of each row. Default value is Auto. | ||
- **ColumnGridLength**: The width of each column. Default value is Auto. | ||
|
||
|
||
|
||
```xml | ||
<uranium:GridLayout Margin="20" | ||
RowCount="2" | ||
ColumnCount="2" | ||
ColumnSpacing="16" | ||
RowSpacing="16" | ||
ColumnGridLength="120" | ||
RowGridLength="120"> | ||
<BoxView Color="Red" /> | ||
<BoxView Color="Green" /> | ||
<BoxView Color="Blue" /> | ||
<BoxView Color="Yellow" /> | ||
</uranium:GridLayout> | ||
``` | ||
|
||
![MAUI GridLayout](images/gridlayout-simple.png) | ||
|
||
|
||
## Span | ||
|
||
You can use the **Grid.RowSpan** and **Grid.ColumnSpan** properties to span an item across multiple rows or columns. | ||
|
||
```xml | ||
<uranium:GridLayout Margin="20" | ||
RowCount="3" | ||
ColumnCount="3" | ||
ColumnSpacing="16" | ||
RowSpacing="16" | ||
ColumnGridLength="120" | ||
RowGridLength="120"> | ||
<BoxView Color="Red" Grid.RowSpan="2" /> | ||
<BoxView Color="Green" Grid.ColumnSpan="2" /> | ||
<BoxView Color="LightBlue" /> | ||
<BoxView Color="Blue" /> | ||
<BoxView Color="DarkBlue" /> | ||
<BoxView Color="Yellow" /> | ||
</uranium:GridLayout> | ||
``` | ||
|
||
![MAUI GridLayout Span](images/gridlayout-spans.png) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
using System.ComponentModel; | ||
using UraniumUI.Extensions; | ||
|
||
namespace UraniumUI.Layouts; | ||
public class GridLayout : Grid | ||
{ | ||
public int RowCount { get => (int)GetValue(RowCountProperty); set => SetValue(RowCountProperty, value); } | ||
|
||
public static readonly BindableProperty RowCountProperty = BindableProperty.Create( | ||
nameof(RowCount), typeof(int), typeof(GridLayout), | ||
defaultValue: 2, | ||
propertyChanged: (bindable, oldValue, newValue) => | ||
{ | ||
if (bindable is GridLayout grid) | ||
{ | ||
grid.SetRowDefinitions(); | ||
} | ||
}); | ||
|
||
public int ColumnCount { get => (int)GetValue(ColumnCountProperty); set => SetValue(ColumnCountProperty, value); } | ||
|
||
public static readonly BindableProperty ColumnCountProperty = BindableProperty.Create( | ||
nameof(ColumnCount), typeof(int), typeof(GridLayout), | ||
defaultValue: 2, | ||
propertyChanged: (bindable, oldValue, newValue) => | ||
{ | ||
if (bindable is GridLayout grid) | ||
{ | ||
grid.SetColumnDefinitions(); | ||
} | ||
}); | ||
|
||
[TypeConverter(typeof(GridLengthTypeConverter))] | ||
public GridLength ColumnGridLength { get => (GridLength)GetValue(ColumnGridLengthProperty); set => SetValue(ColumnGridLengthProperty, value); } | ||
|
||
public static readonly BindableProperty ColumnGridLengthProperty = BindableProperty.Create( | ||
nameof(ColumnGridLength), typeof(GridLength), typeof(GridLayout), GridLength.Auto, | ||
propertyChanged: (bindable, oldValue, newValue) => | ||
{ | ||
if (bindable is GridLayout grid) | ||
{ | ||
grid.SetColumnDefinitions(); | ||
} | ||
}); | ||
|
||
[TypeConverter(typeof(GridLengthTypeConverter))] | ||
public GridLength RowGridLength { get => (GridLength)GetValue(RowGridLengthProperty); set => SetValue(RowGridLengthProperty, value); } | ||
|
||
public static readonly BindableProperty RowGridLengthProperty = BindableProperty.Create( | ||
nameof(RowGridLength), typeof(GridLength), typeof(GridLayout), GridLength.Auto, | ||
propertyChanged: (bindable, oldValue, newValue) => | ||
{ | ||
if (bindable is GridLayout grid) | ||
{ | ||
grid.SetRowDefinitions(); | ||
} | ||
}); | ||
|
||
protected override void OnParentSet() | ||
{ | ||
base.OnParentSet(); | ||
SetDefinitions(); | ||
} | ||
|
||
protected override void OnChildAdded(Element child) | ||
{ | ||
base.OnChildAdded(child); | ||
|
||
var view = child as View; | ||
//this.Children.Remove(view); | ||
|
||
var (row, column) = GetNextAvailablePosition(); | ||
|
||
Grid.SetRow(view, row); | ||
Grid.SetColumn(view, column); | ||
//this.Add(view); | ||
} | ||
|
||
protected virtual void SetDefinitions() | ||
{ | ||
SetColumnDefinitions(); | ||
SetRowDefinitions(); | ||
} | ||
|
||
protected virtual void SetColumnDefinitions() | ||
{ | ||
ColumnDefinitions.Clear(); | ||
for (int i = 0; i < ColumnCount; i++) | ||
{ | ||
ColumnDefinitions.Add(new ColumnDefinition(ColumnGridLength)); | ||
} | ||
} | ||
|
||
protected virtual void SetRowDefinitions() | ||
{ | ||
RowDefinitions.Clear(); | ||
for (int i = 0; i < RowCount; i++) | ||
{ | ||
RowDefinitions.Add(new RowDefinition(RowGridLength)); | ||
} | ||
} | ||
|
||
private (int, int) GetNextAvailablePosition() | ||
{ | ||
for (int row = 0; row < RowCount; row++) | ||
{ | ||
for (int column = 0; column < ColumnCount; column++) | ||
{ | ||
if (IsCellAvailable(row, column)) | ||
{ | ||
return (row, column); | ||
} | ||
} | ||
} | ||
|
||
return (0, 0); | ||
} | ||
|
||
private bool IsCellAvailable(int row, int column) | ||
{ | ||
foreach (var child in Children.Take(Children.Count - 1)) | ||
{ | ||
if (child is View view) | ||
{ | ||
int childRow = (int)view.GetValue(RowProperty); | ||
int childColumn = (int)view.GetValue(ColumnProperty); | ||
int childRowSpan = (int)view.GetValue(RowSpanProperty); | ||
int childColumnSpan = (int)view.GetValue(ColumnSpanProperty); | ||
|
||
if (row >= childRow && row < childRow + childRowSpan && | ||
column >= childColumn && column < childColumn + childColumnSpan) | ||
{ | ||
return false; | ||
} | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
|
||
private static void FindEndPoint(View view, out int row, out int column) | ||
{ | ||
row = (int)view.GetValue(RowProperty); | ||
column = (int)view.GetValue(ColumnProperty); | ||
int rowSpan = (int)view.GetValue(RowSpanProperty); | ||
int columnSpan = (int)view.GetValue(ColumnSpanProperty); | ||
|
||
row += rowSpan; | ||
column += columnSpan; | ||
} | ||
} |