I’m working on my first real iOS app and have a question…
I have what we could call a “volume slider” control that I have pretty much migrated over from my desktop app. This control can feature different things like just the slider. Or with options like labels, tick marks, an LED bar, etc. These features are set in the properties of the control in the IDE. And turning different features on and off affects the width of the control. For example. enabling labels and tick marks results in a wider control than just the slider by itself. In Desktop, this is easy as I can just set the width based upon the selected options. But in iOS, the width property is read only. How can I change the width of the control depending on the selected features? Or do I need to literally create multiple controls depending on what features I want enabled?
Does this make sense? I can post pictures if that helps.
Make a width constraint and give it a name. Then you adjust the size if the constraint.
So you have to do this on a control by control basis in the view? That makes it impossible to put sizing code inside the class. You have to basically raise an event in order to get or set the width then?
The constraint for a control is set on the control itself… and you could just generate them in code.
So I have sizing commands in the open event of the class. So I’ve created a property in the custom IOSCanvas class I’ve created called MyWidth that is an IOSLayoutContstaint. I raise an event to get the constraint from the view. If the returned value from that event is not Nil, then I go ahead and mess with the width.
What a lot of work to do.
When running up against stuff like this it really makes me wonder how the ultimate goal of code portability between all platforms is ever going to work…
The constraint for a control is set on the control itself… and you could just generate them in code.[/quote]
OK. It’s just somewhat confusing as the examples and some of the documentation for constraints talks about setting them and naming them in the inspector. If I can do it in the control that’s much better.
So we have this constructor:
iOSLayoutConstraint.Constructor(firstItem As Object, firstAttribute As AttributeTypes, relation As RelationTypes, secondItem As Object, secondAttribute As AttributeTypes, multiplier As Double, gap As StandardGap, priority As Double = 1000)
If I am doing this in the code for my custom control then:
firstItem = self (ie: the control).
Then seconditem would also equal self, yes?
I sure hope that this mess changes in iOS API2.0. This is a disaster. I’ve set a constraint but increasing the width via the constraint actually seems to make it narrower!
secondItem would be Nil. You aren’t defining the width based on the width of something else (secondItem) but based on the “addend” value:
Constructor(firstItem As Object, firstAttribute As AttributeTypes, relation As RelationTypes, secondItem As Object, secondAttribute As AttributeTypes, multiplier As Double, addend As Double, priority As Double = 1000)
However don’t forget that the constraint must be added to the parentControl / iOSView
Dim MyWidth As New iOSLayoutConstraint(self, _
self.Parent.AddConstraint(width) // if control is placed in another control
parentView.AddConstraint(width) //parentView would need to be passed back to the control subclass through an event or a property set at runtime
I was basically doing this:
MyWidth = New iOSLayoutConstraint(Self, _
I then attempt to adjust the width by adjusting the Offset value of the constraint. Doesn’t seem to do anything…
Setting it to StandardGap sort of locks the offset.
Set it to a value (double) and you can then call
MyWidth.offset = SomeOtherValue
Yeah, doesn’t do squat. I set it all up and adjusting the offset doesn’t adjust the width of the control at all.
Did you add the constraint to it’s parent using parentView.AddConstraint(theConstraint)?
Creating a constraint is one thing, adding it to the control/view that lays out the constraint is another.
[quote=474091:@Jeremie Leroy]Did you add the constraint to it’s parent using parentView.AddConstraint(theConstraint)?
Creating a constraint is one thing, adding it to the control/view that lays out the constraint is another.[/quote]
I was not aware it needed to be added to the view. I thought you just had to add it to the control.
OK. Wait. I’m in a custom control. There is no parentview item.
and be careful you dont have a constraint the IDE generated + the one you added programmatically
If you do and they are set to be the same priority then you can get weird results
This is the most bizarre and ridiculous way to size a control! It simply does to make any sense. I’m getting some results but still not what I’m expecting. And it seems like if I add the constraint to the control then I don’t need to add it again to the view.
But adjusting the offset still does nothing to the “width” property of the control. That’s what I’m trying to change. The width property always stays the same.
I’m about ready to start learning how to use Swift as this stuff I’m doing isn’t Xojo. It’s some weird Voodoo that is a whole new language to learn.
For those that care… Swift , unlike Xojo does not REQUIRE the use of Autolayout, giving the flexibility if the developer so desires to “manually” control all size and positional aspects of an object in a manner identical to how Xojo for Desktop currently does.
Autolayout lets you specify fixed layout positions just like if you had no autolayout
If you set everything to no second item and use just the fixed constant portion and adjust that then you might as well write “top = 345” or whatever else it is you want
And you can adjust that value in a constraint
every constraint is one simple equation
target property will be whatever you set in the IDE - a controls left, top, height, etc (basically me.)
the operator can be = , <=, >= etc and autolayout will ensure that this is respected
second reference may be another controls left, top, etc or the overall views left top etc
and it can be nil
the scale is a percentage (say you want one control to be 80% the width of another)
and constant is just that - a fixed value
creating a constraint that is “top = 300” is simple
you select the control
edit the default constraints by selecting the TOP constraint and pressing edit
and make sure things are set to
IS "equal to"
RELATIVE TO "Parent" <<<< this is like setting a controls top relative to the window
EDGE "top" <<< this + the previous set me.top = parent.top
SCALE "100%" << we dont want to scale out controls top by anything (this makes the scale 1.00)
OFFSET = 300
and this creates a constraint that is
me.top = parent.top * 1.0 + 300
if you really wanted you could use a scale of 0 and the constraint would be
me.top = parent.top * 0.0 + 300
having parent.top in there just means that IF the parent view has to move because there’s a new view about it(like a toolbar might be on a desktop app) your control will move within it
autolayout also lets you do things like “keep the edge of this control 10 pixels away from this other one regardless of the size of things”
Something you have to write code to do otherwise
Autolayout will do this automatically
Autolayout may require you to call invalidate to recalculate the layout and all its constraints
I dont think it automatically notices when you alter a constraint or the contant in one (that would be nice)
Its just a different way to do what a lot of us have long written a lot of code to do
Norman, thank you. It makes some sense. Xojo’s documentation on this is woefully inadequate and the examples are really crummy. I’m still trying to figure it all out.