Does Infragistics publish any best practices for using the various NUCLiOS views with Apple's auto layout? If not, when is this planned? I'm building a library for managing auto layout NSLayoutConstraints programmatically and NUCLiOS auto layout best practices would be useful to me. I've tried moving away from autoresizingMask for IGChartView and IGRangeSelectorView but I am missing something with regards to how the frames are maintained internally. I would be willing to consult with the NUCLiOS team on how to convert the masks to NSLayoutConstraints, or to create a hybrid solution. Cheers.
Hi Caylan,
We do not have any best practices published for using Apple's AutoLayout system as there isn't anything special to our controls in that regard, as they're just UIView's and thus automatically get that behavior for free. And Apple already has quite a detailed explanation of how to use it.
That being said, I can't rule out the fact that there could very well be an issue with one of our controls, and if so, we'll definitely look into asap.
So, are you running into a specific issue with one of our controls, or are you just looking for a little guidance in general on how to create a specific layout using that system.
Either way, i'd be happy to help you. Just let me know how you're looking to lay out your view, a screenshot would probably be best. Also, the platform you're using would also be helpful (Objective-C or Xamarin.iOS)
Thanks,
-SteveZ
Stephen. Thanks for the reply. All of my development has been in Auto Layout. I'm not familiar with Springs and Struts (S&S) and autoresizing masks. I'm not sure where to "draw the line" so to speak, between the two layout systems.
For an example, each orange rect in the below image is a UIView in IB. The top UIView will be a container (property on the VC named self.chartViewContainer) for IGChartView (instance variable infraChart) and the bottom UIView will be a container (property on the VC named self.rangeViewContainer) for IGRangeSelectorView (instance variable rangeSelectorView).
Note: The numbers on the bottom 0...1000 are just UILabels and are not a part of the Infragistics NUCLiOS
In all of the examples I've seen, the preferred way to set this up using Springs&Struts (S&S) in viewWillAppear is:
infraChart.frame = CGRectMake(0, 0, self.chartViewContainer.frame.size.width - 25, self.chartViewContainer.frame.size.height);
infraChart.autoresizesSubviews = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
rangeSelectorView.frame = CGRectMake(10, 0, self.rangeViewContainer.frame.size.width - 10, self.rangeViewContainer.frame.size.height);
rangeSelectorView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
You can see from the above that the chart is inset 25 points from the right. The range selector is inset 10 points from the left and right.
My question is: If I manage the auto layout externally that affects the size/layout of the orange UIViews, what is the preferred method to control the interior of the UIViews and they're associated NUCLiOS views?
Hey Caylan,
In our samples we use autoResizingMasks b/c they're supported in older versions of iOS such as iOS 5 and also in my opinion they tend to be somewhat easier to write, at least once you understand them. That being said, you can still use the new iOS 6 layout system if you prefer.
But, to solve your problem, i believe the code you're looking for should look like this: (I've highlighted in bold my changes to your code. )
infraChart.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin;
rangeSelectorView.frame = CGRectMake(10, 0, self.rangeViewContainer.frame.size.width - 20, self.rangeViewContainer.frame.size.height);
rangeSelectorView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth | UIViewAutoResizingFlexibleLeftMargin | UIViewAutoResizingFlexibleRightMargin;
Basically, you just need to take advantage of the margins. You generally just specify where you padding is going to be. So if you have padding on the left, then use the left margin mask, if you want it on the top of it, then use the top mask, etc..
Also, when you setup your rangeSelector, you said you wanted 10 pts on the left and right. In order to do that you would subtract 20 from the width (10 for the left and 10 for the right)
Does this help, or did i completely misunderstand the question?
For auto layout, this is what I've tried:
<rangeViewContainer:0x9469cd0> (4 constraints)
1. @1000: <IGRangeSelectorView:0xf92b0f0>.leading == <rangeViewContainer:0x9469cd0>.leading + 10.0
2. @1000: <rangeViewContainer:0x9469cd0>.trailing == <IGRangeSelectorView:0xf92b0f0>.trailing + 10.0
3. @1000: <IGRangeSelectorView:0xf92b0f0>.top == <rangeViewContainer:0x9469cd0>.top + 10.0
4. @1000: <rangeViewContainer:0x9469cd0>.bottom == <IGRangeSelectorView:0xf92b0f0>.bottom + 10.0
The charViewContainer has similar constraints.
The code to achieve this broken layout is:
rangeSelectorView.translatesAutoresizingMaskIntoConstraints = NO;
infraChart.translatesAutoresizingMaskIntoConstraints = NO;
StretchToSuperview(infraChart, 50, 1000);
StretchToSuperview(rangeSelectorView, 10, 1000);
void StretchHorizontallyToSuperview(VIEW_CLASS *view, CGFloat indent, NSUInteger priority)
{
NSString *format = @"H:|-indent-[view]-indent-|";
NSDictionary *bindings = NSDictionaryOfVariableBindings(view);
NSDictionary *metrics = @{@"indent":@(indent)};
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:metrics views:bindings];
SE_InstallConstraints(constraints, priority, @"Stretch to Superview");
}
void StretchVerticallyToSuperview(VIEW_CLASS *view, CGFloat indent, NSUInteger priority)
NSString *format = @"V:|-indent-[view]-indent-|";
Using Spark Inspector you can see...
Where that first UIView is in the hierarchy like so...
If I assume that the reason this is broken is because the rangeSelectorView is somehow looking at it's superview for details on layout.
It seems I can fix the breakage if I wrap the rangeSelectorView in another UIView:
UIView *rangeWrapper = [[UIView alloc] initWithFrame:CGRectZero]; rangeSelectorView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;rangeWrapper.translatesAutoresizingMaskIntoConstraints = NO;[rangeWrapper addSubview:rangeSelectorView];[self.rangeViewContainer addSubview:rangeWrapper];StretchToSuperview(rangeWrapper, 10, 1000);
And obligatory 3D rendering...