Search code examples
iosxamarinxamarin.formsxamarin.iosautolayout

How to layout Custom iOS View (UIStackView / UILabel) in Xamarin Forms


I've been trying to implement a custom Checkbox Renderer + View in Xamarin Forms.

On iOS I have a problem with laying out self-defined checkboxes in combination with multiline labels; supposedly because I'm setting a fixed Frame for the view.
Without setting a Frame however, nothing will be displayed at all.


Multiline labels are getting cut off (see checkbox2):

Label content not fully shown

Here I increased the Frame's height of the UIStackView,
content of the label is fully shown now:

Label content fully shown


This is my current implementation:
public sealed class CheckboxView : UIStackView
{

    ...

    private void Setup()
    {
        //
        // Configure the StackView
        //

        Alignment = UIStackViewAlignment.Fill;
        Distribution = UIStackViewDistribution.FillProportionally;
        Axis = UILayoutConstraintAxis.Horizontal;
        Spacing = 15;

        Frame = new CGRect(0, 0, UIScreen.MainScreen.Bounds.Width, 20);

        //
        // Image + Image Holder View (checkbox)
        //

        imageView = new UIImageView();
        imageView.Frame = new CGRect(x: 0, y: 0, width: 20, height: 20);
        imageView.Image = UIImage.FromFile("checkbox-checked.png");

        var imageHolderView = new UIView();
        imageHolderView.WidthAnchor.ConstraintEqualTo(20).Active = true;
        imageHolderView.TranslatesAutoresizingMaskIntoConstraints = false;
        imageHolderView.BackgroundColor = UIColor.Red;

        imageHolderView.AddSubview(imageView);
        AddArrangedSubview(imageHolderView);
        
        //
        // Label
        //

        label = new UILabel();
        AddArrangedSubview(label);

        label.Text = text;
        label.Lines = 0;
        label.LineBreakMode = UILineBreakMode.WordWrap;
        label.Font = UIFont.PreferredCaption1;
        label.BackgroundColor = UIColor.Yellow;
    }
    
    ...

}

Instead of setting a Frame I also tried using Auto-Layout anchors to pin the top, left and right of the StackView to the Superview, unfortunately without much success.

Is there an easy solution for making the StackView automatically expand to the supposed height of the contained UILabel?


Solution

  • Horizontal UIStackView will auto adjust its height if you use AutoLayout. But you should add the correct Constraints. I use your code to create the custom Control with the constraints below, it works properly:

    var check = new CheckboxView();
    //Set this to enable AutoLayout
    check.TranslatesAutoresizingMaskIntoConstraints = false;
    View.AddSubview(check);
    
    check.TopAnchor.ConstraintEqualTo(TopLayoutGuide.GetBottomAnchor()).Active = true;
    //Set some long string
    check.labelText = "some string...";
    check.LeadingAnchor.ConstraintEqualTo(View.LeadingAnchor).Active = true;
    check.WidthAnchor.ConstraintEqualTo(120).Active = true;