- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试在具有动态高度单元格的 UITableView 中创建类似 Accordion 的动画。
问题似乎是 reloadRows 会导致即时单元格高度更新,因此尽管 tableview 会设置动画,但单元格本身不会设置其高度的动画。这导致其他单元格有时会重叠并干扰展开的单元格内容。
这是我所获得的最接近单元格根据需要扩展的位置。但是,当折叠时,TextView 会立即消失,而标题会卡在中间直到折叠。
我尝试实现的效果与尝试 2 中展开时的效果完全相同,但在折叠时也是相反的( Accordion /显示样式)。
注意:如果可能的话,我还想继续使用 StackView 来设置 UITextView 上的 hidden
属性,因为我正在处理的实际项目涉及其他几个 subview ,它们的动画应该类似于UITextView。
我正在使用 XCode 11 beta 7。
struct Post {
var id: String
var title: String
var content: String
}
let posts = [
Post(id: "1", title: "Post 1", content: "Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est"),
Post(id: "2", title: "Post 2", content: "Lorem ipsum dolor"),
Post(id: "3", title: "Post 3", content: "Lorem ipsum dolor"),
Post(id: "4", title: "Post 4", content: "Lorem ipsum dolor"),
Post(id: "5", title: "Post 5", content: "Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda."),
Post(id: "6", title: "Post 6", content: "Lorem ipsum dolor")
]
class MyTableViewController: UITableViewController {
var selectedRow: IndexPath? = nil
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.backgroundColor = .darkGray
self.tableView.rowHeight = UITableView.automaticDimension
self.tableView.estimatedRowHeight = 200
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int {
return posts.count
}
override func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath)
-> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(
withIdentifier: "Cell", for: indexPath) as? MyTableViewCell
else { fatalError() }
let post = posts[indexPath.row]
let isExpanded = selectedRow == indexPath
cell.configure(expanded: isExpanded, post: post)
return cell
}
override func tableView(_ tableView: UITableView,
didSelectRowAt indexPath: IndexPath) {
var reloadPaths: [IndexPath] = []
if selectedRow != nil {
reloadPaths.append(selectedRow!)
}
if selectedRow == indexPath {
selectedRow = nil
} else {
reloadPaths.append(indexPath)
selectedRow = indexPath
}
tableView.reloadRows(at: reloadPaths, with: .automatic)
}
}
class MyTableViewCell: UITableViewCell {
@IBOutlet weak var title: UILabel!
@IBOutlet weak var textView: UITextView!
func configure(expanded: Bool, post: Post) {
title.text = post.title
textView.text = post.content
configureExpansion(expanded)
}
func configureExpansion(_ expanded: Bool) {
self.textView.isHidden = !expanded
self.contentView.backgroundColor = expanded ?
.red : .systemBackground
}
}
与尝试 1 完全相同的代码,除了 ...didSelectRowAt...
被替换为:
override func tableView(_ tableView: UITableView,
didSelectRowAt indexPath: IndexPath) {
tableView.beginUpdates()
if let selectedRow = selectedRow,
let prevCell = tableView.cellForRow(at: selectedRow) as? MyTableViewCell {
prevCell.configureExpansion(false)
}
let selectedCell = tableView.cellForRow(at: indexPath) as? MyTableViewCell
if selectedRow == indexPath {
selectedCell?.configureExpansion(false)
selectedRow = nil
} else {
selectedCell?.configureExpansion(true)
selectedRow = indexPath
}
tableView.endUpdates()
}
最佳答案
我终于在 beginUpdates/endUpdates 的基础上解决了这个问题。我对问题和解决方案的进一步研究如下。
如原始问题中所述,扩展阶段工作正常。这样做的原因是:
isHidden
属性设置为 false
时,包含的堆栈 View 会调整大小并为单元格提供新的固有内容大小endUpdates
被调用时,单元格将自动扩展,因为固有大小已更改且 tableView.rowHeight = .automaticDimension
。动画将根据需要逐渐显示新内容。但是,折叠阶段不会产生相同的反向动画效果。它没有的原因是:
isHidden
属性设置为 true
时,包含的堆栈 View 会隐藏 View 并将单元格调整为新的固有内容大小。 endUpdates
被调用时,动画将通过立即移除 UITextView 开始。考虑一下,这是意料之中的,因为它与扩张期间发生的情况相反。但是,当行缩小时,它会将可见元素“悬挂”在中间,而不是逐渐隐藏 UITextView,从而破坏了所需的动画效果。要获得所需的隐藏效果,UITextView 应在整个动画过程中保持可见,同时单元格会收缩。这包括几个步骤:
第 1 步:覆盖 heightForRow
override func tableView(_ tableView: UITableView,
heightForRowAt indexPath: IndexPath) -> CGFloat {
// If a cell is collapsing, force it to its original height stored in collapsingRow?
// instead of using the intrinsic size and .automaticDimension
if indexPath == collapsingRow?.indexPath {
return collapsingRow!.height
} else {
return UITableView.automaticDimension
}
}
UITextView 现在将在单元格缩小时保持可见,但由于自动布局,UITextView 会立即被剪裁,因为它锚定到单元格高度。
第 2 步:在 UIStackView 上创建一个高度约束,并在 cell 收缩时使其优先
2.1:在 Interface builder 中对 UIStackView 添加了高度限制
2.2:在 MyTableViewCell 中添加 heightConstraint
作为 strong(不是弱,这很重要)
2.3 在 MyTableViewCell 的 awakeFromNib
中,设置 heightConstraint.isActive = false
以保持默认行为
2.4 在界面生成器中:确保 UIStackView 底部约束的优先级设置低于高度约束的优先级。 IE。 999
用于底部约束,1000
用于高度约束。如果不这样做,就会在折叠阶段导致约束冲突。
第 3 步: 折叠时,激活 heightConstraint
并将其设置为 UIStackView 的当前固有大小。这会在单元格高度减小时保持 UITextView 的内容可见,但也会根据需要裁剪内容,从而产生“隐藏”效果。
if let expandedRow = expandedRow,
let prevCell = tableView.cellForRow(at: expandedRow.indexPath) as? MyTableViewCell {
prevCell.heightConstraint.constant = prevCell.stackView.frame.height
prevCell.heightConstraint.isActive = true
collapsingRow = expandedRow
}
第 4 步:在动画完成时使用 CATransaction.setCompletionBlock
重置状态
class MyTableViewController: UITableViewController {
var expandedRow: (indexPath: IndexPath, height: CGFloat)? = nil
var collapsingRow: (indexPath: IndexPath, height: CGFloat)? = nil
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.backgroundColor = .darkGray
self.tableView.rowHeight = UITableView.automaticDimension
self.tableView.estimatedRowHeight = 200
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int {
return posts.count
}
override func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(
withIdentifier: "Cell", for: indexPath) as? MyTableViewCell
else { fatalError() }
let post = posts[indexPath.row]
let isExpanded = expandedRow?.indexPath == indexPath
cell.configure(expanded: isExpanded, post: post)
return cell
}
override func tableView(_ tableView: UITableView,
heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath == collapsingRow?.indexPath {
return collapsingRow!.height
} else {
return UITableView.automaticDimension
}
}
override func tableView(_ tableView: UITableView,
didSelectRowAt indexPath: IndexPath) {
guard let tappedCell = tableView.cellForRow(at: indexPath) as? MyTableViewCell
else { return }
CATransaction.begin()
tableView.beginUpdates()
if let expandedRow = expandedRow,
let prevCell = tableView.cellForRow(at: expandedRow.indexPath)
as? MyTableViewCell {
prevCell.heightConstraint.constant = prevCell.stackView.frame.height
prevCell.heightConstraint.isActive = true
CATransaction.setCompletionBlock {
if let cell = tableView.cellForRow(at: expandedRow.indexPath)
as? MyTableViewCell {
cell.configureExpansion(false)
cell.heightConstraint.isActive = false
}
self.collapsingRow = nil
}
collapsingRow = expandedRow
}
if expandedRow?.indexPath == indexPath {
collapsingRow = expandedRow
expandedRow = nil
} else {
tappedCell.configureExpansion(true)
expandedRow = (indexPath: indexPath, height: tappedCell.frame.height)
}
tableView.endUpdates()
CATransaction.commit()
}
}
关于ios - 具有动态高度的单元格 Accordion 式动画的 UITableView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57845446/
我有下面的图表,它填充了显示器的宽度和高度。高度始终只比屏幕大一点,因此会出现滚动条以显示底部 20 像素左右。 有没有办法让 Kendo UI 显示 100%,而不是 105% 的高度? 在线示例:
这个问题在这里已经有了答案: Why doesn't height: 100% work to expand divs to the screen height? (12 个答案) 关闭 9 年前
此页面 ( http://purcraft.com/madeinla/) 有问题,我正在尝试使用 iframe 元素显示此页面的内容:( http://purcraft.com/madeinla/ho
我在一个父 div 中有 2 个子 div。 Child1 是标题,Child2 是正文。我希望将 Child 2 的高度设置为 Parent - Child1 的高度。 Child2 有内容,所以它
我正在尝试用图像填充窗口。我正在使用 CSS 来尝试解决这个问题,但我想知道是否有一种方法可以最大化图像的宽度/高度,直到所有空白区域都被填满,但又不会破坏质量。 .rel-img-co
这个问题在这里已经有了答案: How to make a div 100% height of the browser window (41 个回答) 关闭 8 年前。
这可能是一个新手问题,但是是否可以将 Sprite 图标添加到带有文本的标签中? 例如: labeltext .icon { width: 30px height: 30px;
我有 3 个 div,分别是 header、content 和 footer。页眉和页脚具有固定的高度,并且它们被设计为 float 在顶部和底部。我想要使用 jquery 自动计算中间的 con
我有一个外部 div,其指定的宽度/高度(以毫米为单位)。 (mm只是赋值,不用于渲染)。 里面有另一个 div,其实际宽度/高度(以 px 为单位)。 两个 div 可以具有不同的比例。 我想要做的
我正在为一个非常简单的画廊 webapp 进行布局排序,但是当我使用 HTML5 文档类型声明时,我的一些 div(100%)的高度会立即缩小,我不能似乎使用 CSS 将它们丰满起来。 我的 HTML
我正在为一个非常简单的画廊 webapp 进行布局排序,但是当我使用 HTML5 文档类型声明时,我的一些 div(100%)的高度会立即缩小,我不能似乎使用 CSS 将它们丰满起来。 我的 HTML
我想更改 UISearchBar。文本字段的高度和宽度。我的问题是如何更改 iphone 中 UISearchBar 中的 UiSearchbar 高度、宽度、颜色 和 Uitextfield 高度?
我想要两个宽度和高度均为 100% 的 div。我知道子 div 不会工作,因为父 div 没有特定的高度,但有没有办法解决这个问题? HTML: CSS: body
我有几个带有“priceText”类的 div,我试图实现如果 div.priceText 高度小于 100px,则隐藏 this div 中的图像。 我无法让它工作。我已成功隐藏所有 .priceT
我正在尝试从 Image 列中列出的图像中获取实际图像尺寸,并将其显示在 Image Size 列中。 我遇到的问题是,我只能获取第一张图片的大小,该图片会添加到 Image Size 列的每个单元格
我正在使用一个插件,它要求我在加载图像后获取图像的宽度和高度,而不管图像的尺寸是如何确定的。
我有一个示例 pdf(已附),它包括一个文本对象和一个高度几乎相同的矩形对象。然后我使用 itextrup 检查了 pdf 的内容,如下所示: 1 1 1 RG 1 1 1 rg 0.12 0 0 0
我是 WPF 新手。我试图解决的一个问题是如何在运行时获得正确的高度。 在我的应用程序中,我将用户控件动态添加到代码隐藏中的 Stackpanel。 Usercontrol 包含一些 Texblock
在自定义 WPF 控件中,我想将控件的宽度设置为高度的函数。例如:Width = Height/3 * x; 实现此目的的最佳方法是什么,以便控件正确且流畅地调整大小(和初始大小)? 最佳答案 您可以
好吧,我本以为这是一个简单的问题,但显然它让我感到困惑。 当我尝试设置 RibbonComboBox 的高度时,它不会移动它的实际大小,而是移动它周围的框。 这是我的 XAML:
我是一名优秀的程序员,十分优秀!