iOS UITableView 偏移刷新控件
iOS UITableView Offset Refresh Control
我有一个受超级视图限制的 UITableView。所以第一个单元格位于父视图的顶部。这意味着在 iPhone X 上,第一个单元格在凹口下流血,并进入状态栏区域。这是完全正确的。我希望 单元格在凹口下渗入状态栏区域,这就是当前的结果。
问题是,我还想在那个 table 视图上有一个刷新控件,以便用户可以通过拉动来刷新内容。但是当你在 iPhone X 上拉动刷新时,刷新控制被缺口切断。我不希望刷新控件被缺口截断。
所以基本上我想做的是将 table 视图限制在超级视图中,但将刷新控件限制在安全区域。
我看过了,Apple 似乎没有提供很多属性或方法来自定义刷新控件的行为。
我考虑过使用某种类型的自定义解决方案,但我想到的每个自定义解决方案都失去了刷新控件和 table 视图滚动等的所有预建物理特性。幕后逻辑太多了,我真的不想牺牲拉动刷新的感觉以及用户的感觉,因为它在 iOS.
中变得如此普遍
关于如何让第一个单元格在凹口下流血(限制在超级视图)但确保刷新控制不会被凹口切断(限制在安全区域)有什么想法吗?
我还在下面附上了屏幕截图,显示了单元格如何渗入状态栏,以及刷新控件如何被缺口切断。
编辑: 我还向 GitHub here 发布了一个示例项目。
但是刷新控件相关的基本代码如下。
private lazy var refreshControl = UIRefreshControl()
override func viewDidLoad() {
super.viewDidLoad()
refreshControl.addTarget(self, action: #selector(handleRefresh), for: .valueChanged)
tableView.refreshControl = refreshControl
}
@objc func handleRefresh() {
DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
self.refreshControl.endRefreshing()
}
}
table 视图的顶部约束必须相对于上边距
解决方法很简单,您可以在viewDidLoad 中设置刷新控件的边界。使用您需要的 y 偏移值(例如 50)
refreshControl.addTarget(self, action: #selector(handleRefresh), for: .valueChanged)
refreshControl.bounds = CGRect(x: refreshControl.bounds.origin.x,
y: 50,
width: refreshControl.bounds.size.width,
height: refreshControl.bounds.size.height)
tableView.refreshControl = refreshControl
更新:
您可以在刷新开始时添加内容插入,并在结束时将其带回。
override func viewDidLoad() {
super.viewDidLoad()
refreshControl.addTarget(self, action: #selector(handleRefresh), for: .valueChanged)
refreshControl.bounds = CGRect(x: refreshControl.bounds.origin.x,
y: -100,
width: refreshControl.bounds.size.width,
height: refreshControl.bounds.size.height);
tableView.refreshControl = refreshControl
}
@objc func handleRefresh() {
self.tableView.contentInset = UIEdgeInsets(top: 200, left: 0, bottom: 0, right: 0)
DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
self.refreshControl.endRefreshing()
self.tableView.contentInset = UIEdgeInsets.zero
self.tableView.setContentOffset(.zero, animated: true)
}
}
您可以享受底层福利UIScrollView
。使用您的 github 示例,您可以获得所需的一切,因此如果您将其扩展为:
extension ViewController: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView.contentOffset.y < 0 {
topConstraint.constant = -scrollView.contentOffset.y/2
} else {
topConstraint.constant = 0
}
}
}
什么反应每次 contentOffset
开始低于 0
并使您的 tableView
移动到底部,无论何时关闭或向下滚动它都会被设置为默认值 -在你的情况下 0
.
这样,您将获得与拖动相关的流畅动画 force/distance,如下所示
我有一个受超级视图限制的 UITableView。所以第一个单元格位于父视图的顶部。这意味着在 iPhone X 上,第一个单元格在凹口下流血,并进入状态栏区域。这是完全正确的。我希望 单元格在凹口下渗入状态栏区域,这就是当前的结果。
问题是,我还想在那个 table 视图上有一个刷新控件,以便用户可以通过拉动来刷新内容。但是当你在 iPhone X 上拉动刷新时,刷新控制被缺口切断。我不希望刷新控件被缺口截断。
所以基本上我想做的是将 table 视图限制在超级视图中,但将刷新控件限制在安全区域。
我看过了,Apple 似乎没有提供很多属性或方法来自定义刷新控件的行为。
我考虑过使用某种类型的自定义解决方案,但我想到的每个自定义解决方案都失去了刷新控件和 table 视图滚动等的所有预建物理特性。幕后逻辑太多了,我真的不想牺牲拉动刷新的感觉以及用户的感觉,因为它在 iOS.
中变得如此普遍关于如何让第一个单元格在凹口下流血(限制在超级视图)但确保刷新控制不会被凹口切断(限制在安全区域)有什么想法吗?
我还在下面附上了屏幕截图,显示了单元格如何渗入状态栏,以及刷新控件如何被缺口切断。
编辑: 我还向 GitHub here 发布了一个示例项目。
但是刷新控件相关的基本代码如下。
private lazy var refreshControl = UIRefreshControl()
override func viewDidLoad() {
super.viewDidLoad()
refreshControl.addTarget(self, action: #selector(handleRefresh), for: .valueChanged)
tableView.refreshControl = refreshControl
}
@objc func handleRefresh() {
DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
self.refreshControl.endRefreshing()
}
}
table 视图的顶部约束必须相对于上边距
解决方法很简单,您可以在viewDidLoad 中设置刷新控件的边界。使用您需要的 y 偏移值(例如 50)
refreshControl.addTarget(self, action: #selector(handleRefresh), for: .valueChanged)
refreshControl.bounds = CGRect(x: refreshControl.bounds.origin.x,
y: 50,
width: refreshControl.bounds.size.width,
height: refreshControl.bounds.size.height)
tableView.refreshControl = refreshControl
更新:
您可以在刷新开始时添加内容插入,并在结束时将其带回。
override func viewDidLoad() {
super.viewDidLoad()
refreshControl.addTarget(self, action: #selector(handleRefresh), for: .valueChanged)
refreshControl.bounds = CGRect(x: refreshControl.bounds.origin.x,
y: -100,
width: refreshControl.bounds.size.width,
height: refreshControl.bounds.size.height);
tableView.refreshControl = refreshControl
}
@objc func handleRefresh() {
self.tableView.contentInset = UIEdgeInsets(top: 200, left: 0, bottom: 0, right: 0)
DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
self.refreshControl.endRefreshing()
self.tableView.contentInset = UIEdgeInsets.zero
self.tableView.setContentOffset(.zero, animated: true)
}
}
您可以享受底层福利UIScrollView
。使用您的 github 示例,您可以获得所需的一切,因此如果您将其扩展为:
extension ViewController: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView.contentOffset.y < 0 {
topConstraint.constant = -scrollView.contentOffset.y/2
} else {
topConstraint.constant = 0
}
}
}
什么反应每次 contentOffset
开始低于 0
并使您的 tableView
移动到底部,无论何时关闭或向下滚动它都会被设置为默认值 -在你的情况下 0
.
这样,您将获得与拖动相关的流畅动画 force/distance,如下所示