К вашему сведению, вы должны стараться придерживаться одного вопроса за раз - или, по крайней мере, только связанных вопросов (другими словами, № 4 должен быть другим вопросом).
Я буду обращаться с 1 по 3.
Сначала у вас есть комментарий в вашем коде:
//constrain width of stack view to width of self.view, NOT scroll view
Что не так. Ваша ширина стека должна быть ограничена шириной прокрутки. В противном случае, если ваше представление прокрутки не растянется по всему экрану, оно будет прокручиваться горизонтально.
В вашем случае вы (кажется,) добавили представление прокрутки с 5-точечным начальным и конечным шагом:
self.scrollView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 5).isActive = true;
self.scrollView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: 5).isActive = true;
Однако ваша константа trailingAnchor должна быть -5
.
Как только это будет исправлено ...
1) Измените ваш "основной" stackView .alignment
тоже .fill
вместо .leading
и убедитесь, что у вашего изображения .contentMode = .scaleAspectFit
. Это будет центрировать «дом» по горизонтали.
2) Вы можете ограничить высоту «внутренних стековых видов» относительно высоты метки. Просто убедитесь, что вы добавили это ограничение после , добавив метку в качестве организованного просмотра
3) Для вертикального центрирования значка -> метка, установите .alignment = .center
для горизонтальных представлений стека.
Вот немного измененная версия отправленного вами кода:
class TestViewController: UIViewController {
var aboutText:[String] = []
var fbLinks:[String] = []
let scrollView = UIScrollView()
let stackView = UIStackView()
override func viewDidLoad() {
super.viewDidLoad()
//Add and setup scroll view
self.view.addSubview(self.scrollView)
self.scrollView.translatesAutoresizingMaskIntoConstraints = false;
//Constrain scroll view
self.scrollView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 5).isActive = true;
self.scrollView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 30).isActive = true;
// trailing constant should be negative
self.scrollView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -5).isActive = true;
self.scrollView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0).isActive = true;
self.scrollView.addSubview(self.stackView)
self.stackView.translatesAutoresizingMaskIntoConstraints = false
self.stackView.axis = .vertical
// change to .fill
self.stackView.alignment = UIStackView.Alignment.leading
self.stackView.alignment = .fill
self.stackView.spacing = 10;
//constrain stack view to scroll view
self.stackView.leadingAnchor.constraint(equalTo: self.scrollView.leadingAnchor).isActive = true;
self.stackView.topAnchor.constraint(equalTo: self.scrollView.topAnchor).isActive = true;
self.stackView.trailingAnchor.constraint(equalTo: self.scrollView.trailingAnchor).isActive = true;
self.stackView.bottomAnchor.constraint(equalTo: self.scrollView.bottomAnchor).isActive = true;
//constrain width of stack view to width of self.view, NOT scroll view
//self.stackView.widthAnchor.constraint(equalTo: self.view.widthAnchor).isActive = true;
// you SHOULD constrain the stackView width to the width of the scrollView (assuming you do not want horizontal scrolling)
self.stackView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true;
//Text Label
aboutText.append("Lorem ipsum dolor sit amet, consectetur adipiscing elit.")
aboutText.append("Maecenas sed pulvinar est. Integer mattis mollis eleifend. Integer suscipit arcu sit amet erat rhoncus malesuada. Nam feugiat augue id leo maximus dignissim id sed libero. Proin dapibus metus vel nisl ultrices, quis laoreet metus malesuada. Lorem ipsum dolor sit amet, consectetur adipiscing elit. ")
aboutText.append(" penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed sit amet dui consectetur, vulputate felis sed, volutpat dui. Quisque eu ex eu nulla facilisis aliquet. Vestibulum vitae lacus non sapien posuere commodo et eget arcu. Sed quis eros condimentum, pharetra ligula non, gravida ex. Cras luctus com")
aboutText.append(" Praesent luctus nulla eget condimentum volutpat. Nunc metus odio, commodo sit amet placerat non, cursus posuere sem. Mauris lorem felis, elementum vel purus")
fbLinks.append("Some text")
fbLinks.append("Some other text but longer")
fbLinks.append("Some other text but way longer then the previous was")
fbLinks.append("text again what a surprise")
fbLinks.append("guess what this is a text too")
let image = UIImage(systemName: "house")
let imageView = UIImageView(image: image!)
imageView.contentMode = .scaleAspectFit
imageView.heightAnchor.constraint(equalToConstant: 60).isActive = true
stackView.addArrangedSubview(imageView)
for text in aboutText
{
stackView.addArrangedSubview(generateText(text:text))
}
stackView.addArrangedSubview(generateStackedItem(imageName:"bell",text: "contact_us"))
stackView.addArrangedSubview(generateStackedItem(imageName:"bolt",text: "rate_us_ios"))
for link in fbLinks
{
let sw:UIStackView = generateStackedItem(imageName:"bolt",text: link)
stackView.addArrangedSubview(sw)
// next two lines are not needed
//sw.leadingAnchor.constraint(equalTo: self.stackView.leadingAnchor).isActive = true;
//sw.trailingAnchor.constraint(equalTo: self.stackView.trailingAnchor).isActive = true;
}
}
func generateText(text:String)->UILabel
{
let textLabel = UILabel()
// no need to set widthAnchor
//textLabel.widthAnchor.constraint(equalToConstant: self.view.frame.width).isActive = true
textLabel.text = NSLocalizedString(text, comment: "")
textLabel.textAlignment = .left
textLabel.numberOfLines = 0
textLabel.lineBreakMode = .byWordWrapping
return textLabel
}
func generateStackedItem(imageName:String,text:String)->UIStackView
{
let stackView = UIStackView()
stackView.axis = NSLayoutConstraint.Axis.horizontal
stackView.distribution = .fill
// horizontal stack view alignment defines the Vertical alignment
//stackView.alignment = UIStackView.Alignment.leading
// so set it to .center to get vertical centering
stackView.alignment = .center
stackView.spacing = 5.0
let image = UIImage(systemName: imageName)
let imageView = UIImageView(image: image!)
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.heightAnchor.constraint(equalToConstant: 20).isActive = true
imageView.widthAnchor.constraint(equalToConstant: 20).isActive = true
let label = generateText(text: text)
stackView.addArrangedSubview(imageView)
stackView.addArrangedSubview(label)
stackView.translatesAutoresizingMaskIntoConstraints = false
// constrain stackView height to label height + constant
//stackView.heightAnchor.constraint(equalToConstant: 50).isActive = true
stackView.heightAnchor.constraint(equalTo: label.heightAnchor, constant: 16).isActive = true
return stackView
}
}
Результат: