我正在做一个项目,我希望用户能够为同一个表单选择两种输入方法。我想出了一个包含两个自定义 UIView(以编程方式制作)的滚动视图。这是负责的视图控制器的代码:
import UIKit
class MainVC: UIViewController, UIScrollViewDelegate {
@IBOutlet weak var scrollView: UIScrollView!
@IBOutlet weak var pageControl: UIPageControl!
var customView1: CustomView1 = CustomView1()
var customView2: customView2 = CustomView2()
var frame = CGRect.zero
func setupScrollView() {
pageControl.numberOfPages = 2
frame.origin.x = 0
frame.size = scrollView.frame.size
customView1 = customView1(frame: frame)
self.scrollView.addSubview(customView1)
frame.origin.x = scrollView.frame.size.width
frame.size = scrollView.frame.size
customView2 = CustomView2(frame: frame)
self.scrollView.addSubview(customView2)
self.scrollView.contentSize = CGSize(width: scrollView.frame.size.width * 2, height: scrollView.frame.size.height)
self.scrollView.delegate = self
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let pageNumber = scrollView.contentOffset.x / scrollView.frame.size.width
pageControl.currentPage = Int(pageNumber)
}
override func viewDidLoad() {
super.viewDidLoad()
setupScrollView()
scrollView.delegate = self
}
当它工作时,Xcode 给我一条关于自动布局的错误消息:
“ScrollView”的可滚动内容大小不明确
还有一个问题:第二个 UIView 上的内容没有居中,即使它应该是:
import UIKit
class customView2: UIView {
lazy var datePicker: UIDatePicker = {
let datePicker = UIDatePicker()
datePicker.translatesAutoresizingMaskIntoConstraints = false
return datePicker
}()
//initWithFrame to init view from code
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
//initWithCode to init view from xib or storyboard
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupView()
}
func setupView () {
self.backgroundColor = .systemYellow
datePicker.datePickerMode = .date
datePicker.addTarget(self, action: #selector(self.datePickerValueChanged(_:)), for: .valueChanged)
addSubview(datePicker)
setupLayout()
}
func setupLayout() {
let view = self
NSLayoutConstraint.activate([
datePicker.centerXAnchor.constraint(equalTo: view.centerXAnchor),
datePicker.topAnchor.constraint(equalTo: view.topAnchor, constant: 20),
datePicker.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.5),
datePicker.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.2)
])
}
@objc func datePickerValueChanged(_ sender: UIDatePicker) {
let dateFormatter: DateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd.MM.yyyy"
let selectedDate: String = dateFormatter.string(from: sender.date)
print("Selected value \(selectedDate)")
}
关于如何解决这个问题的任何想法?非常感谢您提前。请放轻松,这是我关于stackoverflow的第一个问题。我对 swift 编程也很陌生。
为了让自己更轻松,
UIStackView
向滚动视图添加水平.distribution = .fillEqually
.contentLayoutGuide
.frameLayoutGuide
.frameLayoutGuide
这是您的代码,使用该方法进行了修改:
class MainVC: UIViewController, UIScrollViewDelegate {
@IBOutlet weak var scrollView: UIScrollView!
@IBOutlet weak var pageControl: UIPageControl!
var customView1: CustomView1 = CustomView1()
var customView2: CustomView2 = CustomView2()
func setupScrollView() {
pageControl.numberOfPages = 2
// let's put the two custom views in a horizontal stack view
let stack = UIStackView()
stack.axis = .horizontal
stack.distribution = .fillEqually
stack.translatesAutoresizingMaskIntoConstraints = false
stack.addArrangedSubview(customView1)
stack.addArrangedSubview(customView2)
// add the stack view to the scroll view
scrollView.addSubview(stack)
let contentG = scrollView.contentLayoutGuide
let frameG = scrollView.frameLayoutGuide
NSLayoutConstraint.activate([
// constrain stack view to all 4 sides of content layout guide
stack.topAnchor.constraint(equalTo: contentG.topAnchor),
stack.leadingAnchor.constraint(equalTo: contentG.leadingAnchor),
stack.trailingAnchor.constraint(equalTo: contentG.trailingAnchor),
stack.bottomAnchor.constraint(equalTo: contentG.bottomAnchor),
// stack view Height equal to scroll view frame layout guide height
stack.heightAnchor.constraint(equalTo: frameG.heightAnchor),
// stack is set to fillEqually, so we only need to set
// width of first custom view equal to scroll view frame layout guide width
customView1.widthAnchor.constraint(equalTo: frameG.widthAnchor),
])
self.scrollView.delegate = self
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let pageNumber = scrollView.contentOffset.x / scrollView.frame.size.width
pageControl.currentPage = Int(pageNumber)
}
override func viewDidLoad() {
super.viewDidLoad()
setupScrollView()
scrollView.delegate = self
}
}
编辑
几个附加说明...
UIScrollView
布局歧义。正如我在最初的评论说,如果我们添加了一个UIScrollView
在情节提要/我覆盖整个院落乙uilder,但千万不要给它任何约束的内容,IB会抱怨说,它有可滚动的内容大小歧义-因为它确实。我们还没有告诉 IB 内容是什么。
我们可以忽略它,也可以选择滚动视图,然后在 Size Inspector 窗格底部更改Ambiguity
为Never Verify
。
作为一般规则,您应该更正所有自动布局警告/错误,但在诸如此类的特定情况下 - 我们知道它是按照我们想要的方式设置的,并且我们将在运行时满足约束 - 它不会不去管它会很痛。
UIDatePicker
没有水平居中。它实际上是居中的。如果添加此行:
datePicker.backgroundColor = .green
您会看到对象框架本身居中,但框架内的 UI 元素是左对齐的:
从快速研究来看,似乎无法改变。
现在,从 Apple 的文档中,我们看到:
您应该使用自动布局将日期选择器集成到您的布局中。虽然日期选择器可以调整大小,但它们应该以其内在的内容大小使用。
奇怪的是,如果我们UIDatePicker
在 Storyboard 中添加 a ,将其更改Preferred Style
为Compact
,并给它 centerX 和 centerY 约束...... Storyboard 不相信它具有内在的内容大小。
如果我们通过代码添加它,只给它 X/Y 位置约束,它将以它的内在内容大小显示在我们想要的位置。但是...如果我们跳入Debug View Hierarchy
,Xcode 会告诉我们它的Position 和 size 是不明确的。
现在,还有什么更有趣的......
点击该控件并观看调试控制台填充535 行自动布局错误/警告!!!
一些快速调查——这些都是内部自动布局问题,与我们的代码或布局无关。
当 iOS 内置键盘开始显示自动完成选项时,我们会看到类似的问题。
这些可以安全地忽略。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句