前提・実現したいこと
Xamarin.FormsでGridのセル内にボタンを複数設置して、セルの横幅が不足した場合に
複数行に回り込んで描画するGridの行を複数設置したい。
発生している問題・エラーメッセージ
本家のサンプル を参考に、ボタンの回り込みはカスタムレイアウトの作成で対応できそうなのですが、
ボタンが複数行になった場合、Gridの高さが変わってしまい、Gridのセルが縦方向にはみ出てしまいます。
※下図参照
Gridの高さが、ボタンの表示内容に応じて動的に設定されるようにしたいです。
該当のソースコード
Githubにリポジトリを作成してありますので、こちらを参照いただきたいのですが
主だった修正は下記2ファイルです。
WrapLayout.cs
C#
1using System; 2using System.Collections.Generic; 3using Xamarin.Forms; 4 5namespace ImageWrapLayout 6{ 7 public class WrapLayout : Layout<View> 8 { 9 public static readonly BindableProperty ColumnSpacingProperty = BindableProperty.Create( 10 "ColumnSpacing", 11 typeof(double), 12 typeof(WrapLayout), 13 2.0, 14 propertyChanged: (bindable, oldvalue, newvalue) => 15 { 16 ((WrapLayout)bindable).InvalidateLayout(); 17 }); 18 19 public static readonly BindableProperty RowSpacingProperty = BindableProperty.Create( 20 "RowSpacing", 21 typeof(double), 22 typeof(WrapLayout), 23 2.0, 24 propertyChanged: (bindable, oldvalue, newvalue) => 25 { 26 ((WrapLayout)bindable).InvalidateLayout(); 27 }); 28 29 public double ColumnSpacing 30 { 31 set { SetValue(ColumnSpacingProperty, value); } 32 get { return (double)GetValue(ColumnSpacingProperty); } 33 } 34 35 public double RowSpacing 36 { 37 set { SetValue(RowSpacingProperty, value); } 38 get { return (double)GetValue(RowSpacingProperty); } 39 } 40 41 protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint) 42 { 43 // 対象要素のheightの設定 44 // widthはwidthConstraintの値 45 // ※実質1行の高さは同じなので、高さは(1行の高さ*行数)+((行数-1)*スペース) となる 46 double width = widthConstraint; 47 48 int countChildren = Children.Count; 49 int countRows = 1; 50 double tmpWidthPerRow = 0; 51 double? heightPerRow = null; 52 foreach (View child in Children) 53 { 54 // 子要素のサイズを取得 55 SizeRequest childSizeRequest = child.Measure(Double.PositiveInfinity, Double.PositiveInfinity); 56 57 // 1行の幅が全体幅を上回れば行を追加 58 tmpWidthPerRow += childSizeRequest.Request.Width; 59 if (tmpWidthPerRow >= width) 60 { 61 // 1行幅のリセット 62 tmpWidthPerRow = childSizeRequest.Request.Width; 63 64 // 行を1行追加 65 countRows++; 66 } 67 68 // 1行の高さを保存 69 if (!heightPerRow.HasValue) 70 { 71 heightPerRow = childSizeRequest.Request.Height; 72 } 73 } 74 75 // 高さの設定 76 double height = (double)heightPerRow * countRows + RowSpacing * (countRows - 1); 77 78 return new SizeRequest(new Size(width, height)); 79 } 80 81 protected override void LayoutChildren(double x, double y, double width, double height) 82 { 83 double xChild = x; 84 double yChild = y; 85 double tmpWidthPerRow = 0; 86 foreach (View child in Children) 87 { 88 // 子要素のサイズを取得 89 SizeRequest childSizeRequest = child.Measure(Double.PositiveInfinity, Double.PositiveInfinity); 90 91 // 1行の幅が全体幅を上回れば次の行で表示 92 tmpWidthPerRow += childSizeRequest.Request.Width; 93 if (tmpWidthPerRow >= width) 94 { 95 tmpWidthPerRow = childSizeRequest.Request.Width; 96 xChild = x; 97 yChild += RowSpacing + childSizeRequest.Request.Height; 98 } 99 100 // カラムの表示位置の設定 101 LayoutChildIntoBoundingRegion(child, new Rectangle(new Point(xChild, yChild), new Size(childSizeRequest.Request.Width,childSizeRequest.Request.Height))); 102 103 // カラムのx座標を追加 104 xChild += childSizeRequest.Request.Width + ColumnSpacing; 105 } 106 } 107 } 108} 109
ImageWrapLayoutPage.xaml ※コードビハインドはInitializeComponent()のみ
xml
1<?xml version="1.0" encoding="utf-8"?> 2<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 3 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 4 xmlns:local="clr-namespace:ImageWrapLayout" 5 x:Class="ImageWrapLayout.ImageWrapLayoutPage" 6 BackgroundColor="#FFF"> 7 <ScrollView> 8 <StackLayout Margin="20,20,20,20"> 9 <Grid BackgroundColor="#6d6d6d" ColumnSpacing="1" RowSpacing="1" 10 Padding="1" x:Name="DynamicGrid"> 11 <Grid.RowDefinitions> 12 <RowDefinition Height="Auto"/> 13 <RowDefinition Height="Auto"/> 14 <RowDefinition Height="Auto"/> 15 </Grid.RowDefinitions> 16 <Grid.ColumnDefinitions> 17 <ColumnDefinition Width="0.2*"/> 18 <ColumnDefinition Width="0.8*"/> 19 </Grid.ColumnDefinitions> 20 21 <BoxView Grid.Row="0" Grid.Column="0" BackgroundColor="Gray"/> 22 <Label Grid.Row="0" Grid.Column="0" Text="項目A" TextColor="#FFF" 23 HorizontalOptions="Center" VerticalOptions="Center"/> 24 <local:WrapLayout Grid.Row="0" Grid.Column="1" 25 BackgroundColor="#FFF" 26 Padding="5"> 27 <Button Text="111111"/> 28 <Button Text="222222"/> 29 <Button Text="333333"/> 30 <Button Text="444444"/> 31 <Button Text="555555"/> 32 <Button Text="666666"/> 33 <Button Text="777777"/> 34 <Button Text="888888"/> 35 <Button Text="999999"/> 36 </local:WrapLayout> 37 38 <BoxView Grid.Row="1" Grid.Column="0" BackgroundColor="Gray"/> 39 <Label Grid.Row="1" Grid.Column="0" Text="項目B" TextColor="#FFF" 40 HorizontalOptions="Center" VerticalOptions="Center"/> 41 <local:WrapLayout Grid.Row="1" Grid.Column="1" 42 BackgroundColor="#FFF" 43 Padding="5"> 44 <Button Text="111111"/> 45 <Button Text="222222"/> 46 <Button Text="333333"/> 47 <Button Text="444444"/> 48 <Button Text="555555"/> 49 <Button Text="666666"/> 50 <Button Text="777777"/> 51 <Button Text="888888"/> 52 <Button Text="999999"/> 53 </local:WrapLayout> 54 55 <BoxView Grid.Row="2" Grid.Column="0" BackgroundColor="Gray"/> 56 <Label Grid.Row="2" Grid.Column="0" Text="項目C" TextColor="#FFF" 57 HorizontalOptions="Center" VerticalOptions="Center"/> 58 <local:WrapLayout Grid.Row="2" Grid.Column="1" 59 BackgroundColor="#FFF" 60 Padding="5"> 61 <Button Text="111111"/> 62 <Button Text="222222"/> 63 <Button Text="333333"/> 64 <Button Text="444444"/> 65 <Button Text="555555"/> 66 <Button Text="666666"/> 67 <Button Text="777777"/> 68 <Button Text="888888"/> 69 <Button Text="999999"/> 70 </local:WrapLayout> 71 </Grid> 72 <Label Text="テーブル下部のラベル1"/> 73 <Label Text="テーブル下部のラベル2"/> 74 </StackLayout> 75 </ScrollView> 76</ContentPage>
補足情報
- Visual Studio for Mac 7.4.2
- Xamarin.Forms 2.5.0.280555
- 検証端末: Nexus7(Android6.0.1)

バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/04/19 04:03