3

我目前正在创建一个充满按钮的网格。现在我希望这个网格能够响应并且按钮是方形的。我想要创建的东西看起来像一个 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)。

4

2 回答 2

0

当您旋转屏幕时,当前页面会自行调整大小,因此它会在您的页面中调用 OnSizeRequest 方法。如果覆盖该方法,则可以检测大小和方向。

你的页面.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);
}
于 2015-04-14T05:25:38.087 回答
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(视图)。即每个方格的内部视图。在这个例子中,我只添加了一个标签。

子控件视图.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;
        }
    }
}

然后在任何你想要的地方使用这个控件。即在任何内容页面上。这将是您的实际视图(仪表板)

子载体.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

子载体.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;
        }

    }
}
于 2017-07-26T05:56:53.977 回答