我正在创建一个充满按钮的网格。现在我希望这个网格能够响应并且按钮是方形的。我想要创建的东西看起来像iOS或Android主屏幕(只是按钮)。
Grid grid = new Grid
{
HorizontalOptions = LayoutOptions.StartAndExpand,
RowSpacing = 15,
ColumnSpacing = 15,
ColumnDefinitions =
{
new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) },
new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) },
new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }
}
};
for (int i = 0; i < 12; i++)
{
MonitorButton button = new MonitorButton();
grid.Children.Add(button, i % 3, i / 3);
}
this.Content = new ScrollView
{
Padding = new Thickness(15),
Orientation = ScrollOrientation.Vertical,
Content = grid
};
所以就在这里我正在创建一个包含3列的网格,其中包含12个MonitorButtons(背景上带有图像的按钮)。看起来没问题。现在,当我以横向模式打开屏幕时,屏幕会充满矩形,因为列数仍然相同...... 我怎么解决这个问题?我希望有某种动态可能性(例如:itemscontrol @ XAML)。
答案 0 :(得分:0)
当您旋转屏幕时,当前页面会自行调整大小,因此它会在您的页面中调用OnSizeRequest方法。如果覆盖该方法,则可以检测大小和方向。
YourPage.cs || YourPage.xaml.cs 强>
protected override SizeRequest OnSizeRequest(double widthConstraint, double heightConstraint)
{
if(widthConstraint>heightConstraint)
{
//landscape mode
//set your grid row & columndefinitions
}
else
{
//portait mode
//set your grid row & columndefinitions
}
return base.OnSizeRequest(widthConstraint, heightConstraint);
}
答案 1 :(得分:0)
我认为这个自定义(自定义网格控制)网格将更好用,它有命令,因此您可以识别哪个项目被点击,因此我认为您的UI上也可能不需要这么多按钮。 并且您可以在网格单元格中添加您想要的任何控件(在Square中添加按钮)
GridView.Xaml
<?xml version="1.0" encoding="utf-8" ?>
<Grid xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Test.Controls.GridView">
</Grid>
GridView.Xaml.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Test.Views;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace Test.Controls
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class GridView : Grid
{
public GridView()
{
InitializeComponent();
for (var i = 0; i < MaxColumns; i++)
ColumnDefinitions.Add(new ColumnDefinition());
}
public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create<GridView, object>(p => p.CommandParameter, null);
public static readonly BindableProperty CommandProperty = BindableProperty.Create<GridView, ICommand>(p => p.Command, null);
public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create<GridView, IEnumerable<object>>(p => p.ItemsSource, null, BindingMode.OneWay, null, (bindable, oldValue, newValue) => { ((GridView)bindable).BuildTiles(newValue); });
private int _maxColumns = 2;
private float _tileHeight = 0;
public Type ItemTemplate { get; set; } = typeof(SubControlsView);
public int MaxColumns
{
get { return _maxColumns; }
set { _maxColumns = value; }
}
public float TileHeight
{
get { return _tileHeight; }
set { _tileHeight = value; }
}
public object CommandParameter
{
get { return GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
}
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
public IEnumerable<object> ItemsSource
{
get { return (IEnumerable<object>)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public void BuildTiles(IEnumerable<object> tiles)
{
try
{
if (tiles == null || tiles.Count() == 0)
Children?.Clear();
// Wipe out the previous row definitions if they're there.
RowDefinitions?.Clear();
var enumerable = tiles as IList ?? tiles.ToList();
var numberOfRows = Math.Ceiling(enumerable.Count / (float)MaxColumns);
for (var i = 0; i < numberOfRows; i++)
RowDefinitions?.Add(new RowDefinition { Height = TileHeight });
for (var index = 0; index < enumerable.Count; index++)
{
var column = index % MaxColumns;
var row = (int)Math.Floor(index / (float)MaxColumns);
var tile = BuildTile(enumerable[index]);
Children?.Add(tile, column, row);
}
}
catch
{ // can throw exceptions if binding upon disposal
}
}
private Layout BuildTile(object item1)
{
var buildTile = (Layout)Activator.CreateInstance(ItemTemplate, item1);
buildTile.InputTransparent = false;
var tapGestureRecognizer = new TapGestureRecognizer
{
Command = Command,
CommandParameter = item1,
NumberOfTapsRequired = 1
};
buildTile?.GestureRecognizers.Add(tapGestureRecognizer);
return buildTile;
}
}
}
在这里,您可以创建内部UI(视图)。即每个网格方块的内部视图。在这个例子中,我只添加了一个标签。
SubControlsView.Xaml
<?xml version="1.0" encoding="utf-8" ?>
<Grid xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Test.Views.SubControlsView" BackgroundColor="CornflowerBlue">
<StackLayout VerticalOptions="CenterAndExpand">
<!--You can add any controls which you want-->
<!--<Label Text="{Binding id}" HorizontalOptions="CenterAndExpand" TextColor="White" />-->
</StackLayout>
</Grid>
SubControlsView.Xaml.cs
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace Test.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class SubControlsView : Grid
{
public SubControlsView()
{
InitializeComponent();
}
public SubControlsView(object item)
{
InitializeComponent();
BindingContext = item;
}
}
}
然后在任何地方使用此控件。即在任何内容页面上。这将是您的实际视图(仪表板)
SubCarriers.Xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:control="clr-namespace:Test.Controls"
x:Class="Test.Views.SubCarriers" Title="Details Dashboard">
<ContentPage.Content>
<ScrollView Margin="5">
<control:GridView HorizontalOptions="FillAndExpand"
Grid.Row="1"
VerticalOptions="FillAndExpand"
RowSpacing="5"
ColumnSpacing="5"
MaxColumns="2"
ItemsSource="{Binding SubCarriersCnt}"
CommandParameter="{Binding SubCarriersCnt}"
Command="{Binding ClickCommand}"
IsClippedToBounds="False">
<control:GridView.TileHeight>
<OnPlatform x:TypeArguments="x:Single"
iOS="60"
Android="90"
WinPhone="90" />
</control:GridView.TileHeight>
</control:GridView>
</ScrollView>
</ContentPage.Content>
</ContentPage>
然后将ViewModel绑定到您的视图。并在YourViewModel中实现ClickCommand
SubCarriers.Xaml.cs
using System;
using Test.ViewModels;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using CommonUtility;
namespace Test.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class SubCarriers : ContentPage
{
private YourViewModel viewModel;
public SubCarriers()
{
InitializeComponent();
this.BindingContext = new SubCarriersViewModel();
viewModel = (YourViewModel)this.BindingContext;
}
}
}