Перекрывающиеся представления в UIStackView

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

введите описание изображения здесь

Пробовал играть с индексом Z, но это не помогло, поскольку слои как-то не плоские, как вы можете видеть в следующей иерархии представлений:

введите описание изображения здесь

Любая идея или предложение, как это сделать?

Спасибо.

Ответ 1

Документация для класса UIStackView сообщает, что:

Порядок массива subviews определяет Z-порядок подсмотров. Если представления перекрываются, подзоны с более высоким индексом появляются подзоны с более низким индексом.

что и есть то, что я испытал в вопросе. Чтобы закончить мой конкретный случай, я сделал трюк, чтобы изменить семантику представления как RTL, как можно видеть здесь:

введите описание изображения здесь

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

P.S. Это как-то взломать, поэтому любые идеи о том, как изменить порядок Z-порядка подсмотров по-другому, будут наиболее желанными!

Ответ 2

Это решение Swift изменяет порядок подпредставлений стекового представления с помощью метода sendSubviewToBack(_:) (документы здесь):

@IBOutlet weak var stackView: UIStackView!

for view in stackView.arrangedSubviews {
    stackView.sendSubviewToBack(view)
}

По мере продвижения через упорядоченные представления стековых представлений (снизу вверх) более поздние (то есть более высокие) представления сдвигаются к низу, меняя порядок в обратном порядке :-)

Ответ 3

Так как iOS 9.0 позволяет установить z-порядок и расположение представлений представления стека независимо. Используйте новое свойство arrangedSubviews, чтобы указать расположение подпроектов вдоль оси представления стека. И используйте свойство subviews, чтобы указать subviews z-order на основе их индекса в массиве.

Представление стека гарантирует, что его свойство arrangedSubviews всегда является подмножеством его свойства subviews.

Документация для builtSubviews

Ответ 4

Другая идея может заключаться в том, чтобы установить фоновый цвет субвью (7 ячеек) по умолчанию (полностью прозрачный). И установите только фон самого представления стека в белый.

У меня есть аналогичная проблема, но там, где у каждого подзаголовка должен быть определенный фон. И в моем случае ваш взлом может помочь... 😉 Спасибо за это!

Ответ 5

Ниже приведено простое расширение на UIStackView, чтобы отменить z-индекс подкадров UIStackView и, возможно, потребовать компоновку:

extension UIStackView {

  func reverseSubviewsZIndex(setNeedsLayout: Bool = true) {
    let stackedViews = self.arrangedSubviews

    stackedViews.forEach {
      self.removeArrangedSubview($0)
      $0.removeFromSuperview()
    }

    stackedViews.reversed().forEach(addSubview(_:))
    stackedViews.forEach(addArrangedSubview(_:))

    if setNeedsLayout {
      stackedViews.forEach { $0.setNeedsLayout() }
    }
  }

}

Ответ 6

Программно, когда вы добавляете подпредставление, добавляйте ограничения на высоту и ширину. В конце вызова StackView setNeedsLayout. Он рассчитает и попытается отрегулировать виды с интервалом

После различных попыток я могу сделать это горизонтально

 stackView.leadingAnchor.constraint(equalTo: stackScrollView.leadingAnchor).isActive = true
 stackView.trailingAnchor.constraint(equalTo: stackScrollView.trailingAnchor).isActive = true
 stackView.bottomAnchor.constraint(equalTo: stackScrollView.bottomAnchor).isActive = true
 stackView.heightAnchor.constraint(equalTo: stackScrollView.heightAnchor).isActive = true

 stackView.distribution = .equalSpacing
 stackView.spacing = 5
 stackView.axis = .horizontal
 stackView.alignment = .fill


 for i in 0 ..< images.count {
     let photoView = UIButton.init(frame: CGRect(x: 0, y: 0, width: 85, height: 85))

     // set button image
     photoView.translatesAutoresizingMaskIntoConstraints = false
     photoView.heightAnchor.constraint(equalToConstant: photoView.frame.height).isActive = true
     photoView.widthAnchor.constraint(equalToConstant: photoView.frame.width).isActive = true

     stackView.addArrangedSubview(photoView)
 }

 stackView.setNeedsLayout()