Есть несколько способов сделать это - пересчитать размер при вращении (или изменении размера) вероятно не лучший способ.
Одним из подходов, использующих преимущества UIStackView
для обработки всего макета, будет добавление «пустых» представлений в ваше представление стека. Если вы устанавливаете для отображения только 1 или 2 «реальных» представлений, вы также можете отобразить «пустые» представления для заполнить 3 «столбцы».
Итак, предполагая, что вы можете показать строку с реальными представлениями Zero, оставьте свой прототип как есть, но тогда:
- добавить ссылку на IBOutlet в представление стека
- в
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
}
}
В результате получается портрет:
![image](https://i.stack.imgur.com/mlFRU.png)
and Landscape:
Edit:
Вот еще один пример, использующий массив структур со свойствами .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
}
}