如何为UITableView提供与内置单元格布局指标一致的自定义UITableCell
解决UITableViewCell子视图默认边距匹配iOS系统标准的问题
你完全没必要用硬编码的魔法数字!iOS其实提供了两种靠谱的方式,让你的自定义单元格子视图自动匹配系统标准边距,下面给你详细说明:
一、直接利用系统布局边距(推荐方案)
从iOS 8开始,苹果就引入了layoutMargins和preservesSuperviewLayoutMargins属性,你可以直接在自定义单元格里开启这个特性,让子视图自动遵循系统的默认边距,不用手动计算各种数值。
修改你的UITextSingleline类代码如下:
internal class UITextSingleline : UITableViewCell { UILabel headingLabel; UITextView textBox; int MultiHeight; public bool secure; public UITextSingleline() : this(null, 1) { } public UITextSingleline(int multiheight) : this(null, multiheight) { } public UITextSingleline(NSString cellId, int multiheight) : base(UITableViewCellStyle.Default, cellId) { MultiHeight = multiheight; SelectionStyle = UITableViewCellSelectionStyle.None; // 开启布局边距继承,让单元格内容跟着系统走 PreservesSuperviewLayoutMargins = true; ContentView.PreservesSuperviewLayoutMargins = true; headingLabel = new UILabel() { Font = UIFont.SystemFontOfSize(16), TextColor = UIColor.DarkTextColor, BackgroundColor = UIColor.Clear, // 关闭自动布局转换,改用约束绑定 TranslatesAutoresizingMaskIntoConstraints = false }; textBox = new UITextView() { ClipsToBounds = true, Font = UIFont.SystemFontOfSize(16), TextColor = UIColor.DarkTextColor, TranslatesAutoresizingMaskIntoConstraints = false }; if (multiheight == 1) textBox.TextContainer.MaximumNumberOfLines = 1; textBox.Layer.CornerRadius = 10.0f; textBox.Layer.BorderColor = UIColor.DarkTextColor.CGColor; textBox.Layer.BorderWidth = 1f; ContentView.AddSubviews(new UIView[] { headingLabel, textBox }); // 使用Auto Layout绑定到系统布局边距指南 NSLayoutConstraint.ActivateConstraints(new[] { headingLabel.TopAnchor.ConstraintEqualTo(ContentView.LayoutMarginsGuide.TopAnchor, 8), headingLabel.LeadingAnchor.ConstraintEqualTo(ContentView.LayoutMarginsGuide.LeadingAnchor), headingLabel.TrailingAnchor.ConstraintEqualTo(ContentView.LayoutMarginsGuide.TrailingAnchor), headingLabel.HeightAnchor.ConstraintEqualTo(20), textBox.TopAnchor.ConstraintEqualTo(headingLabel.BottomAnchor, 4), textBox.LeadingAnchor.ConstraintEqualTo(ContentView.LayoutMarginsGuide.LeadingAnchor), textBox.TrailingAnchor.ConstraintEqualTo(ContentView.LayoutMarginsGuide.TrailingAnchor), textBox.HeightAnchor.ConstraintEqualTo(36 * MultiHeight), textBox.BottomAnchor.ConstraintEqualTo(ContentView.LayoutMarginsGuide.BottomAnchor, -8) }); } // 不需要再重写LayoutSubviews了,Auto Layout会自动适配所有设备和系统版本 // public override void LayoutSubviews() { ... } public void UpdateCell(string caption, string text) { headingLabel.Text = caption; textBox.Text = text; } public string Text { get { return textBox?.Text; } set { if (textBox != null) textBox.Text = value; } } }
这种方式的优势在于:系统会根据当前设备(iPhone/iPad)、iOS版本甚至界面状态(比如横屏、分屏模式)自动调整边距,完全不用你手动维护数值。
二、手动获取系统标准边距指标
如果你因为某些限制不能用Auto Layout,也可以直接读取系统的布局边距值来替代硬编码的数字:
public override void LayoutSubviews() { base.LayoutSubviews(); // 获取ContentView的系统默认边距 var margins = ContentView.LayoutMargins; // 用系统边距代替魔法数字16 headingLabel.Frame = new CGRect(margins.Left, 8, ContentView.Bounds.Width - margins.Left - margins.Right, 20); textBox.Frame = new CGRect(margins.Left, 32, ContentView.Bounds.Width - margins.Left - margins.Right, 36 * MultiHeight); }
另外你提到的separatorInset,它是控制表格分隔线缩进的属性,系统默认会让单元格内容边距和分隔线缩进保持一致,所以只要你的表格没有自定义separatorInset,ContentView.LayoutMargins就会自动匹配这个值,不用额外处理。
补充:关于系统控件圆角半径
如果想精准匹配系统控件的圆角半径,iOS 13+可以直接读取系统默认配置:
// 获取系统默认控件圆角值 var defaultCornerRadius = UIButton.Configuration.Default.CornerRadius; textBox.Layer.CornerRadius = defaultCornerRadius;
内容的提问来源于stack exchange,提问作者Cee McSharpface
相关产品推荐
相关产品推荐

