Swift - Comment définir une vue personnalisée par longueur de texte
Voici mon code,
func bannerNotification(text: String){
let container = UIView()
let image = UIImageView()
let label = UILabel()
container.frame = CGRect(x: 0, y:0, width: self.view.frame.size.width, height: 100)
container.backgroundColor = .blue
image.frame = CGRect(x: 15, y: 50, width: 30, height: 30)
image.image = UIImage(named: "passport")
label.frame = CGRect(x: image.bounds.maxX + 35, y: 50, width: container.frame.size.width - 100, height: 50)
label.backgroundColor = .red
label.numberOfLines = 0
label.font = UIFont(name:"Helvetica Neue", size: 15)
label.text = text
container.addSubview(image)
container.addSubview(label)
self.view.addSubview(container)
}
Selon ce code, le conteneur et l'image arrivent à la bonne position, mais si je passe un petit texte pour que mon texte ne soit pas en ligne avec Image, cela signifie que la position du haut de l'image et la position du haut du texte doivent être identiques .
Si je passe un gros texte, le bas du conteneur et le bas de l'étiquette doivent être identiques et tout le texte ne doit pas être tronqué et l' image et l'étiquette doivent être en ligne à partir du haut .


Réponses
Vous voulez vraiment utiliser la mise en page automatique pour cela, d'autant plus que vous utilisez une étiquette multiligne - ce qui signifie qu'elle variera en hauteur.
Voici un exemple - lisez les commentaires pour comprendre les contraintes de mise en page automatique:
class KingViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
bannerNotification(text: "Banner Test")
//bannerNotification(text: "Banner Test with lots of text to wrap onto multiple lines. Of the many advantages with using auto-layout, notice that the banner will stretch when you rotate the device.")
}
func bannerNotification(text: String){
let container = UIView()
let image = UIImageView()
let label = UILabel()
container.addSubview(image)
container.addSubview(label)
self.view.addSubview(container)
[image, label, container].forEach {
$0.translatesAutoresizingMaskIntoConstraints = false
}
container.backgroundColor = UIColor(red: 0.0, green: 0.5, blue: 1.0, alpha: 1.0)
//image.image = UIImage(named: "passport")
image.image = UIImage(named: "swiftRed")
label.backgroundColor = .yellow
label.numberOfLines = 0
label.font = UIFont(name:"Helvetica Neue", size: 15)
label.text = text
// respect the safe area
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
// constrain container Top / Leading / Trailing
container.topAnchor.constraint(equalTo: view.topAnchor),
container.leadingAnchor.constraint(equalTo: view.leadingAnchor),
container.trailingAnchor.constraint(equalTo: view.trailingAnchor),
// we'll use the label height to determine the container height
// image view Top = 8 / Leading = 15
image.topAnchor.constraint(equalTo: g.topAnchor, constant: 8.0),
image.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 15.0),
// image view width = 30 / height == width (1:1 ratio)
image.widthAnchor.constraint(equalToConstant: 30.0),
image.heightAnchor.constraint(equalTo: image.widthAnchor),
// label Top aligned to Top of image view
label.topAnchor.constraint(equalTo: image.topAnchor),
// label Leading == image view Trailing + 20
label.leadingAnchor.constraint(equalTo: image.trailingAnchor, constant: 20.0),
// label Trailing = container Trailing - 15
label.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -15.0),
// container bottom should be
// At Least 8-pts below the image view bottom
// AND
// At Least 8-pts below the label bottom
container.bottomAnchor.constraint(greaterThanOrEqualTo: image.bottomAnchor, constant: 8.0),
container.bottomAnchor.constraint(greaterThanOrEqualTo: label.bottomAnchor, constant: 8.0),
])
}
}
Résultat, avec un texte court:

Résultat avec texte long:

Notez qu'il s'ajuste automatiquement lorsque la taille change - comme avec la rotation de l'appareil:
