Swift: 在滚动时改变表格视图的高度
Swift: change tableview height on scroll
我有一个VC如图
顶部有一个 UICollectionView,底部有一个 UITableView。
CollectionView 占屏幕 1:3,TableView 占屏幕 2:3(使用 equalHeight 约束设置)。
我想在滚动 tableView 时 更改 UICollectionView 的高度。
当tableView向上滚动时,我想将 equalHeights 约束的乘数更改为 1:5 和 4:5 collectionView 和 tableView respectively.This 将确保 tableView 的高度增加 和 collectionView 减少
当tableView向下滚动时,equalHeights 约束的乘数应重置为默认值.
我试过向 tableView 添加滑动和平移手势,但它们无法识别。
如何实现这个功能?
P.S:希望通过使用平移手势来实现此功能,以便向上和向下拖动逐渐改变高度。
这是视图层次结构
EDIT/UPDATE
这是我正在使用的代码。
class MyConstant {
var height:CGFloat = 10
}
let myConstant = MyConstant()
主屏幕VC
override func viewWillAppear(_ animated: Bool) {
myConstant.height = self.view.frame.size.height
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if (self.lastContentOffset < scrollView.contentOffset.y) {
NotificationCenter.default.post(name: Notifications.decreaseHeightNotification.name, object: nil)
self.topViewConstraint.constant = -self.view.frame.height / 6
UIView.animate(withDuration: 0.3, animations: {
self.view.layoutIfNeeded()
})
} else if (self.lastContentOffset > scrollView.contentOffset.y) {
NotificationCenter.default.post(name: Notifications.increaseHeightNotification.name, object: nil)
self.topViewConstraint.constant = 0
UIView.animate(withDuration: 0.3, animations: {
self.view.layoutIfNeeded()
})
}
self.lastContentOffset = scrollView.contentOffset.y
}
Cell.Swift
override func awakeFromNib() {
super.awakeFromNib()
NotificationCenter.default.addObserver(self, selector: #selector(decreaseHeight), name: Notification.Name("decreaseHeightNotification"), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(increaseHeight), name: Notification.Name("increaseHeightNotification"), object: nil)
self.contentView.translatesAutoresizingMaskIntoConstraints = false
heightConstraint.constant = (myConstant.height / 3) - 10
widthConstraint.constant = heightConstraint.constant * 1.5
}
@objc func decreaseHeight() {
heightConstraint.constant = (myConstant.height / 6) - 10
widthConstraint.constant = (heightConstraint.constant * 1.5)
self.layoutIfNeeded()
}
@objc func increaseHeight() {
heightConstraint.constant = (myConstant.height / 3) - 10
widthConstraint.constant = (heightConstraint.constant * 1.5)
self.layoutIfNeeded()
}
现在,当我同时滚动两者时,屏幕会冻结。还有调整 collectionViewCell 大小的更好方法吗?
由于 UITableView
是 UIScrollView
的子类,您的 table 视图的 delegate
可以接收 UIScrollViewDelegate
方法。
您不需要使用 PanGesture
首先实施 UITableviewDelegate
然后
var oldContentOffset = CGPoint.zero
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let contentOffset = scrollView.contentOffset.y - oldContentOffset.y
if (self.oldContentOffset < scrollView.contentOffset.y) {
// moved to top
} else if (self.oldContentOffset > scrollView.contentOffset.y) {
// moved to bottom
} else {
// didn't move
}
oldContentOffset = scrollView.contentOffset
}
在这里您可以编写逻辑来更改约束的常量值
UPDATE/EDIT
另一件事是不要对 tabelview height.with 集合视图使用乘数,你可以用 self.view 以 1/3 的比例给出高度约束。对于 tableview,只需给出前导、尾随顶部 (UICollectionView) 和底部。
因此,当您更改 UICollectionView 的高度常量时,Tableview 高度会自动减小,反之亦然。
您不能从插座更改乘数,因为它是只读的。所以你必须将值设为 self.view.frame.height / 3
才能为你工作
希望对您有所帮助
我还没有测试过,但你可以这样做。在此视图中使用自动布局。它会更好地工作。
将主视图的tableview约束设置为Top, Left, Bottom, Right => 0, 0, 0, 0,将collectionView放在tableview下,约束为Top,Left,Right, height => 0, 0, 0, x 主视图。
Note: Tableview is on top of the collectionView.
连接你的 CollectionView 的高度约束出口并定义你的 defaultOffset 变量
@IBOutlet weak var defaultHeightConstraint: NSLayoutConstraint
var defaultOffSet: CGPoint?
在viewDidLoad中,
override func viewDidLoad() {
super.viewDidLoad()
tableView.contentInset = UIEdgeInsetsMake(collectionView.size.height, 0, 0, 0)
}
在viewDidAppear中,写
override func viewDidAppear(_ animated: Bool) {
defaultOffSet = tableView.contentOffset
}
在 ViewDidScroll 中
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let offset = tableView.contentOffset
if let startOffset = self.defaultOffSet {
if offset.y < startOffset.y {
// Scrolling down
// check if your collection view height is less than normal height, do your logic.
let deltaY = fabs((startOffset.y - offset.y))
defaultHeightConstraint.constant = defaultHeightConstraint.constant - deltaY
} else {
// Scrolling up
let deltaY = fabs((startOffset.y - offset.y))
defaultHeightConstraint.constant = defaultHeightConstraint.constant + deltaY
}
self.view.layoutIfNeeded()
}
}
希望对您有所帮助。
为了更简洁的方法,为什么不使用 UIScrollView
作为容器视图并在其中添加 UICollectionView
和 UITableView
并提供 collectionView
高度限制同时禁用 tableView
的滚动直到你的 collectionView
的高度限制变为 0.
这是片段:
用 UIScrollViewDelegate
扩展你的 VC 并使用:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView.contentOffset.y >= 0 && scrollView.contentOffset.y <= yourLimit {
heightConstraint.constant = collectionViewHeight - scrollView.contentOffset.y
tableView.isScrollEnabled = false
} else if scrollView.contentOffset.y > yourLimit {
heightConstraint.constant = collectionViewHeight
tableView.isScrollEnabled = true
}
}
自定义其中的小东西后试试这个片段。它应该主要工作,如果它没有,我会分享另一种方法,一旦它不起作用。
你为什么不直接添加自定义 Table 单元格和你的集合视图,当 indexPath.row == 0 时,return 你的自定义 table 单元格。
我有一个VC如图
顶部有一个 UICollectionView,底部有一个 UITableView。 CollectionView 占屏幕 1:3,TableView 占屏幕 2:3(使用 equalHeight 约束设置)。
我想在滚动 tableView 时 更改 UICollectionView 的高度。
当tableView向上滚动时,我想将 equalHeights 约束的乘数更改为 1:5 和 4:5 collectionView 和 tableView respectively.This 将确保 tableView 的高度增加 和 collectionView 减少
当tableView向下滚动时,equalHeights 约束的乘数应重置为默认值.
我试过向 tableView 添加滑动和平移手势,但它们无法识别。
如何实现这个功能?
P.S:希望通过使用平移手势来实现此功能,以便向上和向下拖动逐渐改变高度。
这是视图层次结构
EDIT/UPDATE
这是我正在使用的代码。
class MyConstant {
var height:CGFloat = 10
}
let myConstant = MyConstant()
主屏幕VC
override func viewWillAppear(_ animated: Bool) {
myConstant.height = self.view.frame.size.height
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if (self.lastContentOffset < scrollView.contentOffset.y) {
NotificationCenter.default.post(name: Notifications.decreaseHeightNotification.name, object: nil)
self.topViewConstraint.constant = -self.view.frame.height / 6
UIView.animate(withDuration: 0.3, animations: {
self.view.layoutIfNeeded()
})
} else if (self.lastContentOffset > scrollView.contentOffset.y) {
NotificationCenter.default.post(name: Notifications.increaseHeightNotification.name, object: nil)
self.topViewConstraint.constant = 0
UIView.animate(withDuration: 0.3, animations: {
self.view.layoutIfNeeded()
})
}
self.lastContentOffset = scrollView.contentOffset.y
}
Cell.Swift
override func awakeFromNib() {
super.awakeFromNib()
NotificationCenter.default.addObserver(self, selector: #selector(decreaseHeight), name: Notification.Name("decreaseHeightNotification"), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(increaseHeight), name: Notification.Name("increaseHeightNotification"), object: nil)
self.contentView.translatesAutoresizingMaskIntoConstraints = false
heightConstraint.constant = (myConstant.height / 3) - 10
widthConstraint.constant = heightConstraint.constant * 1.5
}
@objc func decreaseHeight() {
heightConstraint.constant = (myConstant.height / 6) - 10
widthConstraint.constant = (heightConstraint.constant * 1.5)
self.layoutIfNeeded()
}
@objc func increaseHeight() {
heightConstraint.constant = (myConstant.height / 3) - 10
widthConstraint.constant = (heightConstraint.constant * 1.5)
self.layoutIfNeeded()
}
现在,当我同时滚动两者时,屏幕会冻结。还有调整 collectionViewCell 大小的更好方法吗?
由于 UITableView
是 UIScrollView
的子类,您的 table 视图的 delegate
可以接收 UIScrollViewDelegate
方法。
您不需要使用 PanGesture
首先实施 UITableviewDelegate
然后
var oldContentOffset = CGPoint.zero
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let contentOffset = scrollView.contentOffset.y - oldContentOffset.y
if (self.oldContentOffset < scrollView.contentOffset.y) {
// moved to top
} else if (self.oldContentOffset > scrollView.contentOffset.y) {
// moved to bottom
} else {
// didn't move
}
oldContentOffset = scrollView.contentOffset
}
在这里您可以编写逻辑来更改约束的常量值
UPDATE/EDIT
另一件事是不要对 tabelview height.with 集合视图使用乘数,你可以用 self.view 以 1/3 的比例给出高度约束。对于 tableview,只需给出前导、尾随顶部 (UICollectionView) 和底部。 因此,当您更改 UICollectionView 的高度常量时,Tableview 高度会自动减小,反之亦然。
您不能从插座更改乘数,因为它是只读的。所以你必须将值设为 self.view.frame.height / 3
才能为你工作
希望对您有所帮助
我还没有测试过,但你可以这样做。在此视图中使用自动布局。它会更好地工作。
将主视图的tableview约束设置为Top, Left, Bottom, Right => 0, 0, 0, 0,将collectionView放在tableview下,约束为Top,Left,Right, height => 0, 0, 0, x 主视图。
Note: Tableview is on top of the collectionView.
连接你的 CollectionView 的高度约束出口并定义你的 defaultOffset 变量
@IBOutlet weak var defaultHeightConstraint: NSLayoutConstraint
var defaultOffSet: CGPoint?
在viewDidLoad中,
override func viewDidLoad() {
super.viewDidLoad()
tableView.contentInset = UIEdgeInsetsMake(collectionView.size.height, 0, 0, 0)
}
在viewDidAppear中,写
override func viewDidAppear(_ animated: Bool) {
defaultOffSet = tableView.contentOffset
}
在 ViewDidScroll 中
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let offset = tableView.contentOffset
if let startOffset = self.defaultOffSet {
if offset.y < startOffset.y {
// Scrolling down
// check if your collection view height is less than normal height, do your logic.
let deltaY = fabs((startOffset.y - offset.y))
defaultHeightConstraint.constant = defaultHeightConstraint.constant - deltaY
} else {
// Scrolling up
let deltaY = fabs((startOffset.y - offset.y))
defaultHeightConstraint.constant = defaultHeightConstraint.constant + deltaY
}
self.view.layoutIfNeeded()
}
}
希望对您有所帮助。
为了更简洁的方法,为什么不使用 UIScrollView
作为容器视图并在其中添加 UICollectionView
和 UITableView
并提供 collectionView
高度限制同时禁用 tableView
的滚动直到你的 collectionView
的高度限制变为 0.
这是片段:
用 UIScrollViewDelegate
扩展你的 VC 并使用:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView.contentOffset.y >= 0 && scrollView.contentOffset.y <= yourLimit {
heightConstraint.constant = collectionViewHeight - scrollView.contentOffset.y
tableView.isScrollEnabled = false
} else if scrollView.contentOffset.y > yourLimit {
heightConstraint.constant = collectionViewHeight
tableView.isScrollEnabled = true
}
}
自定义其中的小东西后试试这个片段。它应该主要工作,如果它没有,我会分享另一种方法,一旦它不起作用。
你为什么不直接添加自定义 Table 单元格和你的集合视图,当 indexPath.row == 0 时,return 你的自定义 table 单元格。