Swift: UIStackView 重叠所有视图而不是垂直堆叠它们
Swift: UIStackView Overlapping all Views instead of Stacking them Vertically
我正在尝试为我的应用程序创建一个统计页面,其中包含根据用户拥有的数据类型动态创建的各种图表。为此,我根据本教程堆叠多个 ViewController:https://swiftwithmajid.com/2019/02/27/building-complex-screens-with-child-viewcontrollers/
我 运行 遇到一个问题,其中 ViewController 的视图作为 arrangedSubView 添加到主 StackView,而不是垂直堆叠视图并允许我滚动浏览它们全部,它只是在 z 方向上将它们堆叠在一起。
这是堆栈ViewController代码:
class StackViewController: UIViewController {
private let scrollView = UIScrollView()
private let stackView = UIStackView()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(scrollView)
scrollView.addSubview(stackView)
setupConstraints()
stackView.axis = .vertical
}
private func setupConstraints() {
scrollView.translatesAutoresizingMaskIntoConstraints = false
stackView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
scrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
scrollView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
stackView.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor),
stackView.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor),
stackView.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor),
stackView.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor),
stackView.widthAnchor.constraint(equalTo: scrollView.frameLayoutGuide.widthAnchor)
])
}
}
extension StackViewController {
func add(_ child: UIViewController) {
addChild(child)
stackView.addArrangedSubview(child.view)
print(child.view!)
child.didMove(toParent: self)
}
func remove(_ child: UIViewController) {
guard child.parent != nil else {
return
}
child.willMove(toParent: nil)
stackView.removeArrangedSubview(child.view)
child.view.removeFromSuperview()
child.removeFromParent()
}
}
这里是我创建每个视图控制器并将其添加到堆栈的地方ViewController。
现在,我 运行 循环并一遍又一遍地添加单个视图控制器的副本:
class PrototypeViewController: StackViewController {
override func viewDidLoad() {
super.viewDidLoad()
for _ in 0...10 {
setupUI()
}
}
private func setupUI() {
let storyboard = UIStoryboard(name: "ConsistencyGraph", bundle: .main)
let consistencyGraphVC = storyboard.instantiateViewController(identifier: "ConsistencyGraphVC") as! ConsistencyGraphVC
add(consistencyGraphVC)
consistencyGraphVC.setupUI(name: "sessionName", consistencyPercentage: 30, ballsHit: 10)
}
}
这是视图控制器代码:
class ConsistencyGraphVC: UIViewController {
@IBOutlet weak var mainView: UIView!
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var ballsHitLabel: UILabel!
@IBOutlet weak var pieChartView: PieChartView!
override func viewDidLoad() {
super.viewDidLoad()
}
open func setupUI(name: String, consistencyPercentage: Double, ballsHit: Int) {
displayName(name:name)
drawPieChart(consistencyPercentage: consistencyPercentage)
displayBallsHit(ballsHit: ballsHit)
}
private func displayName(name: String) {
let prefix = "Consistency: "
let title = prefix + name
titleLabel.text = title
}
private func displayBallsHit(ballsHit: Int) {
ballsHitLabel.text = String(ballsHit)
}
private func drawPieChart(consistencyPercentage: Double) {
let maxPercent:Double = 100
let remainingPercent = maxPercent - consistencyPercentage
let dataEntry = [PieChartDataEntry(value: consistencyPercentage, data: String(consistencyPercentage)), PieChartDataEntry(value: remainingPercent, data: nil)]
let dataSet = PieChartDataSet(entries: dataEntry)
let chartData = PieChartData(dataSet: dataSet)
let color1 = randomColor()
let color2 = randomColor()
dataSet.colors = [color1, color2]
pieChartView.data = chartData
}
private func randomColor() -> UIColor {
let red = Double(arc4random_uniform(256))
let green = Double(arc4random_uniform(256))
let blue = Double(arc4random_uniform(256))
let color = UIColor(red: CGFloat(red/255), green: CGFloat(green/255), blue: CGFloat(blue/255), alpha: 1)
return color
}
}
起初,我以为是因为 View Controller 的大小可能不明确。然后我硬编码了每个视图控制器的宽度和高度,但仍然没有运气。
非常感谢任何帮助!我不知道这怎么可能。
提前致谢!
您忘记了 ScrollView 中 StackView 的一些必需约束。
你只有trailing, top, and bottom
还不够
- 正确的是:
stackView.leadingAnchor
stackView.trailingAnchor
stackView.topAnchor
stackView.bottomAnchor
stackView.widthAnchor
我终于找到了解决办法!
我需要补充:
child.view.heightAnchor.constraint(equalToConstant: child.view.frame.size.height).isActive = true
到这里的 StackViewController:
func add(_ child: UIViewController) {
addChild(child)
child.view.heightAnchor.constraint(equalToConstant: child.view.frame.size.height).isActive = true
stackView.addArrangedSubview(child.view)
child.didMove(toParent: self)
}
我不确定为什么会这样。我已经对视图的高度进行了硬编码,但是 stackView 还希望我在添加视图之前对其进行约束。
我希望这对以后的人有所帮助!我用头撞墙好久了...
我正在尝试为我的应用程序创建一个统计页面,其中包含根据用户拥有的数据类型动态创建的各种图表。为此,我根据本教程堆叠多个 ViewController:https://swiftwithmajid.com/2019/02/27/building-complex-screens-with-child-viewcontrollers/
我 运行 遇到一个问题,其中 ViewController 的视图作为 arrangedSubView 添加到主 StackView,而不是垂直堆叠视图并允许我滚动浏览它们全部,它只是在 z 方向上将它们堆叠在一起。
这是堆栈ViewController代码:
class StackViewController: UIViewController {
private let scrollView = UIScrollView()
private let stackView = UIStackView()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(scrollView)
scrollView.addSubview(stackView)
setupConstraints()
stackView.axis = .vertical
}
private func setupConstraints() {
scrollView.translatesAutoresizingMaskIntoConstraints = false
stackView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
scrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
scrollView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
stackView.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor),
stackView.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor),
stackView.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor),
stackView.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor),
stackView.widthAnchor.constraint(equalTo: scrollView.frameLayoutGuide.widthAnchor)
])
}
}
extension StackViewController {
func add(_ child: UIViewController) {
addChild(child)
stackView.addArrangedSubview(child.view)
print(child.view!)
child.didMove(toParent: self)
}
func remove(_ child: UIViewController) {
guard child.parent != nil else {
return
}
child.willMove(toParent: nil)
stackView.removeArrangedSubview(child.view)
child.view.removeFromSuperview()
child.removeFromParent()
}
}
这里是我创建每个视图控制器并将其添加到堆栈的地方ViewController。 现在,我 运行 循环并一遍又一遍地添加单个视图控制器的副本:
class PrototypeViewController: StackViewController {
override func viewDidLoad() {
super.viewDidLoad()
for _ in 0...10 {
setupUI()
}
}
private func setupUI() {
let storyboard = UIStoryboard(name: "ConsistencyGraph", bundle: .main)
let consistencyGraphVC = storyboard.instantiateViewController(identifier: "ConsistencyGraphVC") as! ConsistencyGraphVC
add(consistencyGraphVC)
consistencyGraphVC.setupUI(name: "sessionName", consistencyPercentage: 30, ballsHit: 10)
}
}
这是视图控制器代码:
class ConsistencyGraphVC: UIViewController {
@IBOutlet weak var mainView: UIView!
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var ballsHitLabel: UILabel!
@IBOutlet weak var pieChartView: PieChartView!
override func viewDidLoad() {
super.viewDidLoad()
}
open func setupUI(name: String, consistencyPercentage: Double, ballsHit: Int) {
displayName(name:name)
drawPieChart(consistencyPercentage: consistencyPercentage)
displayBallsHit(ballsHit: ballsHit)
}
private func displayName(name: String) {
let prefix = "Consistency: "
let title = prefix + name
titleLabel.text = title
}
private func displayBallsHit(ballsHit: Int) {
ballsHitLabel.text = String(ballsHit)
}
private func drawPieChart(consistencyPercentage: Double) {
let maxPercent:Double = 100
let remainingPercent = maxPercent - consistencyPercentage
let dataEntry = [PieChartDataEntry(value: consistencyPercentage, data: String(consistencyPercentage)), PieChartDataEntry(value: remainingPercent, data: nil)]
let dataSet = PieChartDataSet(entries: dataEntry)
let chartData = PieChartData(dataSet: dataSet)
let color1 = randomColor()
let color2 = randomColor()
dataSet.colors = [color1, color2]
pieChartView.data = chartData
}
private func randomColor() -> UIColor {
let red = Double(arc4random_uniform(256))
let green = Double(arc4random_uniform(256))
let blue = Double(arc4random_uniform(256))
let color = UIColor(red: CGFloat(red/255), green: CGFloat(green/255), blue: CGFloat(blue/255), alpha: 1)
return color
}
}
起初,我以为是因为 View Controller 的大小可能不明确。然后我硬编码了每个视图控制器的宽度和高度,但仍然没有运气。
非常感谢任何帮助!我不知道这怎么可能。
提前致谢!
您忘记了 ScrollView 中 StackView 的一些必需约束。
你只有trailing, top, and bottom
还不够
- 正确的是:
stackView.leadingAnchor
stackView.trailingAnchor
stackView.topAnchor
stackView.bottomAnchor
stackView.widthAnchor
我终于找到了解决办法!
我需要补充:
child.view.heightAnchor.constraint(equalToConstant: child.view.frame.size.height).isActive = true
到这里的 StackViewController:
func add(_ child: UIViewController) {
addChild(child)
child.view.heightAnchor.constraint(equalToConstant: child.view.frame.size.height).isActive = true
stackView.addArrangedSubview(child.view)
child.didMove(toParent: self)
}
我不确定为什么会这样。我已经对视图的高度进行了硬编码,但是 stackView 还希望我在添加视图之前对其进行约束。
我希望这对以后的人有所帮助!我用头撞墙好久了...