質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.86%

  • C#

    5979questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • Xamarin

    423questions

    Xamarin(ザマリン)は、iPhoneなどのiOSやAndroidで動作し、C# 言語を用いてアプリを開発できるクロスプラットフォーム開発環境です。Xamarin Studioと C# 言語を用いて、 iOS と Android の両方の開発を行うことができます。

Xamarin.FormsでGridのRowの高さが動的に変動する場合、全ての行をはみ出ないように表示したい

受付中

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 142

takuo-nkmr

score 2

 前提・実現したいこと

Xamarin.FormsでGridのセル内にボタンを複数設置して、セルの横幅が不足した場合に
複数行に回り込んで描画するGridの行を複数設置したい。

 発生している問題・エラーメッセージ

本家のサンプル を参考に、ボタンの回り込みはカスタムレイアウトの作成で対応できそうなのですが、
ボタンが複数行になった場合、Gridの高さが変わってしまい、Gridのセルが縦方向にはみ出てしまいます。
※下図参照

イメージ説明

Gridの高さが、ボタンの表示内容に応じて動的に設定されるようにしたいです。

 該当のソースコード

Githubにリポジトリを作成してありますので、こちらを参照いただきたいのですが
主だった修正は下記2ファイルです。

WrapLayout.cs

using System;
using System.Collections.Generic;
using Xamarin.Forms;

namespace ImageWrapLayout
{
    public class WrapLayout : Layout<View>
    {
        public static readonly BindableProperty ColumnSpacingProperty = BindableProperty.Create(
            "ColumnSpacing",
            typeof(double),
            typeof(WrapLayout),
            2.0,
            propertyChanged: (bindable, oldvalue, newvalue) =>
            {
                ((WrapLayout)bindable).InvalidateLayout();
            });

        public static readonly BindableProperty RowSpacingProperty = BindableProperty.Create(
            "RowSpacing",
            typeof(double),
            typeof(WrapLayout),
            2.0,
            propertyChanged: (bindable, oldvalue, newvalue) =>
            {
                ((WrapLayout)bindable).InvalidateLayout();
            });

        public double ColumnSpacing
        {
            set { SetValue(ColumnSpacingProperty, value); }
            get { return (double)GetValue(ColumnSpacingProperty); }
        }

        public double RowSpacing
        {
            set { SetValue(RowSpacingProperty, value); }
            get { return (double)GetValue(RowSpacingProperty); }
        }

        protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
        {
            // 対象要素のheightの設定
            // widthはwidthConstraintの値
            // ※実質1行の高さは同じなので、高さは(1行の高さ*行数)+((行数-1)*スペース) となる
            double width  = widthConstraint;

            int countChildren = Children.Count;
            int countRows = 1;
            double tmpWidthPerRow = 0;
            double? heightPerRow = null;
            foreach (View child in Children)
            {
                // 子要素のサイズを取得
                SizeRequest childSizeRequest = child.Measure(Double.PositiveInfinity, Double.PositiveInfinity);

                // 1行の幅が全体幅を上回れば行を追加
                tmpWidthPerRow += childSizeRequest.Request.Width;
                if (tmpWidthPerRow >= width)
                {
                    // 1行幅のリセット
                    tmpWidthPerRow = childSizeRequest.Request.Width;

                    // 行を1行追加
                    countRows++;
                }

                // 1行の高さを保存
                if (!heightPerRow.HasValue)
                {
                    heightPerRow = childSizeRequest.Request.Height;
                }
            }

            // 高さの設定
            double height = (double)heightPerRow * countRows + RowSpacing * (countRows - 1);

            return new SizeRequest(new Size(width, height));
        }

        protected override void LayoutChildren(double x, double y, double width, double height)
        {
            double xChild = x;
            double yChild = y;
            double tmpWidthPerRow = 0;
            foreach (View child in Children)
            {
                // 子要素のサイズを取得
                SizeRequest childSizeRequest = child.Measure(Double.PositiveInfinity, Double.PositiveInfinity);

                // 1行の幅が全体幅を上回れば次の行で表示
                tmpWidthPerRow += childSizeRequest.Request.Width;
                if (tmpWidthPerRow >= width)
                {
                    tmpWidthPerRow = childSizeRequest.Request.Width;
                    xChild = x;
                    yChild += RowSpacing + childSizeRequest.Request.Height;
                }

                // カラムの表示位置の設定
                LayoutChildIntoBoundingRegion(child, new Rectangle(new Point(xChild, yChild), new Size(childSizeRequest.Request.Width,childSizeRequest.Request.Height)));

                // カラムのx座標を追加
                xChild += childSizeRequest.Request.Width + ColumnSpacing;
            }
        }
    }
}

 
ImageWrapLayoutPage.xaml ※コードビハインドはInitializeComponent()のみ

<?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:local="clr-namespace:ImageWrapLayout"
             x:Class="ImageWrapLayout.ImageWrapLayoutPage"
             BackgroundColor="#FFF">
   <ScrollView>
        <StackLayout Margin="20,20,20,20">
            <Grid BackgroundColor="#6d6d6d" ColumnSpacing="1" RowSpacing="1"
                  Padding="1" x:Name="DynamicGrid">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="0.2*"/>
                    <ColumnDefinition Width="0.8*"/>
                </Grid.ColumnDefinitions>

                <BoxView Grid.Row="0" Grid.Column="0" BackgroundColor="Gray"/>
                <Label Grid.Row="0" Grid.Column="0" Text="項目A" TextColor="#FFF"
                       HorizontalOptions="Center" VerticalOptions="Center"/>
                <local:WrapLayout Grid.Row="0" Grid.Column="1"
                                  BackgroundColor="#FFF"
                                  Padding="5">
                    <Button Text="111111"/>
                    <Button Text="222222"/>
                    <Button Text="333333"/>
                    <Button Text="444444"/>
                    <Button Text="555555"/>
                    <Button Text="666666"/>
                    <Button Text="777777"/>
                    <Button Text="888888"/>
                    <Button Text="999999"/>
                </local:WrapLayout>

                <BoxView Grid.Row="1" Grid.Column="0" BackgroundColor="Gray"/>
                <Label Grid.Row="1" Grid.Column="0" Text="項目B" TextColor="#FFF"
                       HorizontalOptions="Center" VerticalOptions="Center"/>
                <local:WrapLayout Grid.Row="1" Grid.Column="1"
                                  BackgroundColor="#FFF"
                                  Padding="5">
                    <Button Text="111111"/>
                    <Button Text="222222"/>
                    <Button Text="333333"/>
                    <Button Text="444444"/>
                    <Button Text="555555"/>
                    <Button Text="666666"/>
                    <Button Text="777777"/>
                    <Button Text="888888"/>
                    <Button Text="999999"/>
                </local:WrapLayout>

                <BoxView Grid.Row="2" Grid.Column="0" BackgroundColor="Gray"/>
                <Label Grid.Row="2" Grid.Column="0" Text="項目C" TextColor="#FFF"
                       HorizontalOptions="Center" VerticalOptions="Center"/>
                <local:WrapLayout Grid.Row="2" Grid.Column="1"
                                  BackgroundColor="#FFF"
                                  Padding="5">
                    <Button Text="111111"/>
                    <Button Text="222222"/>
                    <Button Text="333333"/>
                    <Button Text="444444"/>
                    <Button Text="555555"/>
                    <Button Text="666666"/>
                    <Button Text="777777"/>
                    <Button Text="888888"/>
                    <Button Text="999999"/>
                </local:WrapLayout>
            </Grid>
            <Label Text="テーブル下部のラベル1"/>
            <Label Text="テーブル下部のラベル2"/>
        </StackLayout>
    </ScrollView>
</ContentPage>

 補足情報

  • Visual Studio for Mac 7.4.2
  • Xamarin.Forms 2.5.0.280555
  • 検証端末: Nexus7(Android6.0.1)
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

+1

WrapLayout クラスは問題無いように見えます。

これは回答にならないかもしれませんが、Grid の列の幅を固定すると、とりあえずうまくいくようです。

<Grid.ColumnDefinitions>
    <ColumnDefinition Width="120"/>
    <ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/19 13:03

    ご回答ありがとうございます。
    記載いただきました通り、こちらでもGridの列幅を固定値とすることで
    修正されることを確認致しました。
    とはいえ、原因は不明のままですので本質問は解決済みとせずに、
    受付中のままとさせてください。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.86%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • C#

    5979questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • Xamarin

    423questions

    Xamarin(ザマリン)は、iPhoneなどのiOSやAndroidで動作し、C# 言語を用いてアプリを開発できるクロスプラットフォーム開発環境です。Xamarin Studioと C# 言語を用いて、 iOS と Android の両方の開発を行うことができます。

  • トップ
  • C#に関する質問
  • Xamarin.FormsでGridのRowの高さが動的に変動する場合、全ての行をはみ出ないように表示したい