Xamarin.Forms の TextCell に矢印を表示する

## 動機

Xamarin.Forms で、あるアプリを作って、使ってみてもらったときのことです。**ListView** の **TextCell** をタップすると次の画面に行けるのですが、そのことに気づいてもらえなかった、ということがありました。ひとつの解決策として、画面遷移のある **TextCell** には矢印を表示することを考えました。

## ViewCell で書く？

はじめ、**TextCell** をやめて **ViewCell** にし、**ViewCell** の中に **Label** を置くことを考えました。

ところが、 iOS と Android とで **TextCell** の中のレイアウトに差があります。このプラットフォーム毎の差異を、**ViewCell** の中のレイアウトの調整によって書き分けなければなりません。これが複雑で... 結局、この方針は採用しませんでした。

別に書き分けなくてもよい、という考えもあるでしょう。矢印を表示しない ListView の TextCell と、見た目が微妙に違ってくるわけですが、これを気にするかどうか。

Xamarin.Forms は、内部でプラットフォーム毎の **TextCellRenderer** を実装して書き分けています。

## エフェクトでは書けない...

なるべく軽い実装にしたかったので探ってみたのですが、 Cell に[エフェクト](https://docs.microsoft.com/ja-jp/xamarin/xamarin-forms/app-fundamentals/effects/)は使えないそうです。仕様。

## カスタム レンダラーで実現

次のブログ記事を見つけて解決です。これが正にやりたいことでした。ということで、私の投稿は James の記事の紹介に過ぎません:stuck_out_tongue:

- [Adding a Disclosure Indicator Accessory to Xamarin.Forms ViewCells](https://montemagno.com/adding-a-disclosure-indicator-accessory-to/) - [James Montemagno: Live, Love, Bike, and Code](https://montemagno.com/)

少々改変しています。例えば、元の記事のコードでは、矢印アイコンが出るのがデフォルトですが、それは過激かと思いましたので、アイコン無しをデフォルトにしています。以下にコードを示します。

```MyApp1.iOS\AccessoryTextCellRenderer.cs
using Xamarin.Forms;
using MyApp1.iOS;
using Xamarin.Forms.Platform.iOS;

[assembly: ExportRenderer(typeof(TextCell), typeof(AccessoryTextCellRenderer))]
namespace MyApp1.iOS
{
    public class AccessoryTextCellRenderer : TextCellRenderer
    {
        public override UIKit.UITableViewCell GetCell(Cell item, UIKit.UITableViewCell reusableCell, UIKit.UITableView tv)
        {
            var cell = base.GetCell(item, reusableCell, tv);
            switch (item.StyleId)
            {
                default:
                case "None":
                    cell.Accessory = UIKit.UITableViewCellAccessory.None;
                    break;
                case "Checkmark":
                    cell.Accessory = UIKit.UITableViewCellAccessory.Checkmark;
                    break;
                case "DetailButton":
                    cell.Accessory = UIKit.UITableViewCellAccessory.DetailButton;
                    break;
                case "DetailDisclosureButton":
                    cell.Accessory = UIKit.UITableViewCellAccessory.DetailDisclosureButton;
                    break;
                case "DisclosureIndicator":
                    cell.Accessory = UIKit.UITableViewCellAccessory.DisclosureIndicator;
                    break;
            }
            return cell;
        }
    }
}
```

```Page1.xaml
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextCell StyleId="DisclosureIndicator" Text="{Binding Text}" Detail="{Binding Detail}" />
                </DataTemplate>
            </ListView.ItemTemplate>
```

見た目はこんな感じです。

![スクリーンショット](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25692/ab5f358c-2f17-8e7d-62cc-7a4aa0220964.png)

公式ドキュメントではこのあたりが参考になると思います。

- [ViewCell のカスタマイズ](https://docs.microsoft.com/ja-jp/xamarin/xamarin-forms/app-fundamentals/custom-renderer/viewcell) - [Microsoft Docs](https://docs.microsoft.com/ja-jp/)

## Android では表示しない

iOS 側しか手当てしていませんので、Android では従来のまま、矢印アイコンなどは表示されません。iOS にあるようなプロパティは Android の API には無さそうです。API に用意が無いのなら、それが Android の流儀なのだろう、と納得することにしました。Xamarin.Forms に組み込まれていない理由は、iOS にしか無いからでしょうか。

以上、[Tweet しながら](https://twitter.com/NakamuraYoichi/status/1168718032631320576) コーディングしていました。