UILabel と UITextField を配置したカスタムセルを自作した

登録画面で使うために、UILabel と UITextField を配置したカスタムセルを、コードだけで実装してみた。 Xamarin.Forms なら EntryCell があるけど、あいにく Xamarin.iOS で開発しているアプリなもので。

レイアウトはもちろん AutoLayout を使ってる。ただし、Storyboard を使わず、すべての制約をコードで指定した。Storyboard を使わなかったのは、宗教的な理由。Storyboard を使っていれば簡単に実装できたかもしれないが、すべてコードだと予想以上に苦労した。

using UIKit;

namespace CustomCellSample.Views
{
    public class TextFieldCell : UITableViewCell
    {
        public const string CellId = nameof(TextFieldCell);

        public UITextField TextField { get; }

        public UILabel TitleLabel { get; }

        NSLayoutConstraint TitleLabelWidth { get; }

        public TextFieldCell()
            : this(CellId)
        {
        }

        public TextFieldCell(string reuseIdentifier)
            : base(UITableViewCellStyle.Default, reuseIdentifier)
        {
            SelectionStyle = UITableViewCellSelectionStyle.None;

            TextField = new UITextField();
            TextField.BackgroundColor = UIColor.Yellow; // スクリーンショットでわかるように背景色を黄色にする

            TitleLabel = new UILabel();

            ContentView.AddSubview(TextField);
            ContentView.AddSubview(TitleLabel);

            TextField.TranslatesAutoresizingMaskIntoConstraints = false;
            TitleLabel.TranslatesAutoresizingMaskIntoConstraints = false;

            TextField.LeadingAnchor.ConstraintEqualTo(TitleLabel.TrailingAnchor, 5).Active = true;
            TextField.CenterYAnchor.ConstraintEqualTo(ContentView.CenterYAnchor).Active = true;
            TextField.TrailingAnchor.ConstraintEqualTo(LayoutMarginsGuide.TrailingAnchor).Active = true;

            TitleLabel.LeadingAnchor.ConstraintEqualTo(LayoutMarginsGuide.LeadingAnchor).Active = true;
            TitleLabel.CenterYAnchor.ConstraintEqualTo(ContentView.CenterYAnchor).Active = true;
            TitleLabelWidth = TitleLabel.WidthAnchor.ConstraintEqualTo(50); // とりあえず仮の幅を設定しておく
            TitleLabelWidth.Active = true;
        }

        public override void LayoutSubviews()
        {
            base.LayoutSubviews();

            // 実際に設定された文字列の幅ぴったりにする
            var rect = TitleLabel.SizeThatFits(ContentView.Frame.Size);
            TitleLabelWidth.Constant = rect.Width;
        }
    }
}

こんな感じで表示される。

f:id:griefworker:20171213223737p:plain