I use the scroll on the screen. At the same time, when displaying the screen on SE there are no problems, when displaying on large screens, a large gap appears between two elements. How to change this problem? I change constraints, but don't have results
import UIKit
class PlayInfoViewController: UIViewController {
private let mainScrollView: UIScrollView = {
let sv = UIScrollView()
sv.backgroundColor = UIColor(named: "backgroundColor")
sv.translatesAutoresizingMaskIntoConstraints = false
return sv
}()
private let contentView: UIView = {
let v = UIView()
v.backgroundColor = UIColor(named: "backgroundColor")
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()
private let horisontalStackViews: [UIStackView] = {
var stackViews: [UIStackView] = []
let textsForMainLabel = [
"Draw a grid with three rows and three columns, creating nine squares in total.",
"Players take turns placing their marker (X or O) in an empty square. To make a move, a player selects a number corresponding to the square where they want to place their marker.",
"Player X starts by choosing a square (e.g., square 5). Player O follows by choosing an empty square (e.g., square 1). Continue alternating turns until the game ends.",
"The first player to align three of their markers horizontally, vertically, or diagonally wins. Examples of Winning Combinations: Horizontal: Squares 1, 2, 3 or 4, 5, 6 or 7, 8, 9 Vertical: Squares 1, 4, 7 or 2, 5, 8 or 3, 6, 9 Diagonal: Squares 1, 5, 9 or 3, 5, 7"
]
var number = 1
for text in textsForMainLabel {
let hStackView = UIStackView(
arrangedSubviews: [
RoundView(
frame: CGRect.zero,
numberOfPosition: number
),
RectangleView(
frame: CGRect.zero,
textForMainLabel: text
)
],
axis: .horizontal,
spacing: 20,
alignment: .top)
stackViews.append(hStackView)
number += 1
}
return stackViews
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor(named: "backgroundColor")
setupViews()
setConstraints()
}
private func setupViews() {
view.addSubview(mainScrollView)
mainScrollView.addSubview(contentView)
view.addSubview(horisontalStackViews[0])
view.addSubview(horisontalStackViews[1])
view.addSubview(horisontalStackViews[2])
view.addSubview(horisontalStackViews[3])
horisontalStackViews[0].translatesAutoresizingMaskIntoConstraints = false
horisontalStackViews[1].translatesAutoresizingMaskIntoConstraints = false
horisontalStackViews[2].translatesAutoresizingMaskIntoConstraints = false
horisontalStackViews[3].translatesAutoresizingMaskIntoConstraints = false
let hConst = contentView.heightAnchor.constraint(equalTo: mainScrollView.heightAnchor)
hConst.isActive = true
hConst.priority = UILayoutPriority(500)
}
}
extension PlayInfoViewController {
private func setConstraints() {
NSLayoutConstraint.activate([
mainScrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
mainScrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 42),
mainScrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
mainScrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
contentView.leadingAnchor.constraint(equalTo: mainScrollView.leadingAnchor),
contentView.topAnchor.constraint(equalTo: mainScrollView.topAnchor),
contentView.trailingAnchor.constraint(equalTo: mainScrollView.trailingAnchor),
contentView.bottomAnchor.constraint(equalTo: mainScrollView.bottomAnchor),
contentView.widthAnchor.constraint(equalTo: mainScrollView.widthAnchor),
// contentView.heightAnchor.constraint(equalTo: mainScrollView.heightAnchor, multiplier: 2),
horisontalStackViews[0].leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 21),
horisontalStackViews[0].topAnchor.constraint(equalTo: contentView.topAnchor),
horisontalStackViews[0].trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -21),
// horisontalStackViews[0].widthAnchor.constraint(equalTo: contentView.widthAnchor),
// horisontalStackViews[0].heightAnchor.constraint(equalToConstant: 75)
horisontalStackViews[1].leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 21),
horisontalStackViews[1].topAnchor.constraint(equalTo: horisontalStackViews[0].bottomAnchor, constant: 10),
horisontalStackViews[1].trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -21),
// horisontalStackViews[1].widthAnchor.constraint(equalTo: contentView.widthAnchor),
// horisontalStackViews[1].heightAnchor.constraint(equalToConstant: 192)
horisontalStackViews[2].leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 21),
horisontalStackViews[2].topAnchor.constraint(equalTo: horisontalStackViews[1].bottomAnchor, constant: 10),
horisontalStackViews[2].trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -21),
// horisontalStackViews[2].widthAnchor.constraint(equalTo: contentView.widthAnchor),
// horisontalStackViews[2].heightAnchor.constraint(equalToConstant: 171)
horisontalStackViews[3].leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 21),
horisontalStackViews[3].topAnchor.constraint(equalTo: horisontalStackViews[2].bottomAnchor, constant: 10),
horisontalStackViews[3].trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -21),
horisontalStackViews[3].bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
// horisontalStackViews[3].widthAnchor.constraint(equalTo: contentView.widthAnchor),
// horisontalStackViews[3].heightAnchor.constraint(equalToConstant: 255)
])
}
}
I change constraint and hConst. Don't have result
horisontalStackViews[3].bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
let hConst = contentView.heightAnchor.constraint(equalTo: mainScrollView.heightAnchor)
hConst.isActive = true
hConst.priority = UILayoutPriority(500)
class RoundView: UIView {
var numberOfPosition: Int
lazy var numberLabel: UILabel = {
let label = UILabel()
label.text = "Some text"
label.font = UIFont.systemFont(ofSize: 20, weight: .regular)
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
required init(frame: CGRect, numberOfPosition: Int) {
self.numberOfPosition = numberOfPosition
super.init(frame: frame)
layer.cornerRadius = 22.5
translatesAutoresizingMaskIntoConstraints = false
numberLabel.text = String(numberOfPosition)
setupView()
setConstraints()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupView() {
backgroundColor = #colorLiteral(red: 0.8375778794, green: 0.7538908124, blue: 0.96424371, alpha: 1)
addSubview(numberLabel)
}
}
extension RoundView {
private func setConstraints() {
NSLayoutConstraint.activate([
numberLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 18),
numberLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -18),
numberLabel.topAnchor.constraint(equalTo: topAnchor, constant: 12),
numberLabel.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -12)
])
}
}
class RectangleView: UIView {
var textForMainLabel: String
lazy var mainLabel: UILabel = {
let label = UILabel()
label.text = "Some text"
label.font = UIFont.systemFont(ofSize: 18, weight: .regular)
label.numberOfLines = 0
label.minimumScaleFactor = 0.5
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
required init(frame: CGRect, textForMainLabel: String) {
self.textForMainLabel = textForMainLabel
super.init(frame: frame)
layer.cornerRadius = 30
translatesAutoresizingMaskIntoConstraints = false
mainLabel.text = textForMainLabel
setupView()
setConstraints()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupView() {
backgroundColor = #colorLiteral(red: 0.8718322515, green: 0.8867664933, blue: 0.9465543628, alpha: 1)
addSubview(mainLabel)
}
}
extension RectangleView {
private func setConstraints() {
NSLayoutConstraint.activate([
mainLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 24),
mainLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -24),
mainLabel.topAnchor.constraint(equalTo: topAnchor, constant: 12),
mainLabel.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -12)
])
}
}
It's Good enter image description here
This is a wrong
Instead of constraining your horizontal stack view "rows," let's add them to a Vertical stack view.
To avoid the "gap" between the 1st and 2nd "row" on the larger screens, we do not set a height constraint on either the vertical stack view or the "content" view. On small screens - such as the SE - we get scrolling. On larger screens, we get a bit of space at the bottom, while keeping the "row spacing" consistent.
Looks like this:
RoundView
class RoundView: UIView {
var numberOfPosition: Int
lazy var numberLabel: UILabel = {
let label = UILabel()
label.textAlignment = .center
label.text = "0"
label.font = UIFont.systemFont(ofSize: 20, weight: .regular)
label.translatesAutoresizingMaskIntoConstraints = false
// make sure the label frame cannot compress
label.setContentCompressionResistancePriority(.required, for: .horizontal)
label.setContentCompressionResistancePriority(.required, for: .vertical)
return label
}()
required init(frame: CGRect, numberOfPosition: Int) {
self.numberOfPosition = numberOfPosition
super.init(frame: frame)
translatesAutoresizingMaskIntoConstraints = false
numberLabel.text = String(numberOfPosition)
setupView()
setConstraints()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupView() {
backgroundColor = #colorLiteral(red: 0.8375778794, green: 0.7538908124, blue: 0.96424371, alpha: 1)
addSubview(numberLabel)
}
override func layoutSubviews() {
super.layoutSubviews()
// set the cornerRadius here to make sure it matches the view size
layer.cornerRadius = min(bounds.height, bounds.width) * 0.5
}
}
extension RoundView {
private func setConstraints() {
NSLayoutConstraint.activate([
numberLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 18),
numberLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -18),
numberLabel.topAnchor.constraint(equalTo: topAnchor, constant: 12),
numberLabel.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -12),
// let's keep this view at a 1:1 aspect ratio
self.widthAnchor.constraint(equalTo: self.heightAnchor),
])
}
}
RectangleView
class RectangleView: UIView {
var textForMainLabel: String
lazy var mainLabel: UILabel = {
let label = UILabel()
label.text = "Some text"
label.font = UIFont.systemFont(ofSize: 18, weight: .regular)
label.numberOfLines = 0
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
required init(frame: CGRect, textForMainLabel: String) {
self.textForMainLabel = textForMainLabel
super.init(frame: frame)
layer.cornerRadius = 30
translatesAutoresizingMaskIntoConstraints = false
mainLabel.text = textForMainLabel
setupView()
setConstraints()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupView() {
backgroundColor = #colorLiteral(red: 0.8718322515, green: 0.8867664933, blue: 0.9465543628, alpha: 1)
addSubview(mainLabel)
}
}
extension RectangleView {
private func setConstraints() {
NSLayoutConstraint.activate([
mainLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 24),
mainLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -24),
mainLabel.topAnchor.constraint(equalTo: topAnchor, constant: 12),
mainLabel.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -12)
])
}
}
PlayInfoViewController
class PlayInfoViewController: UIViewController {
private let mainScrollView: UIScrollView = {
let sv = UIScrollView()
sv.backgroundColor = UIColor(named: "backgroundColor")
sv.translatesAutoresizingMaskIntoConstraints = false
return sv
}()
private let contentView: UIView = {
let v = UIView()
v.backgroundColor = UIColor(named: "backgroundColor")
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()
// vertical stack view to hold the "rows" of horizontal stack views
private let vertStackView: UIStackView = {
let sv = UIStackView()
sv.axis = .vertical
sv.spacing = 10
sv.translatesAutoresizingMaskIntoConstraints = false
return sv
}()
private let horisontalStackViews: [UIStackView] = {
var stackViews: [UIStackView] = []
let textsForMainLabel = [
"Draw a grid with three rows and three columns, creating nine squares in total.",
"Players take turns placing their marker (X or O) in an empty square. To make a move, a player selects a number corresponding to the square where they want to place their marker.",
"Player X starts by choosing a square (e.g., square 5). Player O follows by choosing an empty square (e.g., square 1). Continue alternating turns until the game ends.",
"The first player to align three of their markers horizontally, vertically, or diagonally wins. Examples of Winning Combinations: Horizontal: Squares 1, 2, 3 or 4, 5, 6 or 7, 8, 9 Vertical: Squares 1, 4, 7 or 2, 5, 8 or 3, 6, 9 Diagonal: Squares 1, 5, 9 or 3, 5, 7"
]
var number = 1
for text in textsForMainLabel {
let hStackView = UIStackView()
hStackView.axis = .horizontal
hStackView.spacing = 20
hStackView.alignment = .top
let roundView = RoundView (
frame: CGRect.zero,
numberOfPosition: number
)
let rectView = RectangleView (
frame: CGRect.zero,
textForMainLabel: text
)
hStackView.addArrangedSubview(roundView)
hStackView.addArrangedSubview(rectView)
stackViews.append(hStackView)
number += 1
}
return stackViews
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor(named: "backgroundColor")
setupViews()
setConstraints()
}
private func setupViews() {
view.addSubview(mainScrollView)
mainScrollView.addSubview(contentView)
contentView.addSubview(vertStackView)
for v in horisontalStackViews {
vertStackView.addArrangedSubview(v)
}
}
}
extension PlayInfoViewController {
private func setConstraints() {
let g = view.safeAreaLayoutGuide
let cg = mainScrollView.contentLayoutGuide
let fg = mainScrollView.frameLayoutGuide
NSLayoutConstraint.activate([
mainScrollView.leadingAnchor.constraint(equalTo: g.leadingAnchor),
mainScrollView.topAnchor.constraint(equalTo: g.topAnchor, constant: 42),
mainScrollView.trailingAnchor.constraint(equalTo: g.trailingAnchor),
mainScrollView.bottomAnchor.constraint(equalTo: g.bottomAnchor),
contentView.leadingAnchor.constraint(equalTo: cg.leadingAnchor),
contentView.topAnchor.constraint(equalTo: cg.topAnchor),
contentView.trailingAnchor.constraint(equalTo: cg.trailingAnchor),
contentView.bottomAnchor.constraint(equalTo: cg.bottomAnchor),
contentView.widthAnchor.constraint(equalTo: fg.widthAnchor),
// do NOT set contentView.heightAnchor
vertStackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 21),
vertStackView.topAnchor.constraint(equalTo: contentView.topAnchor),
vertStackView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -21),
vertStackView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
])
}
}