FluentLayout v2.5 Released

It's been a little over a year since the last FluentLayout update, so it seemed like a good time to get some little improvements in. I also definitely want to give a shout out to Diego Ponce de León for prompting some of these changes and helping brainstorm some things!

If you're using FluentLayout, I'd definitely love to hear your input on improvements you'd like to see, shortcomings, etc. There's a lot more we can do in FluentLayout, so I'd like to start gathering some ideas in order to set things up for an eventual 3.0 release where we can also reshape the API as needed.

In the meantime, here's some of the new little improvements in 2.5, which is now available on NuGet!

Constraint Identifiers

You can now specify an identifier string to be assigned to the constraint that gets created. You can set this through the Identifier property on FluentLayout, or set it through the fluent interface:

label.Height().EqualTo(ViewModel.Constant).WithIdentifier("labelHeight");

Additionally, the helper for creating a vertical stack layout has been updated to automatically generate predictable identifiers for all the constraints it creates. These identifiers are in the form of {containerId}-{viewId}-{constraintDescription}:

  • containerId will be the container view's AccessibilityIdentifier if one is set, and VerticalStackPanel if not
  • viewId will be the subview's AccessibilityIdentifier if one is set, and the subview's index in the array if not
  • constraintDescription will be based on the constraint itself, such as Bottom, Top, Width, etc.

Updating Existing FluentLayouts

This was the primary change that I wanted to get in, and should hopefully help clean things up for everyone. Prior to now, the properties on FluentLayout would just be used when the constraint gets created, and then have no effect after that. In version 2.5 we allow for updating Constant, Priority, Identifier, and Active after the constraint has been created, which will update the underlying constraint if one had been created. Active is also a new property, which allows you to easily switch a constraint on and off.

A demo of this was added to the sample application, which allows you to alter the height constraint of a label through the UI, as well as toggle it on and off:

Updating live constraints

Wiring this up in an MvvmCross app to use databinding to update the constraint directly is trivial (full code available in the sample app):

var toggleHeight = new UISwitch();
var heightConstant = new UISlider();

var heightLayout = label.Height().EqualTo(ViewModel.Constant);

View.AddConstraints(
	heightLayout
);

var set = this.CreateBindingSet<UpdateConstraintsView, UpdateConstraintsViewModel>();
set.Bind(heightLayout).For(layout => layout.Active).To(vm => vm.Active);
set.Bind(heightLayout).For(layout => layout.Constant).To(vm => vm.Constant);
set.Bind(toggleHeight).To(vm => vm.Active);
set.Bind(heightConstant).To(vm => vm.Constant);
set.Apply();

Deprecating ToLayoutConstraints()

As part of figuring out the right way to implement that last part, I was reminded that the existing ToLayoutConstraints() method on FluentLayout is a bit of an odd API. It would take the properties of the class and create a new NSLayoutConstraint object based on them, which was used in the extension methods to add the constraint to a view, but also exposed publicly as well. It was also returning a collection of constraints, despite there only ever being one constraint created and included in that collection.

As part of FluentLayout 2.5 we are deprecating ToLayoutConstraints(), and expect to remove it in a 3.0 release. Now that FluentLayout is a smarter abstraction over the underlying constraint we wanted to internalize the actual constraint as much as possible. If there's still a reason you need to call this method in your app please do let me know! If there's a valid need we can consider exposing the Constraint property publicly (it's currently marked as internal).

AdvancedVerticalStackPanelConstraints

This is a new extension contributed by Diego Ponce de León to allow for setting independent left, right, and top margins for children in a vertical stack. You can find an example in the sample app, which looks like this:

Advanced vertical stack layout

The syntax of the method is very similar to the existing vertical stack helper:

var marginMultiplier = UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Pad ? 2 : 1;
var constraints = View.AdvancedVerticalStackPanelConstraints(
  new Margins(20, 10, 20, 10, 5, 5),
  leftMargins.ToArray(),
  topMargins.ToArray(),
  rightMargins.ToArray(),
  marginMultiplier,
  View.Subviews);
View.AddConstraints(constraints);

Miscellaneous

Those are the main improvements, but we also made some changes under the hood as well, largely around code cleanup. The sample app was migrated to MvvmCross 4.0 to help make sure things work correctly on the latest and greatest there. We also moved the repository over to its own organization on GitHub, added build scripts using FAKE, and set up CI builds with Bitrise! Build status will be reported in pull requests:

Build status in pull request

Have an idea or feature request for something you'd like to see in FluentLayout? Let us know!

comments powered by Disqus
Navigation