这是@rob_mayoff对以代码为中心的方法的出色回答的一个端口,使用NSLayoutAnchor对象并移植到Xamarin。对我来说,NSLayoutAnchor和相关类使AutoLayout更容易编程:
public class ContentView : UIView
{
public ContentView (UIColor fillColor)
{
BackgroundColor = fillColor;
}
}
public class MyController : UIViewController
{
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
//Starting point:
var view = new ContentView (UIColor.White);
blueView = new ContentView (UIColor.FromRGB (166, 200, 255));
view.AddSubview (blueView);
lightGreenView = new ContentView (UIColor.FromRGB (200, 255, 220));
lightGreenView.Frame = new CGRect (20, 40, 200, 60);
view.AddSubview (lightGreenView);
pinkView = new ContentView (UIColor.FromRGB (255, 204, 240));
view.AddSubview (pinkView);
greenView = new ContentView (UIColor.Green);
greenView.Frame = new CGRect (80, 20, 40, 200);
pinkView.AddSubview (greenView);
//Now start doing in code the things that @rob_mayoff did in IB
//Make the blue view size up to its parent, but half the height
blueView.TranslatesAutoresizingMaskIntoConstraints = false;
var blueConstraints = new []
{
blueView.LeadingAnchor.ConstraintEqualTo(view.LayoutMarginsGuide.LeadingAnchor),
blueView.TrailingAnchor.ConstraintEqualTo(view.LayoutMarginsGuide.TrailingAnchor),
blueView.TopAnchor.ConstraintEqualTo(view.LayoutMarginsGuide.TopAnchor),
blueView.HeightAnchor.ConstraintEqualTo(view.LayoutMarginsGuide.HeightAnchor, (nfloat) 0.5)
};
NSLayoutConstraint.ActivateConstraints (blueConstraints);
//Make the pink view same size as blue view, and linked to bottom of blue view
pinkView.TranslatesAutoresizingMaskIntoConstraints = false;
var pinkConstraints = new []
{
pinkView.LeadingAnchor.ConstraintEqualTo(blueView.LeadingAnchor),
pinkView.TrailingAnchor.ConstraintEqualTo(blueView.TrailingAnchor),
pinkView.HeightAnchor.ConstraintEqualTo(blueView.HeightAnchor),
pinkView.TopAnchor.ConstraintEqualTo(blueView.BottomAnchor)
};
NSLayoutConstraint.ActivateConstraints (pinkConstraints);
//From here, address the aspect-fitting challenge:
lightGreenView.TranslatesAutoresizingMaskIntoConstraints = false;
//These are the must-fulfill constraints:
var lightGreenConstraints = new []
{
//Aspect ratio of 1 : 5
NSLayoutConstraint.Create(lightGreenView, NSLayoutAttribute.Height, NSLayoutRelation.Equal, lightGreenView, NSLayoutAttribute.Width, (nfloat) 0.20, 0),
//Cannot be larger than parent's width or height
lightGreenView.WidthAnchor.ConstraintLessThanOrEqualTo(blueView.WidthAnchor),
lightGreenView.HeightAnchor.ConstraintLessThanOrEqualTo(blueView.HeightAnchor),
//Center in parent
lightGreenView.CenterYAnchor.ConstraintEqualTo(blueView.CenterYAnchor),
lightGreenView.CenterXAnchor.ConstraintEqualTo(blueView.CenterXAnchor)
};
//Must-fulfill
foreach (var c in lightGreenConstraints)
{
c.Priority = 1000;
}
NSLayoutConstraint.ActivateConstraints (lightGreenConstraints);
//Low priority constraint to attempt to fill parent as much as possible (but lower priority than previous)
var lightGreenLowPriorityConstraints = new []
{
lightGreenView.WidthAnchor.ConstraintEqualTo(blueView.WidthAnchor),
lightGreenView.HeightAnchor.ConstraintEqualTo(blueView.HeightAnchor)
};
//Lower priority
foreach (var c in lightGreenLowPriorityConstraints)
{
c.Priority = 750;
}
NSLayoutConstraint.ActivateConstraints (lightGreenLowPriorityConstraints);
//Aspect-fit on the green view now
greenView.TranslatesAutoresizingMaskIntoConstraints = false;
var greenConstraints = new []
{
//Aspect ratio of 5:1
NSLayoutConstraint.Create(greenView, NSLayoutAttribute.Height, NSLayoutRelation.Equal, greenView, NSLayoutAttribute.Width, (nfloat) 5.0, 0),
//Cannot be larger than parent's width or height
greenView.WidthAnchor.ConstraintLessThanOrEqualTo(pinkView.WidthAnchor),
greenView.HeightAnchor.ConstraintLessThanOrEqualTo(pinkView.HeightAnchor),
//Center in parent
greenView.CenterXAnchor.ConstraintEqualTo(pinkView.CenterXAnchor),
greenView.CenterYAnchor.ConstraintEqualTo(pinkView.CenterYAnchor)
};
//Must fulfill
foreach (var c in greenConstraints)
{
c.Priority = 1000;
}
NSLayoutConstraint.ActivateConstraints (greenConstraints);
//Low priority constraint to attempt to fill parent as much as possible (but lower priority than previous)
var greenLowPriorityConstraints = new []
{
greenView.WidthAnchor.ConstraintEqualTo(pinkView.WidthAnchor),
greenView.HeightAnchor.ConstraintEqualTo(pinkView.HeightAnchor)
};
//Lower-priority than above
foreach (var c in greenLowPriorityConstraints)
{
c.Priority = 750;
}
NSLayoutConstraint.ActivateConstraints (greenLowPriorityConstraints);
this.View = view;
view.LayoutIfNeeded ();
}
}