しっぽを追いかけて

ぐるぐるしながら考えています

Unity と猫の話題が中心   掲載内容は個人の私見であり、所属組織の見解ではありません

本棚風 GridView をつくる

前回の レスポンシブな大理石風背景を表示する - しっぽを追いかけて をさらに拡張して本棚風にタイルを表示させてみたいと思います

完成イメージはこんな感じ

f:id:matatabi_ux:20140629144330p:plain

背景は前回のやり方で描画するとして、問題は棚の部分です

どのように組み立てるか、パーツとして分解したイメージはこんな感じ

f:id:matatabi_ux:20140629161818p:plain

マウスオーバーや選択時に枠を表示する ItemTemplate の領域は緑色の部分にして、Path で三角形と平行四辺形を描き、残りは Rectangle で立体感を出します

棚が右へ続く場合はすき間をつなげたいので、右端の一部に隣のタイルの左端を重ねてくっつけるようにしようと思います

というわけでさっそく上記のイメージになるように GridView のアイテムコンテナーである GridViewItem をカスタマイズします

f:id:matatabi_ux:20140629152504p:plain

まずは VisualStudio のドキュメントアウトラインから GridView を選択し、「追加テンプレートの編集」「生成されたアイテムコンテナーの編集」「コピーして編集」を選びます

今回は GridViewItem の既定のスタイルにしてみました

スタイルのコードがずら~っと生成されますが、下記の部分のみ変更します

<Style TargetType="GridViewItem">
    <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
    <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
    <Setter Property="Background" Value="Transparent" />
    <Setter Property="TabNavigation" Value="Local" />
    <Setter Property="IsHoldingEnabled" Value="True" />
    <!-- 上余白を開ける-->
    <Setter Property="Margin" Value="0,40,0,0" />
    <!-- 上余白を開ける-->
    <!-- タイルを領域いっぱいまで表示する -->
    <Setter Property="HorizontalContentAlignment" Value="Stretch" />
    <Setter Property="VerticalContentAlignment" Value="Stretch" />
    <!-- タイルを領域いっぱいまで表示する -->
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="GridViewItem">
                <Border x:Name="OuterContainer">
                    <VisualStateManager.VisualStateGroups>

                            ~ 中略 ~

                    </VisualStateManager.VisualStateGroups>
                    <!-- 右端が隣のタイルと 40 px 重なるようにする -->
                    <Grid Margin="0,0,-40,0">
                        <!-- タイル領域を 4 段に分割する -->
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*" />
                            <RowDefinition Height="30" />
                            <RowDefinition Height="10" />
                            <RowDefinition Height="30" />
                        </Grid.RowDefinitions>
                        <!-- 2 段目と 3 段目をまたいで使用-->
                        <Grid Grid.Row="1" Grid.RowSpan="2">
                            <!--  内部を 両端 40 px と残り全部の 3 列に分割する  -->
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="40" />
                                <ColumnDefinition Width="*" />
                                <ColumnDefinition Width="40" />
                            </Grid.ColumnDefinitions>
                            <!--  左端 40 px 内に三角形を Path で描画  -->
                            <Path Data="M0,40 L40,0 L40,40 Z">
                                <Path.Fill>
                                    <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                                        <GradientStop Offset="0" Color="#FF686151" />
                                        <GradientStop Offset="1" Color="#FF91876F" />
                                    </LinearGradientBrush>
                                </Path.Fill>
                            </Path>
                            <!--  中央に Rectangle を描画  -->
                            <Rectangle Grid.Column="1">
                                <Rectangle.Fill>
                                    <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                                        <GradientStop Offset="0" Color="#FF686151" />
                                        <GradientStop Offset="1" Color="#FF91876F" />
                                    </LinearGradientBrush>
                                </Rectangle.Fill>
                            </Rectangle>
                            <!--  右端 40 px 内に三角形を Path で描画  -->
                            <Path Grid.Column="2" Data="M0,0 L40,0 L0,40 Z">
                                <Path.Fill>
                                    <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                                        <GradientStop Offset="0" Color="#FF686151" />
                                        <GradientStop Offset="1" Color="#FF91876F" />
                                    </LinearGradientBrush>
                                </Path.Fill>
                            </Path>
                        </Grid>
                        <!--  右端 40 px 内に平行四辺形を Path で描画  -->
                        <Path Grid.Row="1"
                                Grid.RowSpan="3"
                                HorizontalAlignment="Right"
                                Data="M0,40 L40,0 L40,30 L0,70 Z">
                            <Path.Fill>
                                <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                                    <GradientStop Offset="0" Color="#FF484131" />
                                    <GradientStop Offset="1" Color="#FF71674F" />
                                </LinearGradientBrush>
                            </Path.Fill>
                        </Path>
                        <!-- 3 段目に重ねて表示する -->
                        <Grid Grid.RowSpan="2" Margin="10,0">
                            <!-- 中央寄せで ItemTemplate 領域を表示する -->
                            <Grid x:Name="ReorderHintContent"
                                    HorizontalAlignment="Center"
                                    Background="Transparent">

                            ~ 中略 ~

                         </Grid>
                        </Grid>
                        <!-- 4 段目に Rectangle を描画 -->
                        <Rectangle Grid.Row="3" Fill="#FFF6E3BC" />
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

あとは画面側の XAML の GridView を適当に余白やレイアウト調整して・・・

<!--  水平スクロール グリッド  -->
<GridView x:Name="itemGridView"
            Grid.RowSpan="2"
            AutomationProperties.AutomationId="ItemsGridView"
            AutomationProperties.Name="Items"
            IsItemClickEnabled="True"
            IsSwipeEnabled="false"
            ItemClick="Presenter.OnItemClick"
            ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
            Padding="116,140,116,50"
            SelectionMode="None"
            TabIndex="1">
    <GridView.ItemsPanel>
        <ItemsPanelTemplate>
            <VariableSizedWrapGrid ItemHeight="280"
                                    ItemWidth="250"
                                    Orientation="Vertical" />
        </ItemsPanelTemplate>
    </GridView.ItemsPanel>
    <GridView.ItemTemplate>
        <DataTemplate>
            <Viewbox>
                <Grid Width="250" Height="300">
                    <Image HorizontalAlignment="Center"
                            VerticalAlignment="Top"
                            AutomationProperties.Name="{Binding Content.Title}"
                            Source="{Binding Content.ImageUri}"
                            Stretch="UniformToFill" />
                    <Border VerticalAlignment="Bottom"
                            Background="{ThemeResource ListViewItemOverlayBackgroundThemeBrush}"
                            Padding="10">
                        <TextBlock FontSize="12"
                                    Foreground="{ThemeResource ListViewItemOverlayForegroundThemeBrush}"
                                    Style="{StaticResource BaseTextBlockStyle}"
                                    TextTrimming="CharacterEllipsis"
                                    TextWrapping="NoWrap">
                            <Run Text="Photo: " /><Run Text="{Binding Content.Title}" /><Run Text=" by " /><Run Text="{Binding Content.Owner}" />
                        </TextBlock>
                    </Border>
                </Grid>
            </Viewbox>
        </DataTemplate>
    </GridView.ItemTemplate>
</GridView>

できました!

f:id:matatabi_ux:20140629144330p:plain

解像度を変えてもいい感じに棚が増えます

f:id:matatabi_ux:20140629162559p:plain