LoginSignup
5
2

More than 1 year has passed since last update.

Xamarin.Forms の TextCell の Detail に複数行を表示したい

Last updated at Posted at 2019-12-11

動機

Xamarin.Forms に TextCell という UI があります。大きなフォントで1行の Text ラベルと、小さなフォントで1行の Detail ラベルとからなるセルです。ListViewTableView の要素になります。

Detail に複数行の文字列を表示したいことがありました。試しに Detail に複数行の文字列を入れると、1行目だけが表示されました。これではダメですね。(あとで分かったのですが、1行目だけが表示されるのは iOS の場合で、Android では改行されずに続けて表示されます。)

こういうとき、まずは ViewCell を使うのだと思います。しかし、ViewCell の中に Label を並べただけだと、マージンやフォントサイズなどのスタイルが周囲の TextCell と合いません。合わせるにしても、iOS と Android とではスタイルが微妙に違うこともあって、スタイルを作りこむのは少々面倒です。

そこで、Detail に複数行の文字列を表示できる TextCellカスタム レンダラーで作ろうと思い立ちました。そちらの方が面倒ではないかという意見もあるやもしれませんが、あるいは、既にどこかに似たようなものがあるかもしれませんが、ご容赦ください。

準備

Xamarin.Forms のソースTextCellRenderer の実装などを見て作戦を練ります。

  • iOS
  • Android
    • BaseCellView に実装の中に _DetailText.SetSingleLine(true) とあるので、この値を false に変更すれば良さそう。
    • TextView SetSingleLine - Android Developers

Android の方ですが、 _DetailText が private であるため外から触ることができません。ググったところ、GetChildAt() を使ってアクセスできることが分かりました。次の記事を参考にしました。

成果物

共通部分は空っぽです。

/App1/App1/MultilineTextCell.cs
using Xamarin.Forms;
namespace App1
{
    public class MultilineTextCell : TextCell
    {
    }
}

iOS のカスタムレンダラー:

/App1/App1.iOS/MultilineTextCellRenderer.cs
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(App1.MultilineTextCell), typeof(App1.iOS.MultilineTextCellRenderer))]
namespace App1.iOS
{
    public class MultilineTextCellRenderer : TextCellRenderer
    {
        public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
        {
            var cell = base.GetCell(item, reusableCell, tv);
            cell.DetailTextLabel.Lines = 0;
            cell.DetailTextLabel.LineBreakMode = UILineBreakMode.WordWrap;
            return cell;
        }
    }
}

Android のカスタムレンダラー:

/App1/App1.Android/MultilineTextCellRenderer.cs
using Android.Content;
using Android.Views;
using Android.Widget;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(App1.MultilineTextCell), typeof(App1.Droid.MultilineTextCellRenderer))]
namespace App1.Droid
{
    public class MultilineTextCellRenderer : TextCellRenderer
    {
        protected override Android.Views.View GetCellCore(Cell item, Android.Views.View convertView, ViewGroup parent, Context context)
        {
            var cell = (LinearLayout)base.GetCellCore(item, convertView, parent, context);
            var detailText = (TextView)(cell.GetChildAt(1) as LinearLayout).GetChildAt(1);
            detailText.SetSingleLine(false);
            return cell;
        }
    }
}

XAML で利用します。

/App1/App1/Views/Page1.xaml
xmlns:local="clr-namespace:App1"
...
<TextCell Text="通常のTextCell" Detail="{Binding MultilineText}"/>
<local:MultilineTextCell Text="複数行テキスト" Detail="{Binding MultilineText}" />

iOS のスクリーンショット:
iOS.png

Android のスクリーンショット:
Android.png

以上、ツイートしながら コーディングしていました。

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2