代码之家  ›  专栏  ›  技术社区  ›  Cee McSharpface

如何将自定义“uitablecell”提供给“uitableview”,使其具有内置单元格所具有的相同布局度量?

  •  0
  • Cee McSharpface  · 技术社区  · 6 年前

    当我向原型表单元添加子视图时,假设 UITextView ,则默认情况下没有左边距。 我希望它使用与ios内部用于内置标准单元布局相同的边距。 如果我忽略了显而易见的一点,“使用设备/ios默认值”标志在哪里?否则,我首选的解决方案是查询设备的设备相关和ios版本相关ui度量的方法。对于这个问题,我们可以将其限制为 UITableView 控制及其 UITableCell 后代。

    这就是我生成自定义单元格的方式:

        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;            
                headingLabel = new UILabel()
                {
                    Font = UIFont.SystemFontOfSize(16),
                    TextColor = UIColor.DarkTextColor,
                    BackgroundColor = UIColor.Clear
                };
    
                textBox = new UITextView()
                {                
                    ClipsToBounds = true,
                    Font = UIFont.SystemFontOfSize(16),
                    TextColor = UIColor.DarkTextColor
                };
    
                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 });               
            }
    
            public override void LayoutSubviews()
            {
                base.LayoutSubviews();
                headingLabel.Frame = new CGRect(16, 8, ContentView.Bounds.Width - 32, 20);
                textBox.Frame = new CGRect(16, 32, ContentView.Bounds.Width - 32, 36 * MultiHeight); /* see? magic numbers all over the place */
            }
    
            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;
                }
            }
        }
    

    这就是它链接到包含表视图的方式:

    public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
    {
        switch (indexPath.Section)
        {
            case 0:
                /* area/workplace */
                switch (indexPath.Row)
                {
                    case 0:
                        /* area picker (omitted) */
                    case 1:
                        /* workplace text input (single-line) */
                        if (txtWorkplace == null)
                        {
                            txtWorkplace = new UITextSingleline();
                            txtWorkplace.UpdateCell("Workplace", Data.Instance.Payload.report.workplace);
                        }
                        return txtWorkplace;
                }
                break;
            case 1:
                /* rest ommitted for brevity */
                break;
        }
        return null;
    }
    

    我搜索了So和Internet,寻找与SystemMetrics等效的内容,有很多颜色和字体,但我发现关于尺寸、边距、插页、角半径等的信息很少:

    • This question 处理相反的问题,去掉任何保证金,并且没有提到如何复制ios的默认值。
    • This page from apple dev 提到 separatorInset 整体属性 TableView ,这似乎适用于左缩进,但我对将布局的一部分的度量应用于另一部分有点怀疑。

    硬编码的幻数不是一个选项。我们在iphone和ipad上进行了测试,发现即使在同一台设备上,只有ios版本不同,inset的默认值也不尽相同。 我也很乐意使用objective-c和swift提示和解决方案,只要它们能在xamarin中正确翻译。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Ax1le    6 年前

    如果要根据不同设备或不同版本使用默认边距,为什么不尝试自动布局? NSLayoutAttribute.LeadingMargin 表示元素边距的默认前缘。在你的 UITextSingleline 修改 LayoutSubviews() 从硬代码到自动布局:

    假设单元格只有一个标签来显示某些文本:

    public override void LayoutSubviews()
    {
        base.LayoutSubviews();
    
        var leadingConstraint = NSLayoutConstraint.Create(headingLabel, NSLayoutAttribute.Leading, NSLayoutRelation.Equal, ContentView, NSLayoutAttribute.LeadingMargin, 1.0f, 0);
        var topConstraint = NSLayoutConstraint.Create(headingLabel, NSLayoutAttribute.Top, NSLayoutRelation.Equal, ContentView, NSLayoutAttribute.TopMargin, 1.0f, 0);
        var trailingConstraint = NSLayoutConstraint.Create(headingLabel, NSLayoutAttribute.Trailing, NSLayoutRelation.Equal, ContentView, NSLayoutAttribute.TrailingMargin, 1.0f, 0);
        var bottomConstraint = NSLayoutConstraint.Create(headingLabel, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, ContentView, NSLayoutAttribute.BottomMargin, 1.0f, 0);
    
        ContentView.AddConstraints(new NSLayoutConstraint[] { leadingConstraint, topConstraint, trailingConstraint, bottomConstraint });
    }
    

    这样的话, headingLabel 将具有与“标准内置单元格的文本标签”相同的布局。

    此外,在您的情况下,似乎您要添加 UITextView 也在你的牢房里。我建议您在构造函数时添加约束,我提供我的约束供您参考:

    public MyTableViewCell (IntPtr handle) : base (handle)
    {
        headingLabel = new UILabel()
        {
            Font = UIFont.SystemFontOfSize(17),
            TextColor = UIColor.DarkTextColor,
            BackgroundColor = UIColor.Clear,
            Lines = 0
        };
    
        textBox = new UITextView()
        {
            ClipsToBounds = true,
            Font = UIFont.SystemFontOfSize(16),
            TextColor = UIColor.DarkTextColor
        };
    
        ContentView.AddSubview(headingLabel);
        ContentView.AddSubview(textBox);
    
        // Disable this to enable autolayout
        headingLabel.TranslatesAutoresizingMaskIntoConstraints = false;
        textBox.TranslatesAutoresizingMaskIntoConstraints = false;
    
        doLayouts();
    }
    
    void doLayouts()
    {
    
        var leadingConstraint = NSLayoutConstraint.Create(headingLabel, NSLayoutAttribute.Leading, NSLayoutRelation.Equal, ContentView, NSLayoutAttribute.LeadingMargin, 1.0f, 0);
        var topConstraint = NSLayoutConstraint.Create(headingLabel, NSLayoutAttribute.Top, NSLayoutRelation.Equal, ContentView, NSLayoutAttribute.TopMargin, 1.0f, 0);
        var trailingConstraint = NSLayoutConstraint.Create(headingLabel, NSLayoutAttribute.Trailing, NSLayoutRelation.Equal, ContentView, NSLayoutAttribute.TrailingMargin, 1.0f, 0);
    
        ContentView.AddConstraints(new NSLayoutConstraint[] { leadingConstraint, topConstraint, trailingConstraint });
    
        var boxLeading = NSLayoutConstraint.Create(textBox, NSLayoutAttribute.Leading, NSLayoutRelation.Equal, ContentView, NSLayoutAttribute.LeadingMargin, 1.0f, 0);
        var boxTop = NSLayoutConstraint.Create(textBox, NSLayoutAttribute.Top, NSLayoutRelation.Equal, headingLabel, NSLayoutAttribute.Bottom, 1.0f, 4);
        var boxTrailing = NSLayoutConstraint.Create(textBox, NSLayoutAttribute.Trailing, NSLayoutRelation.Equal, ContentView, NSLayoutAttribute.TrailingMargin, 1.0f, 0);
        var boxBottom = NSLayoutConstraint.Create(textBox, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, ContentView, NSLayoutAttribute.BottomMargin, 1.0f, 0);
        var boxHeight = NSLayoutConstraint.Create(textBox, NSLayoutAttribute.Height, NSLayoutRelation.Equal, null, NSLayoutAttribute.NoAttribute, 1.0f, 36 * MultiHeight);
    
        ContentView.AddConstraints(new NSLayoutConstraint[] { boxLeading, boxTop, boxTrailing, boxBottom, boxHeight });
    }
    

    使用autolayout的另一个好处是:将tableview的rowheight设置为 UITableView.AutomaticDimension 如果我们设置了正确的约束,单元格将根据内容自动计算行高。