Загрузите представление из Xib и измените размеры подвидов фрейма после автоматического макета - PullRequest
0 голосов
/ 12 мая 2018

Я исследовал 2 дня, но не нашел решения этой проблемы:

Я загружаю представление из Xib и применяю к нему автоматическую компоновку. Вид справа и автоматическое расположение работает нормально. Но когда я пытаюсь получить кадр подпредставлений после автоматического макета, он не работает. Мне нужна рамка подпредставления, чтобы сделать redView круговой.

Я загружаю представление из Xib, когда оно инициализируется, и добавляю его в качестве подпредставления с автоматическим макетом (я уже пробовал много разных вещей и проверяю, что распечатки, которые я делаю, находятся в layoutSubviews.

class ReusableView: UIView {

    @IBOutlet weak var redView: UIView!

    var mainView: UIView?
    // MARK: - Initializers.
    override init(frame: CGRect) {
        super.init(frame: frame)
        loadXIB()
    }

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

    override func layoutSubviews() {
        super.layoutSubviews()
        print ("Self subviews \(self.subviews)")
        print ("MainView frame \(mainView?.frame)")
        print ("Red View frame \(redView?.frame)")
    }

    func loadXIB() {
        guard let view = loadView(String(describing: type(of: self))) else { return }
        print ("View loaded from nib \(view.frame)")
        view.translatesAutoresizingMaskIntoConstraints = false
        view.subviews.forEach {
            $0.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        }
        addSubview(view)
        NSLayoutConstraint.activate([
            view.topAnchor.constraint(equalTo: self.topAnchor),
            view.leadingAnchor.constraint(equalTo: self.leadingAnchor),
            view.trailingAnchor.constraint(equalTo: self.trailingAnchor),
            view.bottomAnchor.constraint(equalTo: self.bottomAnchor),
            ])
        mainView = view
    }

    func loadView(_ nibName: String) -> UIView? {
        if nibName.isEmpty {
            return nil
        }
        let bundle = Bundle(for: type(of: self) as AnyClass)
        let nib = UINib(nibName: nibName, bundle: bundle)
        if let view = nib.instantiate(withOwner: self, options: nil).first as? UIView {
            return view
        }
        return nil
    }
}

Результат отпечатков:

View loaded from nib (0.0, 0.0, 375.0, 667.0)
Self subviews [<UIView: 0x7ff232216880; frame = (0 0; 150 150); autoresize = W+H; layer = <CALayer: 0x60800022f4e0>>]
MainView frame Optional((0.0, 0.0, 150.0, 150.0))
Red View frame Optional((0.0, 20.0, 375.0, 647.0))
MainView subviews Optional([<UIView: 0x7ff232216690; frame = (0 20; 375 647); autoresize = W+H; layer = <CALayer: 0x60800022f520>>])

Как мы видим, основной вид был изменен, но не его подпредставление. (Затем, когда вид распечатывается, он работает совершенно нормально, я делал это с более сложными видами, но никогда раньше не сталкивался с проблемой получения фрейма внутри de UIView.)

1 Ответ

0 голосов
/ 12 мая 2018

Я нашел этот обходной путь, но я все еще хочу знать, есть ли более элегантный способ.

После загрузки представления я сохраняю исходный размер xib в переменной с именем XibSize

    guard let view = loadView(String(describing: type(of: self))) else { return }
    xibSize = view.frame.size

И затем я создал метод, который принимает в качестве параметра размер, который вы хотите пересчитать после применения макета после: (Так как у нас есть оригинальный размер ( XibSize)) и пересчитанный размер mainView ), мы можем рассчитать размер после применения автоматического макета подпредставлений.)

func getSizeAfterAutoLayout(sizeToRecalculate: CGSize) -> CGSize? {
    guard let mainView = mainView, let xibFrame = xibFrame else { return nil }
    let width = sizeToRecalculate.width * mainView.frame.size.width / xibSize.width
    let height = sizeToRecalculate.height * mainView.frame.size.height / xibSize.height
    return CGSize(width: width, height: height)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...