Программно применяемые ограничения не работают в ViewController

Поскольку я интегрирую собственный экран iOS в плагин Flutter, мне приходится программно устанавливать ограничения для пользовательского интерфейса, поскольку раскадровки нет.

У меня есть эти компоненты пользовательского интерфейса:

    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()

Я читаю их ограничения из раскадровки, но изо всех сил пытаюсь воспроизвести их программно. Мне удалось установить ограничения для overlayMaskView, previewView и stillImagePreviewView четырех привязок к привязкам безопасной области.

//        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

Затем первая метка viewFinderShapeLabel, центр которой x выровнен по оси x вида, верхняя привязка к верхней привязке безопасной области с константой 8, ведущие и конечные привязки к ведущей и завершающей привязке безопасной области с константой 16. Итак, я установил их все так, и они оказались в нужном положении:

        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

Затем есть первый сегментированный контроллер, у которого центр x также выровнен по оси x представления, ведущие и конечные привязки к ведущей и конечной привязкам безопасной области с константой 16, а его верхняя привязка к нижней привязке viewFinderShapeLabel с константой 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

Эта настройка не удалась, поскольку сегментированный элемент управления размещается в верхнем левом углу без каких-либо интервалов.

Что я делаю неправильно, из-за чего эти последние ограничения не работают?

Нет смысла устанавливать одновременно ведущие/конечные привязки и привязку centerx. Либо установите центр и ширину, либо установите ведущие/конечные привязки.

Paulw11 19.08.2024 13:25

Привет, @Paulw11, давно я не задавал вопрос, связанный со Swift. Действительно, использование трех ограничений излишне, я знаю, на самом деле я буду использовать только конечные и ведущие.

Vincenzo 19.08.2024 13:44

@Фабио, я собирался спросить тебя о твоем ответе, но он был удален??

Vincenzo 19.08.2024 13:58
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
51
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я не совсем понимаю, как вы хотите создать пользовательский интерфейс... Ниже приведен пример, основанный на вашем коде, который может вам помочь, часть, которая меняет цвет, уже является imageView:

import UIKit

var overlayMaskView = UIView()
var previewView = UIView()
var stillImagePreviewView = UIImageView()
var viewFinderShapeLabel = UILabel()
var viewfinderShapeType = UISegmentedControl()
var vehicleTypeLabel = UILabel()
var vehicleType = UISegmentedControl()

class ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()

view.backgroundColor = .black

previewView.translatesAutoresizingMaskIntoConstraints = false
previewView.backgroundColor = UIColor.red //.black
view.addSubview(previewView)
previewView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
previewView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
previewView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
previewView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true

viewFinderShapeLabel.translatesAutoresizingMaskIntoConstraints = false
viewFinderShapeLabel.text = "Formato targa"
viewFinderShapeLabel.font = .systemFont(ofSize: 16, weight: .bold)
viewFinderShapeLabel.textAlignment = .center
viewFinderShapeLabel.textColor = .white
previewView.addSubview(viewFinderShapeLabel)
viewFinderShapeLabel.heightAnchor.constraint(equalToConstant: 30).isActive = true
viewFinderShapeLabel.topAnchor.constraint(equalTo: previewView.topAnchor, constant: 16).isActive = true
viewFinderShapeLabel.leadingAnchor.constraint(equalTo: previewView.leadingAnchor, constant: 16).isActive = true
viewFinderShapeLabel.trailingAnchor.constraint(equalTo: previewView.trailingAnchor, constant: -16).isActive = true

let items = ["RETTANGOLARE", "QUADRATA"]
viewfinderShapeType = UISegmentedControl(items: items)
viewfinderShapeType.selectedSegmentIndex = 0
viewfinderShapeType.layer.cornerRadius = 5.0
viewfinderShapeType.backgroundColor = .white.withAlphaComponent(0.5)
viewfinderShapeType.addTarget(self, action: #selector(change), for: .valueChanged)
viewfinderShapeType.translatesAutoresizingMaskIntoConstraints = false

previewView.addSubview(viewfinderShapeType)
viewfinderShapeType.topAnchor.constraint(equalTo: viewFinderShapeLabel.bottomAnchor, constant: 10).isActive = true
viewfinderShapeType.centerXAnchor.constraint(equalTo: previewView.centerXAnchor).isActive = true

stillImagePreviewView.translatesAutoresizingMaskIntoConstraints = false
stillImagePreviewView.contentMode = .scaleAspectFit
stillImagePreviewView.isUserInteractionEnabled = false
stillImagePreviewView.backgroundColor = .white
view.addSubview(stillImagePreviewView)
stillImagePreviewView.leadingAnchor.constraint(equalTo: previewView.leadingAnchor, constant: 0).isActive = true
stillImagePreviewView.trailingAnchor.constraint(equalTo: previewView.trailingAnchor, constant: 0).isActive = true
stillImagePreviewView.topAnchor.constraint(equalTo: viewfinderShapeType.bottomAnchor, constant: 20).isActive = true
stillImagePreviewView.bottomAnchor.constraint(equalTo: previewView.bottomAnchor, constant: 0).isActive = true
}

@objc fileprivate func change() {
if stillImagePreviewView.backgroundColor == .white {
    stillImagePreviewView.backgroundColor = .systemOrange
} else {
    stillImagePreviewView.backgroundColor = .white
  }
 }
}

Приятно, спасибо! Я изучаю это, чтобы понять, почему моя версия не работает... как и в вашей версии верхняя привязка для сегментированного элемента управления связана с нижней привязкой метки. Я попробовал ваши настройки в своем контроллере представления, и они работают.. все равно что-то в моих настройках нарушает его, и сегментированный элемент управления оказывается в верхнем левом углу.. Я наверняка неправильно устанавливаю некоторые параметры.

Vincenzo 19.08.2024 15:28

@Винченцо, где бы ты хотел это связать? Бок о бок? Объясните лучше, чтобы я мог решить ее для вас... Может быть, добавьте рисунок

Fabio 19.08.2024 15:58

это точно так же, как вы сделали. просто я устанавливал .translatesAutoresizingMaskIntoConstraints = false для сегментированного элемента управления, а затем объявлял новый. см. ответ ДонМага. Спасибо за ответ и помощь

Vincenzo 19.08.2024 16:14

На самом деле в вашем коде viewfinderShapeType.translatesAutoresizingMaskIntoConstraint‌​s = false это последняя строка настроек viewfinderShapeType

Vincenzo 19.08.2024 16:17
Ответ принят как подходящий

Вы создали сегментированный элемент управления как свойство вашего класса:

var viewfinderShapeType: UISegmentedControl = UISegmentedControl()

Причина, по которой ваш код помещает сегментированный элемент управления вверху слева, связана с этими двумя строками:

viewfinderShapeType.translatesAutoresizingMaskIntoConstraints = false
viewfinderShapeType = UISegmentedControl(items: ["RETTANGOLARE", "QUADRATA"])

Первая строка устанавливает .translatesAutoresizingMaskIntoConstraints = false для элемента управления, который является свойством вашего класса.

Вторая строка создает НОВЫЙ UISegmentedControl... для которого .translatesAutoresizingMaskIntoConstraints не установлено в false... и назначает этот новый элемент управления свойству класса.

Вы можете либо поменять порядок этих двух строк (создать новый экземпляр, а затем установить переводы...), либо

объявите свой контроль следующим образом:

var viewfinderShapeType: UISegmentedControl = {
    let v = UISegmentedControl(items: ["RETTANGOLARE", "QUADRATA"])
    return v
}()

и избавьтесь от этой строки:

//viewfinderShapeType = UISegmentedControl(items: ["RETTANGOLARE", "QUADRATA"])

вот и все! вот почему... можно ли с уверенностью предположить, что .translatesAutoresizingMaskIntoConstraints = false следует установить последним?

Vincenzo 19.08.2024 16:11

@Vincenzo — по умолчанию при создании объекта пользовательского интерфейса для него установлено значение true. Итак, его просто нужно установить на экземпляре/объекте после его создания.

DonMag 19.08.2024 16:58

конечно, я не мог видеть, что создаю новый сегментированный элемент управления вместо того, чтобы просто назначать элементы пустому элементу, созданному в свойствах ViewController. Это было нормально для метки, установленной в первую очередь, но не для сегментированного элемента управления, поскольку я фактически создавал новый и назначал его свойству ViewController, и ходил по кругу. еще раз спасибо

Vincenzo 19.08.2024 17:06

Другие вопросы по теме