yamamoWorks

.NET技術を中心に気まぐれに更新していきます

Xamarin.Forms ListViewのGroupHeaderの高さ調整

いやぁXamarin.Formsは壁が多い奥が深いですね。
今回はListViewをグルーピングした際のレイアウトについてです。

ListViewをグルーピングしてそのヘッダー部分をViewCellでカスタムレイアウトする場合に一筋縄ではいかない事が分かったのでメモしておきます。

下記のようなグルーピングしたListViewを用意します。 ここではGroupHeaderTemplateにTextCellを使用したものとViewCellとLabelを使用したものとを並べてみます。

    <ListView x:Name="listView1" IsGroupingEnabled="True" HasUnevenRows="True">
      <ListView.GroupHeaderTemplate>
        <DataTemplate>
          <TextCell Text="{Binding Key}" />
        </DataTemplate>
      </ListView.GroupHeaderTemplate>
      <ListView.ItemTemplate>
        <DataTemplate>
          <ViewCell>
            <Label Text="{Binding Name}" />
          </ViewCell>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>
    ...
    <ListView x:Name="listView2" IsGroupingEnabled="True" HasUnevenRows="True">
      <ListView.GroupHeaderTemplate>
        <DataTemplate>
          <ViewCell>
            <Label Text="{Binding Key}" />
          </ViewCell>
        </DataTemplate>
      </ListView.GroupHeaderTemplate>
      <ListView.ItemTemplate>
        <DataTemplate>
          <ViewCell>
              <Label Text="{Binding Name}" />
          </ViewCell>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>

以下、各プラットフォームでの表示と対応方法です。

Android

特に違和感はありません。
f:id:yamamoWorks:20160619184825p:plain:w350

iOS

ViewCellを使用している方の高さが残念ですが、これはViewCellのHeightを指定すれば解決します。

f:id:yamamoWorks:20160619191743j:plain:w300 f:id:yamamoWorks:20160619191755p:plain:w300
修正前   修正後
      <ListView.GroupHeaderTemplate>
        <DataTemplate>
          <ViewCell Height="22">
            <Label Text="{Binding Key}" />
          </ViewCell>
        </DataTemplate>
      </ListView.GroupHeaderTemplate>

UWP

こちらもViewCellを使用している方の高さが残念です。 そしてUWPではViewCellのHeightを指定しても解決しません。 UWPプロジェクトのApp.xamlファイルでListViewHeaderItemの既定のスタイルを上書きする必要があります。

f:id:yamamoWorks:20160619202144j:plain:w350 f:id:yamamoWorks:20160619193155p:plain:w350
修正前   修正後

App.xaml

    <Application.Resources>
        <x:Double x:Key="ListViewHeaderItemMinHeight">22</x:Double>
    </Application.Resources>

解説

これはXamarin.Forms.Platform.UWP.ListViewRendererがUWPのListViewを内部で生成する際にGroupStyleSelectorの値にResource.xamlで"ListViewGroupSelector"として定義されているXamarin.Forms.Platform.UWP.ListViewGroupStyleSelectorを設定していて、この ListViewGroupStyleSelectorがResource.xamlで"ListViewGroup"として定義されているGroupStyleを返すのですが、その中でHeaderContainerStyleとしてListViewHeaderItemが指定されており、UWPでその既定のスタイルがMinHeightが44になっている事が原因です。

ListViewHeaderItem スタイルとテンプレート - Windows app development

通常はXamarin.Formsで対応していないプラットフォーム側のパラメーターの調整はCustom Rendererでも作らない限り手が出ませんが、UWPのスタイルテンプレートの仕組みを活用すれば何とかなる場合もある事が分かりました。