ideaki's blog

WinRT C#/XAML の開発について

Flyoutをかっこよくカスタマイズしてみる UWP/XAML

この記事はWindows 10 Mobile / Windows Phone Advent Calendar 2016 - Adventar 20日目の記事です。
半年ぶりのブログ投稿になります。ITエンジニアをやめてからもだいたい半年です。

この記事ではFlyoutの見た目をカスタマイズしていき、自分だけのかっこいいFlyoutを作る参考にしてもらいたいと思います。

Flyout
一時的に少量の情報を表示する向けのコントロールで、開くのも閉じるのもとっても簡単なコントロールです。
僕はターゲットを右クリックしたり長押ししたりしたときに出すコンテキストメニューとして多用してます。(その用途だとちょっと違うFlyoutになる)
ちゃんと知りたい方はこちらをどうぞ。
https://msdn.microsoft.com/ja-jp/library/windows/apps/windows.ui.xaml.controls.flyout?f=255&MSPPError=-2147217396


Flyoutの見た目をカスタマイズするには
Flyoutには情報を表示するContentプロパティと外観を定義するFlyoutPresenterStyleプロパティがあります。
今回は外観を変えたいためFlyoutPresenterStyleに手を加えていきます。
Styleとはなんぞやという方はこちらをご覧ください。
https://msdn.microsoft.com/ja-jp/windows/uwp/controls-and-patterns/xaml-styles

Flyout使用例
なんの変哲もない下記のFlyout使用例を元にStyleをカスタマイズしていきます。
FlyoutのContentプロパティにはTextBlockを格納しています。

<Border BorderBrush="Black"
        BorderThickness="1">
    <Button Content="Button"
            VerticalAlignment="Center"
            HorizontalAlignment="Center">
        <Button.Flyout>
            <Flyout>
                <TextBlock Text="Flyout" />
            </Flyout>
        </Button.Flyout>
    </Button>
</Border>

f:id:ideaki:20161219005422p:plain

FlyoutPresenterStyleを編集する
下記はデフォルトのFlyoutPresenterStyleになります。Styleとしてはかなーり短く読みやすいですね。
ちなみに"C:\Program Files (x86)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\10.0.14393.0\Generic\generic.xaml" より引っ張ってきています。

<Style TargetType="FlyoutPresenter">
    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
    <Setter Property="VerticalContentAlignment" Value="Stretch"/>
    <Setter Property="IsTabStop" Value="False"/>
    <Setter Property="Background" Value="{ThemeResource SystemControlBackgroundChromeMediumLowBrush}"/>
    <Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundChromeHighBrush}"/>
    <Setter Property="BorderThickness" Value="{ThemeResource FlyoutBorderThemeThickness}"/>
    <Setter Property="Padding" Value="{ThemeResource FlyoutContentThemePadding}"/>
    <Setter Property="MinWidth" Value="{ThemeResource FlyoutThemeMinWidth}"/>
    <Setter Property="MaxWidth" Value="{ThemeResource FlyoutThemeMaxWidth}"/>
    <Setter Property="MinHeight" Value="{ThemeResource FlyoutThemeMinHeight}"/>
    <Setter Property="MaxHeight" Value="{ThemeResource FlyoutThemeMaxHeight}"/>
    <Setter Property="ScrollViewer.HorizontalScrollMode" Value="Auto" />
    <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto" />
    <Setter Property="ScrollViewer.VerticalScrollMode" Value="Auto" />
    <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
    <Setter Property="ScrollViewer.ZoomMode" Value="Disabled" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="FlyoutPresenter">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                    <ScrollViewer x:Name="ScrollViewer"
                        ZoomMode="{TemplateBinding ScrollViewer.ZoomMode}"
                        HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
                        HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
                        VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
                        VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
                        AutomationProperties.AccessibilityView="Raw">
                        <ContentPresenter Content="{TemplateBinding Content}"
                                          ContentTemplate="{TemplateBinding ContentTemplate}"
                                          ContentTransitions="{TemplateBinding ContentTransitions}"
                                          Margin="{TemplateBinding Padding}"
                                          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </ScrollViewer>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

枠にシステムカラーを付けてみる
BorderBrushプロパティを設定しているSetterプロパティを下記に変更します。
ちなみに変更した値は "C:\Program Files (x86)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\10.0.14393.0\Generic\generic.xaml" より引っ張ってきています。

<Setter Property="BorderBrush"
        Value="{ThemeResource SystemControlForegroundAccentBrush}" />

f:id:ideaki:20161220025738p:plain

光らせてみる
※Build 10586以上必須
専用のコントロールを用意します(おい)
詳細は省きますが、MSのGitHubに上がっているCompositionShadowコントロールをお借りします。
github.com
Templateプロパティを設定しているSetterプロパティを下記に変更します。

<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="FlyoutPresenter">
            <local:CompositionShadow BlurRadius="20"
                                     Color="{ThemeResource SystemAccentColor}">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                    <ScrollViewer x:Name="ScrollViewer"
                                  ZoomMode="{TemplateBinding ScrollViewer.ZoomMode}"
                                  HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
                                  HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
                                  VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
                                  VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
                                  AutomationProperties.AccessibilityView="Raw">
                        <ContentPresenter Content="{TemplateBinding Content}"
                                          ContentTemplate="{TemplateBinding ContentTemplate}"
                                          ContentTransitions="{TemplateBinding ContentTransitions}"
                                          Margin="{TemplateBinding Padding}"
                                          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
                    </ScrollViewer>
                </Border>
            </local:CompositionShadow>
        </ControlTemplate>
    </Setter.Value>
</Setter>

f:id:ideaki:20161220032938p:plain


どのコントロールも光っているとうっとしいですが、
ユーザーに注目してほしいときにはいいんじゃないでしょうか。
なによりかっこいい!

以上のサンプルを置いておきます。
https://1drv.ms/u/s!AhaSq7vQuLAcicBkznwQg3_QDSQImw
1drv.ms



明日はmiu_hiro_さんです。