Ios Swift:从stackView中消失的视图
我在主情节提要中有一个相当简单的设置:Ios Swift:从stackView中消失的视图,ios,iphone,swift,uistackview,Ios,Iphone,Swift,Uistackview,我在主情节提要中有一个相当简单的设置: 包含三个视图的堆栈视图 第一个视图具有固定高度,并包含一个线段控制器 其他两个视图没有任何限制,其想法是一次只有一个视图处于活动状态,从而填充可用空间 我的代码将处理更改的视图活动视图,如下所示: import Foundation import UIKit class ViewController : UIViewController { @IBOutlet weak var stackView: UIStackView! @IBOu
- 包含三个视图的堆栈视图
- 第一个视图具有固定高度,并包含一个线段控制器
- 其他两个视图没有任何限制,其想法是一次只有一个视图处于活动状态,从而填充可用空间
import Foundation
import UIKit
class ViewController : UIViewController {
@IBOutlet weak var stackView: UIStackView!
@IBOutlet weak var segmentController: UISegmentedControl!
@IBAction func SegmentClicked(_ sender: AnyObject) {
updateView(segment: sender.titleForSegment(at: sender.selectedSegmentIndex)!)
}
override func viewDidLoad() {
updateView(segment: "First")
}
func updateView(segment: String) {
UIView.animate(withDuration: 1) {
if(segment == "First") {
self.stackView.arrangedSubviews[1].isHidden = false
self.stackView.arrangedSubviews[2].isHidden = true
} else {
self.stackView.arrangedSubviews[1].isHidden = true
self.stackView.arrangedSubviews[2].isHidden = false
}
print("Updating views")
print("View 1 is \(self.stackView.arrangedSubviews[1].isHidden ? "hidden" : "visible")")
print("View 2 is \(self.stackView.arrangedSubviews[2].isHidden ? "hidden" : "visible")")
}
}
}
如您所见,当选择名为“First”的选项卡时,索引1处的子视图应显示,而索引2处的子视图应隐藏;当选择任何其他内容时,索引2处的子视图应显示,而索引1处的子视图应隐藏
如果我慢慢地改变视图,这在一开始似乎是可行的,但是如果我稍微快一点,在点击几下后,索引1处的视图似乎会永久隐藏,导致索引0处的视图覆盖整个屏幕。我在下面放了一个动画,展示了这个问题和故事板的截图。输出显示,当问题发生时,单击第一个线段时,两个视图都保持隐藏状态
有谁能告诉我为什么会这样?这是一个错误,还是我没有做我应该做的事情
非常感谢
更新:我似乎能够可靠地重现问题,按顺序转到第一个>第二个>第三个>第二个>第一个片段。根据我所看到的,这种奇怪的行为是由动画持续时间造成的。正如您所看到的,动画需要一秒钟才能完成,但是如果切换segmentControl的速度比这快,那么我认为这就是导致这种行为的原因 您应该做的是在调用该方法时停用用户交互,然后在动画完成后重新启用它 它应该是这样的:
func updateView(segment: String) {
segmentControl.userInteractionEnabled = false
UIView.animateWithDuration(1.0, animations: {
if(segment == "First") {
self.stackView.arrangedSubviews[1].isHidden = false
self.stackView.arrangedSubviews[2].isHidden = true
} else {
self.stackView.arrangedSubviews[1].isHidden = true
self.stackView.arrangedSubviews[2].isHidden = false
}
print("Updating views")
print("View 1 is \(self.stackView.arrangedSubviews[1].isHidden ? "hidden" : "visible")")
print("View 2 is \(self.stackView.arrangedSubviews[2].isHidden ? "hidden" : "visible")")
}, completion: {(finished: Bool) in
segmentControl.userInteractionEnabled = true
}
}
虽然这会阻止快速切换(您可能会认为这是一个缺点),但我知道解决这一问题的唯一其他方法是完全删除动画。检查堆栈视图和子视图上的配置和自动布局约束,尤其是分段控件 分段控件使堆栈视图的设置复杂化,因此我将从堆栈视图中取出分段控件,并设置其相对于主视图的约束 使用堆栈视图之外的分段控件,设置堆栈视图相对简单,这样代码就能正常工作 重置堆栈视图上的约束,使其位于分段控件下方并覆盖superview的其余部分。在“属性检查器”中,将“对齐”设置为“填充”,将“分布”设置为“均匀填充”,将“内容模式”设置为“按比例填充” 删除子视图上的约束,并将其内容模式设置为“按比例填充”
在你的代码中调整arrangedSubviews上的索引,它会自动工作。最后,在尝试了这里的所有建议之后,我仍然无法理解为什么它会这样,所以我联系了苹果,苹果要求我提交一份bug报告。不过,我确实找到了解决方法,首先取消隐藏两个视图,解决了我的问题:
func updateView(segment: String) {
UIView.animate(withDuration: 1) {
self.stackView.arrangedSubviews[1].isHidden = false
self.stackView.arrangedSubviews[2].isHidden = false
if(segment == "First") {
self.stackView.arrangedSubviews[2].isHidden = true
} else {
self.stackView.arrangedSubviews[1].isHidden = true
}
}
}
错误在于在堆栈视图中隐藏和显示视图是累积的。奇怪的苹果虫。如果在堆栈视图中隐藏视图两次,则需要显示两次才能将其取回。如果显示三次,则需要隐藏三次才能真正隐藏它(假设在开始时已隐藏) 这与使用动画无关 因此,如果在代码中执行类似操作,仅在视图可见时隐藏视图,则可以避免此问题:
if myView.isHidden == false {
myView.isHidden = true
}
IMO称,基于davebatton的漂亮回答,您还可以添加UIView扩展以使呼叫站点更干净
extension UIView {
var isHiddenInStackView: Bool {
get {
return isHidden
}
set {
if isHidden != newValue {
isHidden = newValue
}
}
}
}
然后您可以调用
stackView.subviews[someIndex].isHiddenInStackView=false
,如果您在堆栈视图中有多个视图要管理,而不是一堆if语句,这将非常有用。对不起,Benjamin,这似乎仍然无法解决问题-感谢您的尝试@本,哈,真奇怪。我再看一眼谢谢,我刚刚更新了上面的内容,说如果我转到第一个>第二个>第三个>第二个>第一个片段,我可以复制它,如果这有帮助的话@Ben如果你按顺序慢慢点击它们(例如,点击之间的停顿时间超过一秒钟),它是否仍然会被复制?是的-没有任何区别。你说你的两个其他视图没有“限制”,你应该用限制设置它们。然后,如果希望它们不显示在视图中,请告诉它们隐藏。堆栈视图最酷的一点是,当你告诉某些东西隐藏在其中时,堆栈视图将重新调整以正确匹配其余视图。文本“First”实际上在动画底部可见,因此不会隐藏。是否确实已在段控件上设置了固定高度约束?@phix23固定高度位于包含段控件的堆栈视图的第一个子视图上。它被设置为高度=32。我也尝试过堆栈外视图,所以我不相信是这样。它还报告为隐藏在打印
中,因此它肯定认为它是隐藏的(除非我可能需要等待动画完成后再检查?。@zsteed我的理解是,如果没有约束,视图应该自动填充堆栈视图?无论哪种方式,即使有0/0/0/0约束,问题仍然会发生。我相信这是因为代码由于某种原因无法取消隐藏第一个视图,但我不知道为什么。我想是的,当显示和隐藏视图时,StackView会自动处理。运气不好-在进入第一个>第二个>第三个>第二个>第一个之后,仍然不允许取消隐藏第一个视图。我在UITableViewCell中遇到了与UIStackView相同的问题。由于单元格被重用,当您快速滚动表格时,stackview可能会连续快速隐藏/取消隐藏组件。我的解决办法是