What is the purpose of dynamically adding controls to controls?

So I know I’m awash in iOS framework questions probably asked by others over the last 7 months or so. Forgive me for any restatement of questions…

But what is the purpose of being able to dynamically add a control inside another control? No, I get it but you can’t put layout constraints inside a control. So for example, I can’t make a canvas subclass and add controls dynamically to the subclass and set constraints for them inside the canvas. In my code, I’d like to add an iOSImageView onto a canvas and make the iOSImage view to be equal to the size of the canvas. But I can’t do that in the subclass. Constraints have to be added to a view.

So then if I have to do all my adding of controls and setting constraints in a view, what is the purpose of being able to add controls inside other controls?

I suppose you could do operations on the control from methods and events inside its parent. But you still have to set all of its constraints in the view. Why not just add it to the view and go from there?

Or am I missing something?

From your subclass you would have to grab the view and then you could add the auto layout constraints, but AFAIK it is not possible to get the view from an iOSControl.

Well, I suppose you could add an event to the control and then raise the event in the Open event of the control. Then you could pass in the view. But why do that?

Why not be able to set up constraints inside a control if you can add a control to a control?

because that isn’t where they belong
controls dont own constraints
they are affected by the solution to the entire set of constraints the view has

the view basically solves ALL the constraints as one big set and then “applies” the results to the affected controls
not the other way round

now you might make an argument that a control COULD have an “add constraint” that just passes it through to the containing view
thats plausible and could be a reasonable feature request

but for now you add them to the containing view

OK, actually, that worked pretty well - adding an event definition to my subclass.

So I wanted to create an iOSImage view inside my canvas. Why? Because ImageViews scale the image - iOSCanvases do not (grr). ImageViews don’t have events like PointerDown, PointerUp and PointerDrag. So you have to use both…

So I created a method inside the canvas to create my iOSImageView. This method needs to be called AFTER the Canvas is added to the view and properly constrained so that the sizing gets correct. I have an event definition in the canvas that returns an iOSImage view. So in the view, where this event is handled, you return the view…

Sub CreateImageView()
  Dim iv as New iOSImageView
  
  iv.Image = MediaSwitcherIconBlue
  
  Dim v as iOSView = RaiseEvent GrabIOSView
  
  Dim lft as New iOSLayoutConstraint(iv, _
  iOSLayoutConstraint.AttributeTypes.Left, _
  IOSLayoutConstraint.RelationTypes.Equal, _
  me, _
  IOSLayoutConstraint.AttributeTypes.Left,1,0)
  
  Dim tp as New iOSLayoutConstraint(iv, _
  IOSLayoutConstraint.AttributeTypes.Top, _
  iOSLayoutConstraint.RelationTypes.Equal, _
  me, _
  iOSLayoutConstraint.AttributeTypes.Top,1,0)
  
  Dim wdth as New iOSLayoutConstraint(iv, _
  IOSLayoutConstraint.AttributeTypes.Width, _
  iOSLayoutConstraint.RelationTypes.Equal, _
  me, _
  iOSLayoutConstraint.AttributeTypes.width,1,0)
  
  Dim hgt as New iOSLayoutConstraint(iv, _
  IOSLayoutConstraint.AttributeTypes.Height, _
  iOSLayoutConstraint.RelationTypes.Equal, _
  me, _
  iOSLayoutConstraint.AttributeTypes.Height,1,0)
  
  
  me.AddControl(iv)
  v.AddConstraint(lft)
  v.AddConstraint(tp)
  v.AddConstraint(wdth)
  v.AddConstraint(hgt)
  
End Sub

Now I wonder what coding rules I’ve broken here. But it works! :slight_smile:

[quote=203818:@Norman Palardy]because that isn’t where they belong
controls dont own constraints
they are affected by the solution to the entire set of constraints the view has

the view basically solves ALL the constraints as one big set and then “applies” the results to the affected controls
not the other way round

now you might make an argument that a control COULD have an “add constraint” that just passes it through to the containing view
thats plausible and could be a reasonable feature request

but for now you add them to the containing view[/quote]

Is what I did considered “OK”? That way all the constraint code is handled inside the subclass but you are grabbing the view and applying it to the view…

I dont see anything wrong with what you’ve done.
You really don’t have any other way to get at the view.

[quote=203829:@Norman Palardy]I dont see anything wrong with what you’ve done.
You really don’t have any other way to get at the view.[/quote]

Thanks. I wanted to make sure I didn’t violate any best practices where all the adding of constraints should be done inside the view itself, etc.

But this is good then because now I have portable code that sets the image view to the same size as the canvas and loads the image…

Just FYI you can actually receive touch events using gesture recognizers without needing a canvas.
Example code using iOSKit (untested it’s off the top of my head):

[code]Declare sub setUserInteractionEnabled lib UIKitLib selector “setUserInteractionEnabled:” (obj_id as Ptr, yesNo as Boolean)
Declare sub addGestureRecognizer lib UIKitLib selector “addGestureRecognizer:” (obj_id as ptr, recognizer as Ptr)

setUserInteractionEnabled(MYIMAGEVIEW.Handle, true)
addGestureRecognizer(MYIMAGEVIEW.Handle, TapRecognizer)[/code]
You will have to add a UITapGestureRecognizer to the view called TapRecognizer and then put the above code in the open event. You will then get an event in the gesture recognizer object that you can parse to handle the tap as you are currently doing with the canvas. Maybe easier, maybe not, but you won’t have to put the image view inside of a canvas.

To get the location of the Tap you should be able to do the following in the Gesture event:

Dim location as NSPoint = additionData.locationInView(new UIView(MYIMAGEVIEW.Handle)) Dim point as new Xojo.core.point(location.x, location.y)
If you want to use a Xojo.core.point this code converts the location to that so it is just like the Canvas event.
Hopefully this helps and let me know if you have any questions,
Jason

Thanks, Jason…