iOS StackViews с пропорционально заполненными подпредставлениями и собственной шириной, которые не работают должным образом - PullRequest
0 голосов
/ 25 февраля 2019

После этой статьи я пытался заставить работать пропорциональный размер StackViews.

https://spin.atomicobject.com/2017/02/07/uistackviev-proportional-custom-uiviews/

Предполагалось, что, переопределяя intrinsicContentSize, мы можем указать новое число, и оно вычислитсоотношение размеров подвидов и соответственно изменяет размер представлений.

Когда я повторяю реализацию, я получаю странное поведение.Соотношение сохраняется, но последний элемент растягивается, чтобы занять оставшееся пространство вместо масштабирования элементов по всей ширине родительского вида (см. Изображение ниже).

Код:

class GuageSection: UIView {

    var width: Double = 1.0

    override var intrinsicContentSize: CGSize {
        return CGSize(width: width, height: 1.0)
    }
}

, который используется следующим образом

var guageWrapper = UIStackView()
guageWrapper.distribution = .fillProportionally

let guageSection = GuageSection()
guageSection.width = category.range // Currently Doubles ranging between 1.0 and 1.5
guageWrapper.addArrangedSubview(guageSection)

enter image description here

Я попытался поиграть со свойством translateAutoResizingMaskInConstraints и некоторыми другими вещами, но, похоже, ничего не изменилосьэто поведение.

Если бы кто-то видел это поведение до того, как хорошая точка в правильном направлении была бы очень признательна.

1 Ответ

0 голосов
/ 25 февраля 2019

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

Если .spacingis 0 (ноль), .fillProportionally, кажется, работает как задокументировано.Если .spacing равно не равно нулю , мы видим проблемы.

Итак, попробуйте это ... Инициализируйте представление стека с интервалом 0, затем:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    guageWrapper.spacing = 2
}

Конечно, вам понадобится ссылка на guageWrapper, поэтому создайте ее как переменную уровня класса.


Редактировать:

Я создал пример со стековым представлением как часть пользовательского UIView.

Используя массив "intrinsic widths" 1.0, 2.0, 1.0, 1.0, 1.5, вот результат:

enter image description here

enter image description here

Все выполняется с помощью кода (не требуется @IBOutlets), так что вы сможете запустить егодобавление нового контроллера представления и установка его пользовательского класса в GuageTestViewController:

//
//  GuageTestViewController.swift
//
//  Created by Don Mag on 2/28/19.
//

import UIKit

class GuageSection: UIView {

    let label: UILabel = {
        let v = UILabel()
        v.textAlignment = .center
        v.numberOfLines = 0
        v.font = UIFont.systemFont(ofSize: 14.0)
        v.translatesAutoresizingMaskIntoConstraints = false
        return v
    }()

    let colorView: UIView = {
        let v = UIView()
        v.translatesAutoresizingMaskIntoConstraints = false
        return v
    }()

    var width: Double = 1.0

    override var intrinsicContentSize: CGSize {
        return CGSize(width: width, height: 1.0)
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        commonInit()
    }

    func commonInit() -> Void {

        self.addSubview(colorView)
        self.addSubview(label)

        NSLayoutConstraint.activate([

            colorView.topAnchor.constraint(equalTo: self.topAnchor, constant: 0.0),
            colorView.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 0.0),
            colorView.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 0.0),

            colorView.heightAnchor.constraint(equalToConstant: 10.0),

            label.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0.0),
            label.centerXAnchor.constraint(equalTo: self.centerXAnchor, constant: 0.0),
            label.widthAnchor.constraint(equalTo: colorView.widthAnchor, constant: 0.0),

            label.topAnchor.constraint(equalTo: colorView.bottomAnchor, constant: 2.0),

            ])

    }

}

class GuageView: UIView {

    var pStack = UIStackView()

    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        commonInit()
    }

    func commonInit() -> Void {

        self.backgroundColor = UIColor(red: 41.0 / 255.0, green: 59.0 / 255.0, blue: 78.0 / 255.0, alpha: 1.0)

        pStack.translatesAutoresizingMaskIntoConstraints = false
        pStack.axis = .horizontal
        pStack.alignment = .fill
        pStack.distribution = .fillProportionally
        pStack.spacing = 0
        addSubview(pStack)

        let labels = [
            "Low", "Ideal", "Pre-High", "High", "Very High"
        ]

        let rgbVals = [
            [252, 191, 127],
            [ 79, 197, 140],
            [252, 191, 127],
            [249, 129, 131],
            [217,  92,  98],
            ]

        let widths = [
            1.0, 2.0, 1.0, 1.0, 1.5
        ]

        for i in 0..<labels.count {
            let v = GuageSection()
            v.translatesAutoresizingMaskIntoConstraints = false
            v.label.text = labels[i]
            v.width = widths[i]
            let rgb = rgbVals[i].compactMap { CGFloat($0) / 255.0 }
            v.colorView.backgroundColor = UIColor(red: rgb[0], green: rgb[1], blue: rgb[2], alpha: 1.0)
            v.label.textColor = v.colorView.backgroundColor
            pStack.addArrangedSubview(v)
        }

        // constrain the stack view 20-pts from top, leading and trailing, 8-pts from bottom
        NSLayoutConstraint.activate([

            pStack.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20.0),
            pStack.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -20.0),
            pStack.topAnchor.constraint(equalTo: topAnchor, constant: 20.0),
            pStack.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -8.0),

            // no height constraint ...
            // let the guageSection view height determine the stack view height
            //      guageSection has 10-pt tall view and multi-line capable label

            ])

    }

    override func layoutSubviews() {
        super.layoutSubviews()

        pStack.spacing = 2

    }
}

class GuageTestViewController: UIViewController {

    var gView = GuageView()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = UIColor(red: 31.0 / 255.0, green: 46.0 / 255.0, blue: 61.0 / 255.0, alpha: 1.0)

        view.addSubview(gView)
        gView.translatesAutoresizingMaskIntoConstraints = false

        // constrain the view to leading and trailing, and 40-pts from the top
        NSLayoutConstraint.activate([

            gView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 0.0),
            gView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: 0.0),
            gView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 40.0),

            // no height constraint ...
            // let the GuageView's content determine the height

            ])

    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...