在我的表视图的单元格中,我堆叠了包含视图的视图。我跟踪堆栈视图的约束。我根据我在堆栈视图中显示的视图数来计算此尾随约束的值。
有没有什么办法可以重新计算这个尾随约束值并显示视图而无需在设备旋转后重新加载viewWillTransition
中的表视图?
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
self.tableView.reloadData()
// self.view.layoutIfNeeded() // This doesn't recalculate constraints
}
有几种方法可以做到这一点 - 重新计算旋转尺寸(或尺寸变化)可能不是最好的方法。
利用UIStackView
处理所有布局的一种方法是在堆栈视图中添加“空白”视图。如果您只设置1或2个“真实”视图,则可以显示“空白”视图以填写3“列。”
因此,假设您可能显示具有零实际视图的行,请保持原型不变,但随后:
awakeFromNib()
中,创建并添加3个清晰的UIView
s到堆栈视图现在,当您设置要显示的视图时,隐藏不显示的视图并显示足够的空白视图以保持3个视图可见。
例子:
[1, 2]
隐藏view3
并展示blank1
[2]
隐藏view1
和view3
并显示blank1
和blank2
因此,您的堆栈中将始终有3个子视图,并且不需要进行任何计算...自动布局将保持它们的排列。
这是一个示例实现:
class ThreeColCell: UITableViewCell {
@IBOutlet var mainStackView: UIStackView!
@IBOutlet var view1: UIView!
@IBOutlet var view2: UIView!
@IBOutlet var view3: UIView!
var arrayOfRealViews: [UIView] = [UIView]()
var arrayOfBlankViews: [UIView] = [UIView]()
var myData: [Int] = [Int]() {
didSet {
// hide all the views in the stack
mainStackView.arrangedSubviews.forEach {
$0.isHidden = true
}
// show the specified "real" views
myData.forEach { i in
arrayOfRealViews[i - 1].isHidden = false
}
// if fewer than 3 "real" views, show "blank" view(s)
for i in 0..<(3 - myData.count) {
arrayOfBlankViews[i].isHidden = false
}
}
}
override func awakeFromNib() {
super.awakeFromNib()
commonInit()
}
func commonInit() -> Void {
// ordered array of views 1 to 3
arrayOfRealViews = [view1, view2, view3]
// add 3 "blank" views to the stack view
// and to array of blank views
for _ in 0..<3 {
let v = UIView()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .clear
mainStackView.addArrangedSubview(v)
arrayOfBlankViews.append(v)
}
}
}
class ThreeColTableViewController: UITableViewController {
var theData = [
[1, 2],
[1, 2, 3],
[1],
[1, 2, 3],
[2],
[2, 3],
[1, 2, 3],
[3],
[2, 3],
[1, 2, 3],
]
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return theData.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ThreeColCell", for: indexPath) as! ThreeColCell
cell.myData = theData[indexPath.row]
return cell
}
}
导致肖像:
和景观:
编辑:
这是另一个例子,使用带有.isDisabled1
(和2和3)属性的结构数组:
struct Profile {
var isDisabled1 = false
var isDisabled2 = false
var isDisabled3 = false
}
class ThreeColCell: UITableViewCell {
@IBOutlet var mainStackView: UIStackView!
@IBOutlet var view1: UIView!
@IBOutlet var view2: UIView!
@IBOutlet var view3: UIView!
var arrayOfRealViews: [UIView] = [UIView]()
var arrayOfBlankViews: [UIView] = [UIView]()
var myProfile: Profile = Profile() {
didSet {
// hide all the views in the stack
mainStackView.arrangedSubviews.forEach {
$0.isHidden = true
}
// I don't know how you have your button/label views set up, but here
// you would set button titles and label texts based on myProfile properties
// create a [1, 2, 3] array based on the .isDisabled# properties of the Profile object
var a = [Int]()
if !myProfile.isDisabled1 {
a.append(1)
}
if !myProfile.isDisabled2 {
a.append(2)
}
if !myProfile.isDisabled3 {
a.append(3)
}
// you now have an array "a" that will be
// [1, 2, 3] or
// [1, 2] or
// [2] or
// [2, 3] etc
// show the specified "real" views (arrays are Zero-based)
a.forEach { i in
arrayOfRealViews[i - 1].isHidden = false
}
// pad stackview to 3 using "blank" view(s)
// if 1 real view, show 2 blank views
// if 2 real views, show 1 blank view
// if 3 real views, don't show any blank views
for i in 0..<(3 - a.count) {
arrayOfBlankViews[i].isHidden = false
}
}
}
override func awakeFromNib() {
super.awakeFromNib()
// ordered array of views 1 to 3
arrayOfRealViews = [view1, view2, view3]
// add 3 "blank" views to the stack view
// and to array of blank views
for _ in 0..<3 {
let v = UIView()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .clear
mainStackView.addArrangedSubview(v)
arrayOfBlankViews.append(v)
}
}
}
class ThreeColTableViewController: UITableViewController {
var profilesArray: [Profile] = [Profile]()
override func viewDidLoad() {
super.viewDidLoad()
// create a few Profiles
// all 3 views are "enabled" by default
var p = Profile()
profilesArray.append(p)
// Profile with views 2 and 3 disabled
p = Profile()
p.isDisabled2 = true
p.isDisabled3 = true
profilesArray.append(p)
// Profile with view 3 disabled
p = Profile()
p.isDisabled3 = true
profilesArray.append(p)
// Profile with view 1 disabled
p = Profile()
p.isDisabled1 = true
profilesArray.append(p)
// Profile with views 1 and 2 disabled
p = Profile()
p.isDisabled1 = true
p.isDisabled2 = true
profilesArray.append(p)
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return profilesArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ThreeColCell", for: indexPath) as! ThreeColCell
cell.myProfile = profilesArray[indexPath.row]
return cell
}
}
您应该实现该方法
func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
当设备转换到新视图(横向或纵向)时会调用它。在此,您可以更改约束和调用
view.setNeedsLayout()
标记需要在下一个Runloop中重新计算布局。