web-dev-qa-db-fra.com

Chevauchement de vues dans UIStackView

J'ai une vue de pile horizontale que j'ai ajoutée à des sous-vues arrangées (7 cellules). Chacune des cellules de la pile a un badge circulaire qui dépasse les limites de la vue (contrainte négative). Lors de l'exécution, comme vous pouvez le voir ci-dessous, chaque cellule se trouve au-dessus du badge de la cellule précédente. Je voudrais changer l'ordre pour que les badges soient entièrement visibles.

 enter image description here

J'ai essayé de jouer avec l'index Z mais cela n'a pas aidé, car les couches ne sont pas plates comme vous pouvez le voir dans la hiérarchie suivante:

 enter image description here

Une idée ou une suggestion comment le faire?

Merci.

12
yossile

La documentation de la classe UIStackView indique que: 

L'ordre du tableau des sous-vues définit l'ordre Z des sous-vues. Si les vues se chevauchent, les sous-vues d'indice inférieur apparaissent derrière les sous-vues d'index supérieur.

ce qui est exactement ce que j'ai expérimenté dans la question. Pour résoudre mon cas spécifique, j'ai eu l’astuce de changer la sémantique de la vue en RTL comme on peut le voir ici:

 enter image description here

Cela ne couvre pas le cas générique, car un périphérique a peut-être été défini comme langage RTL dans ses paramètres globaux. Pour le cas générique, je devrais vérifier la sémantique de l'interface et forcer une direction opposée à celle de la pile.

P.S. C'est un peu un bidouillage, toute idée sur la façon de réordonner l'ordre Z des sous-vues d'une manière différente sera la bienvenue!

11
yossile

Cette solution Swift inverse l'ordre de la sous-vue de la pile à l'aide de la méthode UIView sendSubviewToBack(_:) ( docs here ):

@IBOutlet weak var stackView: UIStackView!

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

Au fur et à mesure que nous avançons dans les vues organisées de la vue de pile (de bas en haut), les vues les plus récentes (c'est-à-dire les plus hautes) sont poussées vers le bas, inversant ainsi l'ordre :-)

7
future-adam

Depuis iOS 9.0, il est possible de définir indépendamment l'ordre z et la disposition des sous-vues de la vue de pile. Utilisez la nouvelle propriété arrangedSubviews pour spécifier la disposition des sous-vues le long de l’axe de la vue de pile. Et utilisez la propriété subviews pour spécifier l'ordre z des sous-vues en fonction de leur index dans le tableau.

La vue de pile garantit que sa propriété arrangedSubviews est toujours un sous-ensemble de sa propriété subviews.

Documentation pour les vues organisées

3
IvanRublev

Vous trouverez ci-dessous une simple extension sur UIStackView pour inverser l'index z des sous-vues de UIStackView et nécessiter éventuellement une présentation:

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

}
1
sean woodward

Une autre idée pourrait être de définir la couleur de fond des sous-vues (7 cellules) sur la valeur par défaut ( entièrement transparent ). Et définissez uniquement l'arrière-plan de la vue stack sur white .

J'ai un problème similaire mais où chaque sous-vue doit avoir un arrière-plan spécifique. Et dans mon cas, votre bidouille pourrait aider… ???? Merci pour cela!

1
MonsieurDart

Par programme, lorsque vous ajoutez la sous-vue, ajoutez des contraintes de hauteur et de largeur constantes. À la fin, appelez setNeedsLayout de StackView. Il va calculer et essayer d'ajuster les vues avec l'espacement

Après diverses tentatives, je suis capable de le faire horizontalement

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

 } 
0
user1039695