none
縦横比に合わせてレイアウトを変えることはできますか? RRS feed

  • 質問

  • UWPのAdaptiveTriggerについて質問です。

    サンプルを見ると、AdaptiveTriggerでは、MinWindowHeightとMinWindowWidth が設定できますが、サイズではなく、ポートレートならこのレイアウト、ランドスケープならこのレイアウト、みたいに、アスペクト比でレイアウトを変えることはできますか?

    例えば、グリッドの分割をランドスケープなら左右に、ポートレートなら上下に、という感じです。

    マイクロソフトのセミナーで貰ったサンプルコードでは、幅が一定より狭くなったら、Gridレイアウトを切り替える、というコードはあったのですが、比率で変える方法を検討しております。

    よろしくお願いいたします。

       <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
            <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="VisualStateGroup">
                    <VisualState x:Name="VisualStateMin320">
                        <VisualState.StateTriggers>
                            <AdaptiveTrigger MinWindowWidth="320"/>
                        </VisualState.StateTriggers>
                        <VisualState.Setters>
                            <Setter Target="Hero.(Grid.ColumnSpan)" Value="2" />
                            <Setter Target="Hero.(Grid.RowSpan)" Value="1" />
                            <Setter Target="Metadata.(Grid.Column)" Value="0" />
                            <Setter Target="Metadata.(Grid.Row)" Value="1" />
                            <Setter Target="Metadata.(Grid.ColumnSpan)" Value="2" />
                            <Setter Target="Metadata.(Grid.RowSpan)" Value="1" />
                            <Setter Target="Description.(RelativePanel.RightOf)" Value="" />
                            <Setter Target="Description.(RelativePanel.Below)" Value="Username" />
                            <Setter Target="Description.Margin " Value="0,12,0,0" />
                            <Setter Target="ImageName.FontSize" Value="20" />
                        </VisualState.Setters>
                    </VisualState>
                    <VisualState x:Name="VisualStateMin548">
                        <VisualState.StateTriggers>
                            <AdaptiveTrigger MinWindowWidth="548"/>
                        </VisualState.StateTriggers>
                        <VisualState.Setters>
                            <Setter Target="Hero.(Grid.ColumnSpan)" Value="2" />
                            <Setter Target="Hero.(Grid.RowSpan)" Value="1" />
                            <Setter Target="Metadata.(Grid.Column)" Value="0" />
                            <Setter Target="Metadata.(Grid.Row)" Value="1" />
                            <Setter Target="Metadata.(Grid.ColumnSpan)" Value="2" />
                            <Setter Target="Metadata.(Grid.RowSpan)" Value="1" />
                            <Setter Target="Description.(RelativePanel.RightOf)" Value="Avatar" />
                            <Setter Target="Description.(RelativePanel.Below)" Value="" />
                            <Setter Target="Description.Margin " Value="12,0,0,0" />
                            <Setter Target="ImageName.FontSize" Value="20" />
                        </VisualState.Setters>
                    </VisualState>
                    <VisualState x:Name="VisualStateMin1024">
                        <VisualState.StateTriggers>
                            <AdaptiveTrigger MinWindowWidth="1024"/>
                        </VisualState.StateTriggers>
                        <VisualState.Setters>
                            <Setter Target="Hero.(Grid.ColumnSpan)" Value="1" />
                            <Setter Target="Hero.(Grid.RowSpan)" Value="2" />
                            <Setter Target="Metadata.(Grid.Column)" Value="1" />
                            <Setter Target="Metadata.(Grid.Row)" Value="0" />
                            <Setter Target="Metadata.(Grid.ColumnSpan)" Value="1" />
                            <Setter Target="Metadata.(Grid.RowSpan)" Value="2" />
                            <Setter Target="LeftCol.Width" Value="2*" />
                            <Setter Target="RightCol.Width" Value="1*" />
                            <Setter Target="Description.(RelativePanel.RightOf)" Value="Avatar" />
                            <Setter Target="Description.(RelativePanel.Below)" Value="" />
                            <Setter Target="Description.Margin " Value="12,0,0,0" />
                            <Setter Target="ImageName.FontSize" Value="24" />
                        </VisualState.Setters>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>
            <Grid.RowDefinitions>
                <RowDefinition />
                <RowDefinition />
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition x:Name="LeftCol" />
                <ColumnDefinition x:Name="RightCol" />
            </Grid.ColumnDefinitions>
            <Image x:Name="Hero" Grid.Column="0" Source="Assets/airtime.jpg" Stretch="UniformToFill" HorizontalAlignment="Center" VerticalAlignment="Center" />
            <ScrollViewer x:Name="Metadata" VerticalScrollBarVisibility="Auto">
                <RelativePanel Grid.Column="1" Background="LightBlue" Padding="12">
                    <Image x:Name="Avatar" Source="Assets/avatar.jpg" Width="100" Height="100" HorizontalAlignment="Left" />
                    <TextBlock x:Name="Username" RelativePanel.Below="Avatar" RelativePanel.AlignHorizontalCenterWith="Avatar" Text="phutureproof" />
                    <StackPanel x:Name="Description">
                        <TextBlock x:Name="ImageName" Foreground="White" FontWeight="Light" Text="Airtime" />
                        <TextBlock Text="9/15/15" />
                        <TextBlock Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla imperdiet pulvinar nunc. In et gravida ipsum. Morbi congue consequat ullamcorper. Integer ornare porta convallis. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vivamus sem nisi, ornare vel laoreet vel, accumsan facilisis tortor. Pellentesque ut nunc in leo vehicula pretium et at quam. Aliquam euismod id purus nec ultrices. Aliquam sed nisl at erat maximus finibus in sed urna. Nulla ullamcorper vehicula ex, in porta ante ullamcorper id. Phasellus a enim vitae odio ultricies semper. Suspendisse fermentum, erat in sodales accumsan, lacus urna aliquam nisi, sed ultricies dolor orci quis ligula." TextWrapping="WrapWholeWords" />
                    </StackPanel>
                </RelativePanel>
            </ScrollViewer>
        </Grid>


    • 編集済み NIM5 2016年6月24日 18:10
    2016年6月24日 18:09

回答

  • SteteTriggerを使って判定してみる

    <Page
        x:Class="App1.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:App1"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:app="using:App1"
        mc:Ignorable="d">
    
        <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
            <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="VisualStateGroup">
    
                    <VisualState x:Name="WideState">
                        <VisualState.StateTriggers>
                            <app:RatioTrigger Ratio="WideOrSquare" />
                        </VisualState.StateTriggers>
                        <VisualState.Setters>
                            <Setter Target="Hero.(Grid.Column)" Value="0" />
                            <Setter Target="Hero.(Grid.Row)" Value="0" />
                            <Setter Target="Hero.(Grid.ColumnSpan)" Value="1" />
                            <Setter Target="Hero.(Grid.RowSpan)" Value="2" />
    
                            <Setter Target="Metadata.(Grid.Column)" Value="1" />
                            <Setter Target="Metadata.(Grid.Row)" Value="0" />
                            <Setter Target="Metadata.(Grid.ColumnSpan)" Value="1" />
                            <Setter Target="Metadata.(Grid.RowSpan)" Value="2" />
    
                            <Setter Target="Description.(RelativePanel.RightOf)" Value="" />
                            <Setter Target="Description.(RelativePanel.Below)" Value="Username" />
                            <Setter Target="Description.Margin " Value="0,12,0,0" />
                            <Setter Target="ImageName.FontSize" Value="20" />
                            
                            <Setter Target="Description.Background" Value="Red" />
                        </VisualState.Setters>
                    </VisualState>
                    
                    <VisualState x:Name="NarrowState">
                        <VisualState.StateTriggers>
                            <app:RatioTrigger Ratio="Narrow" />
                        </VisualState.StateTriggers>
                        <VisualState.Setters>
                            <Setter Target="Hero.(Grid.Column)" Value="0" />
                            <Setter Target="Hero.(Grid.Row)" Value="0" />                        
                            <Setter Target="Hero.(Grid.ColumnSpan)" Value="2" />
                            <Setter Target="Hero.(Grid.RowSpan)" Value="1" />
                            
                            <Setter Target="Metadata.(Grid.Column)" Value="0" />
                            <Setter Target="Metadata.(Grid.Row)" Value="1" />
                            <Setter Target="Metadata.(Grid.ColumnSpan)" Value="2" />
                            <Setter Target="Metadata.(Grid.RowSpan)" Value="1" />
                            
                            <Setter Target="Description.(RelativePanel.RightOf)" Value="Avatar" />
                            <Setter Target="Description.(RelativePanel.Below)" Value="" />
                            <Setter Target="Description.Margin " Value="12,0,0,0" />
                            <Setter Target="ImageName.FontSize" Value="20" />
    
                            <Setter Target="Description.Background" Value="Yellow" />
                        </VisualState.Setters>
                    </VisualState>
                   
                </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>
            <Grid.RowDefinitions>
                <RowDefinition />
                <RowDefinition />
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition x:Name="LeftCol" />
                <ColumnDefinition x:Name="RightCol" />
            </Grid.ColumnDefinitions>
            <Image x:Name="Hero" Grid.Column="0" Source="Assets/airtime.jpg" Stretch="UniformToFill" HorizontalAlignment="Center" VerticalAlignment="Center" />
            <ScrollViewer x:Name="Metadata" VerticalScrollBarVisibility="Auto">
                <RelativePanel Grid.Column="1" Background="LightBlue" Padding="12">
                    <Image x:Name="Avatar" Source="Assets/avatar.jpg" Width="100" Height="100" HorizontalAlignment="Left" />
                    <TextBlock x:Name="Username" RelativePanel.Below="Avatar" RelativePanel.AlignHorizontalCenterWith="Avatar" Text="phutureproof" />
                    <StackPanel x:Name="Description" >
                        <TextBlock x:Name="ImageName" Foreground="White" FontWeight="Light" Text="Airtime" />
                        <TextBlock Text="9/15/15" />
                        <TextBlock Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla imperdiet pulvinar nunc. In et gravida ipsum. Morbi congue consequat ullamcorper. Integer ornare porta convallis. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vivamus sem nisi, ornare vel laoreet vel, accumsan facilisis tortor. Pellentesque ut nunc in leo vehicula pretium et at quam. Aliquam euismod id purus nec ultrices. Aliquam sed nisl at erat maximus finibus in sed urna. Nulla ullamcorper vehicula ex, in porta ante ullamcorper id. Phasellus a enim vitae odio ultricies semper. Suspendisse fermentum, erat in sodales accumsan, lacus urna aliquam nisi, sed ultricies dolor orci quis ligula." TextWrapping="WrapWholeWords" />
                    </StackPanel>
                </RelativePanel>
            </ScrollViewer>
        </Grid>
    </Page>
    namespace App1
    {
        sealed class RatioTrigger : Windows.UI.Xaml.StateTriggerBase
        {
            public RatioTrigger()
            {
                var window = Windows.ApplicationModel.Core.CoreApplication.GetCurrentView().CoreWindow;
                window.SizeChanged += (s, e) =>
                {
                    OnSizeChanged();
                };
                OnSizeChanged();
            }
    
            private void OnSizeChanged()
            {
                var window = Windows.ApplicationModel.Core.CoreApplication.GetCurrentView().CoreWindow;
                var bounds = window.Bounds;
                switch (this.Ratio)
                {
                    case RatioState.Wide:
                        SetActive(bounds.Width > bounds.Height);
                        break;
                    case RatioState.WideOrSquare:
                        SetActive(bounds.Width >= bounds.Height);
                        break;
                    case RatioState.Square:
                        SetActive(bounds.Width == bounds.Height);
                        break;
                    case RatioState.NarrowOrSquare:
                        SetActive(bounds.Width <= bounds.Height);
                        break;
                    case RatioState.Narrow:
                        SetActive(bounds.Width < bounds.Height);
                        break;
    
                    default:
                        SetActive(false);
                        break;
                }
    
            }
    
            public RatioState Ratio { get; set; }
    
        }
        enum RatioState
        {
            Wide,
            WideOrSquare,
            Square,
            NarrowOrSquare,
            Narrow,
        }
    }

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク NIM5 2016年6月25日 1:40
    2016年6月24日 23:24

すべての返信

  • SizeChangedイベントでWidth/highのどちらが大きいかを取得して、VisualStateを切り替えるのがいいと思います。
    private void Object_SizeChanged(object sender, SizeChangedEventArgs e)
    {
            if (e.NewSize.Height >= e.NewSize.Width)
            {
                    // 切り替え処理
            }
    }
    

    2016年6月24日 22:10
  • SteteTriggerを使って判定してみる

    <Page
        x:Class="App1.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:App1"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:app="using:App1"
        mc:Ignorable="d">
    
        <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
            <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="VisualStateGroup">
    
                    <VisualState x:Name="WideState">
                        <VisualState.StateTriggers>
                            <app:RatioTrigger Ratio="WideOrSquare" />
                        </VisualState.StateTriggers>
                        <VisualState.Setters>
                            <Setter Target="Hero.(Grid.Column)" Value="0" />
                            <Setter Target="Hero.(Grid.Row)" Value="0" />
                            <Setter Target="Hero.(Grid.ColumnSpan)" Value="1" />
                            <Setter Target="Hero.(Grid.RowSpan)" Value="2" />
    
                            <Setter Target="Metadata.(Grid.Column)" Value="1" />
                            <Setter Target="Metadata.(Grid.Row)" Value="0" />
                            <Setter Target="Metadata.(Grid.ColumnSpan)" Value="1" />
                            <Setter Target="Metadata.(Grid.RowSpan)" Value="2" />
    
                            <Setter Target="Description.(RelativePanel.RightOf)" Value="" />
                            <Setter Target="Description.(RelativePanel.Below)" Value="Username" />
                            <Setter Target="Description.Margin " Value="0,12,0,0" />
                            <Setter Target="ImageName.FontSize" Value="20" />
                            
                            <Setter Target="Description.Background" Value="Red" />
                        </VisualState.Setters>
                    </VisualState>
                    
                    <VisualState x:Name="NarrowState">
                        <VisualState.StateTriggers>
                            <app:RatioTrigger Ratio="Narrow" />
                        </VisualState.StateTriggers>
                        <VisualState.Setters>
                            <Setter Target="Hero.(Grid.Column)" Value="0" />
                            <Setter Target="Hero.(Grid.Row)" Value="0" />                        
                            <Setter Target="Hero.(Grid.ColumnSpan)" Value="2" />
                            <Setter Target="Hero.(Grid.RowSpan)" Value="1" />
                            
                            <Setter Target="Metadata.(Grid.Column)" Value="0" />
                            <Setter Target="Metadata.(Grid.Row)" Value="1" />
                            <Setter Target="Metadata.(Grid.ColumnSpan)" Value="2" />
                            <Setter Target="Metadata.(Grid.RowSpan)" Value="1" />
                            
                            <Setter Target="Description.(RelativePanel.RightOf)" Value="Avatar" />
                            <Setter Target="Description.(RelativePanel.Below)" Value="" />
                            <Setter Target="Description.Margin " Value="12,0,0,0" />
                            <Setter Target="ImageName.FontSize" Value="20" />
    
                            <Setter Target="Description.Background" Value="Yellow" />
                        </VisualState.Setters>
                    </VisualState>
                   
                </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>
            <Grid.RowDefinitions>
                <RowDefinition />
                <RowDefinition />
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition x:Name="LeftCol" />
                <ColumnDefinition x:Name="RightCol" />
            </Grid.ColumnDefinitions>
            <Image x:Name="Hero" Grid.Column="0" Source="Assets/airtime.jpg" Stretch="UniformToFill" HorizontalAlignment="Center" VerticalAlignment="Center" />
            <ScrollViewer x:Name="Metadata" VerticalScrollBarVisibility="Auto">
                <RelativePanel Grid.Column="1" Background="LightBlue" Padding="12">
                    <Image x:Name="Avatar" Source="Assets/avatar.jpg" Width="100" Height="100" HorizontalAlignment="Left" />
                    <TextBlock x:Name="Username" RelativePanel.Below="Avatar" RelativePanel.AlignHorizontalCenterWith="Avatar" Text="phutureproof" />
                    <StackPanel x:Name="Description" >
                        <TextBlock x:Name="ImageName" Foreground="White" FontWeight="Light" Text="Airtime" />
                        <TextBlock Text="9/15/15" />
                        <TextBlock Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla imperdiet pulvinar nunc. In et gravida ipsum. Morbi congue consequat ullamcorper. Integer ornare porta convallis. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vivamus sem nisi, ornare vel laoreet vel, accumsan facilisis tortor. Pellentesque ut nunc in leo vehicula pretium et at quam. Aliquam euismod id purus nec ultrices. Aliquam sed nisl at erat maximus finibus in sed urna. Nulla ullamcorper vehicula ex, in porta ante ullamcorper id. Phasellus a enim vitae odio ultricies semper. Suspendisse fermentum, erat in sodales accumsan, lacus urna aliquam nisi, sed ultricies dolor orci quis ligula." TextWrapping="WrapWholeWords" />
                    </StackPanel>
                </RelativePanel>
            </ScrollViewer>
        </Grid>
    </Page>
    namespace App1
    {
        sealed class RatioTrigger : Windows.UI.Xaml.StateTriggerBase
        {
            public RatioTrigger()
            {
                var window = Windows.ApplicationModel.Core.CoreApplication.GetCurrentView().CoreWindow;
                window.SizeChanged += (s, e) =>
                {
                    OnSizeChanged();
                };
                OnSizeChanged();
            }
    
            private void OnSizeChanged()
            {
                var window = Windows.ApplicationModel.Core.CoreApplication.GetCurrentView().CoreWindow;
                var bounds = window.Bounds;
                switch (this.Ratio)
                {
                    case RatioState.Wide:
                        SetActive(bounds.Width > bounds.Height);
                        break;
                    case RatioState.WideOrSquare:
                        SetActive(bounds.Width >= bounds.Height);
                        break;
                    case RatioState.Square:
                        SetActive(bounds.Width == bounds.Height);
                        break;
                    case RatioState.NarrowOrSquare:
                        SetActive(bounds.Width <= bounds.Height);
                        break;
                    case RatioState.Narrow:
                        SetActive(bounds.Width < bounds.Height);
                        break;
    
                    default:
                        SetActive(false);
                        break;
                }
    
            }
    
            public RatioState Ratio { get; set; }
    
        }
        enum RatioState
        {
            Wide,
            WideOrSquare,
            Square,
            NarrowOrSquare,
            Narrow,
        }
    }

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク NIM5 2016年6月25日 1:40
    2016年6月24日 23:24
  • 早速のご回答ありがとうございます。

    コードで処理するのはシンプルでわかりやすいですね。

    2016年6月25日 1:38
  • gekkaさん、回答ありがとうございます。

    なるほど、StateTriggerというものがあるんですね。

    これだと、VSMでのアニメーションなどもBlendで編集できそうです。

    こちらを試してみます。ありがとうございました。

    2016年6月25日 1:40