2014-06-26 35 views
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)。

+0

目前在Xamarin.Forms沒有GridView控件。你將不得不計算你的列寬(和間距)並動態添加你的列定義。這將完成使用[模數運算符](http://msdn.microsoft.com/en-us/library/0w4e0fzs.aspx)'%' –

回答

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); 
} 
0

我覺得這個定製(自定義網格控制)電網將更好地使用,其中有命令,以便您可以識別哪些項目被竊聽,所以我想你可能不需要這麼多您的用戶界面上的按鈕也。 ,你可以添加你想要的網格單元內(在廣場就像你已經添加按鈕)

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; 
     } 
    } 
} 

在這裏,你可以控制什麼創建你的內部用戶界面(視圖)。即每個網格正方形的內部視圖。在這個例子中,我只添加了一個標籤。

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> 

然後你的視圖模型綁定到你的觀點。在YourViewModel實現點擊指令

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; 
     } 

    } 
} 
+0

嗨,我已經實現了一切,它的作品除了ClickCommand。我嘗試了幾件事,但無法獲得點擊操作。如果可以,請分享代碼。 – Singhal2