As I’m integrating a native iOS screen in a Flutter plugin I have to set constraints programmatically for the ui as there is no storyboard.
I have these UI components:
var overlayMaskView: UIView = UIView()
var previewView: UIView = UIView()
var stillImagePreviewView: UIImageView = UIImageView()
var viewFinderShapeLabel: UILabel = UILabel()
var viewfinderShapeType: UISegmentedControl = UISegmentedControl()
var vehicleTypeLabel: UILabel = UILabel()
var vehicleType: UISegmentedControl = UISegmentedControl()
I’m reading their constraints from the storyboard but I’m struggling to replicate them programmatically.
I was able to set constraints for overlayMaskView
, previewView
and stillImagePreviewView
four anchors to the safe area anchors.
// view.translatesAutoresizingMaskIntoConstraints = false
previewView.translatesAutoresizingMaskIntoConstraints = false
previewView.backgroundColor = UIColor.black//.black
previewView.contentMode = .scaleToFill
previewView.isUserInteractionEnabled = true
previewView.isOpaque = true
previewView.clearsContextBeforeDrawing = true
previewView.clipsToBounds = false
previewView.autoresizesSubviews = true
view.addSubview(previewView)
previewView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 0).isActive = true
previewView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: 0).isActive = true
previewView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 0).isActive = true
previewView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 0).isActive = true
stillImagePreviewView.translatesAutoresizingMaskIntoConstraints = false
stillImagePreviewView.contentMode = .scaleAspectFit
stillImagePreviewView.isUserInteractionEnabled = false
stillImagePreviewView.isOpaque = true
stillImagePreviewView.clearsContextBeforeDrawing = true
stillImagePreviewView.clipsToBounds = true
stillImagePreviewView.autoresizesSubviews = true
view.addSubview(stillImagePreviewView)
stillImagePreviewView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 0).isActive = true
stillImagePreviewView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: 0).isActive = true
stillImagePreviewView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 0).isActive = true
stillImagePreviewView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 0).isActive = true
overlayMaskView.translatesAutoresizingMaskIntoConstraints = false
overlayMaskView.contentMode = .scaleToFill
overlayMaskView.isUserInteractionEnabled = true
overlayMaskView.isOpaque = true
overlayMaskView.clearsContextBeforeDrawing = true
overlayMaskView.clipsToBounds = false
overlayMaskView.autoresizesSubviews = true
view.addSubview(overlayMaskView)
overlayMaskView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 0).isActive = true
overlayMaskView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: 0).isActive = true
overlayMaskView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 0).isActive = true
overlayMaskView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 0).isActive = true
Then the first label viewFinderShapeLabel
which has center x aligned to the view x axis, a top anchor to the safe area top anchor with a constant of 8, leading and trailing anchors to the safe area leading and trailing anchors with a constant of 16.
So i set them all like so and it’s at desired position :
viewFinderShapeLabel.translatesAutoresizingMaskIntoConstraints = false
viewFinderShapeLabel.text = "Formato targa"
viewFinderShapeLabel.textAlignment = .center
viewFinderShapeLabel.textColor = UIColor.white
viewFinderShapeLabel.isEnabled = true
viewFinderShapeLabel.isUserInteractionEnabled = false
viewFinderShapeLabel.isOpaque = false
viewFinderShapeLabel.clearsContextBeforeDrawing = true
viewFinderShapeLabel.autoresizesSubviews = true
view.addSubview(viewFinderShapeLabel)
viewFinderShapeLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0).isActive = true
viewFinderShapeLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 8).isActive = true
viewFinderShapeLabel.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 16).isActive = true
viewFinderShapeLabel.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -16).isActive = true
Then there is the first segmented controller which also has center x aligned to the view x axis, leading and trailing anchors to the safe area leading and trailing anchors with a constant of 16, but its top anchor to the viewFinderShapeLabel’s bottom anchor with a constant of 8.
viewfinderShapeType.translatesAutoresizingMaskIntoConstraints = false
viewfinderShapeType = UISegmentedControl(items: ["RETTANGOLARE", "QUADRATA"])
viewfinderShapeType.setEnabled(true, forSegmentAt: 0)
viewfinderShapeType.setEnabled(true, forSegmentAt: 1)
viewfinderShapeType.selectedSegmentIndex = 0
viewfinderShapeType.isEnabled = true
viewfinderShapeType.isUserInteractionEnabled = true
viewfinderShapeType.clearsContextBeforeDrawing = true
viewfinderShapeType.autoresizesSubviews = true
view.addSubview(viewfinderShapeType)
viewfinderShapeType.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0).isActive = true
viewfinderShapeType.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 16).isActive = true
viewfinderShapeType.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -16).isActive = true
viewfinderShapeType.topAnchor.constraint(equalTo: viewFinderShapeLabel.bottomAnchor, constant: 8).isActive = true
This setup fails as the segmented control is placed at the top left corner without any spacing.
What am I doing wrong causing these latest constraints not to work?
2
Answers
I don’t quite understand how you want to create the UI… Below is an example based on your code that could help you, the part that changes color is already an imageView:
You have created a segmented control as a property of your class:
The reason your code puts the segmented control at top left is due to these two lines:
The first line sets
.translatesAutoresizingMaskIntoConstraints = false
on the control which is a property of your class.The second line creates a NEW
UISegmentedControl
… which does not have.translatesAutoresizingMaskIntoConstraints
set tofalse
… and assigns that new control to the class property.You could either swap the order of those two lines (create the new instance and then set translates…), or,
declare your control like this:
and get rid of this line: