- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 XIB 文件来设计 UITableView 中的单元格。我还使用出队机制,例如:let cell = tableView.dequeueReusableCellWithIdentifier("articleCell", forIndexPath: indexPath) as! ArticleTableViewCell
。我预先计算了 viewDidLoad
中的所有行高我的 ViewController 的方法 func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
立即返回正确的值。所有这些都有效。
在我的 UITableViewCell 中,我使用了许多动态高度标签(行数 = 0)。布局是这样的:
我不使用透明背景,我的所有 subview 都是不透明的,具有指定的背景颜色。我检查了Color Blended Layers
(一切都是绿色的)和Color Misaligned Images
(没有什么是黄色的)。
这是我的 cellForRowAtIndexPath 方法:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let tableViewSection = tableViewSectionAtIndex(indexPath.section)
let tableViewRow = tableViewSection.rows.objectAtIndex(indexPath.row) as! TableViewRow
switch tableViewRow.type! {
case TableViewRowType.Article :
let article = tableViewRow.article!
if article.type == TypeArticle.Article {
let cell = tableView.dequeueReusableCellWithIdentifier("articleCell", forIndexPath: indexPath) as! ArticleTableViewCell
return cell
} else {
let cell = tableView.dequeueReusableCellWithIdentifier("chroniqueCell", forIndexPath: indexPath) as! ChroniqueTableViewCell
return cell
}
default:
return UITableViewCell()
}
}
然后,在 willDisplayCell 方法中:
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
let tableViewSection = tableViewSectionAtIndex(indexPath.section)
let tableViewRow = tableViewSection.rows.objectAtIndex(indexPath.row) as! TableViewRow
let article = tableViewRow.article!
if cell.isKindOfClass(ArticleTableViewCell) {
let cell = cell as! ArticleTableViewCell
cell.delegate = self
cell.article = article
if let imageView = articleImageCache[article.id] {
cell.articleImage.image = imageView
cell.shareControl.image = imageView
} else {
loadArticleImage(article, articleCell: cell)
}
} else {
let cell = cell as! ChroniqueTableViewCell
cell.delegate = self
cell.article = article
if let chroniqueur = article.getChroniqueur() {
if let imageView = chroniqueurImageCache[chroniqueur.id] {
cell.chroniqueurImage.image = imageView
} else {
loadChroniqueurImage(article, articleCell: cell)
}
}
}
}
我的所有图像都是在后台线程中下载的,因此滚动时不会加载图像。
布局在我的ArticleTableViewCell
中修改当我设置“文章”属性时:cell.article = article
:
var article: Article? {
didSet {
updateUI()
}
}
还有我的 updateUI 函数:
func updateUI() -> Void {
if let article = article {
if let surtitre = article.surtitre {
self.surtitre.text = surtitre.uppercaseString
self.surtitre.setLineHeight(3)
} else {
self.surtitre.hidden = true
}
self.titre.text = article.titre
self.titre.setLineHeight(3)
if let amorce = article.amorce {
self.amorce.text = amorce
self.amorce.setLineHeight(3)
} else {
self.amorce.hidden = true
}
if let section = article.sectionSource {
if section.couleurFoncee != "" {
self.bordureSection.backgroundColor = UIColor(hexString: section.couleurFoncee)
self.surtitre.textColor = UIColor(hexString: section.couleurFoncee)
}
}
}
}
问题是在设置标签文本时,这会导致滞后。 setLineHeight
方法将标签的文本转换为 NSAttributedString 来指定行高,但即使删除此代码并简单地设置文本标签,在显示新单元格时也会出现小滞后。
如果我删除所有标签设置代码,单元格将显示默认标签文本,并且表格 View 滚动非常平滑,并且高度也正确。每当我设置标签文本时,就会出现滞后。
我正在我的 iPhone 6s 上运行该应用程序。在6s模拟器上,绝对没有任何延迟,非常流畅。
有什么想法吗?也许是因为我使用 UIStackView 嵌入我的标签?我这样做是因为在空标签时更容易隐藏标签,因此其他元素会向上移动,以避免空标签所在的位置出现间距。
我尝试了很多方法,但无法让桌面 View 平滑滚动,任何帮助将不胜感激。
最佳答案
我的所有优化使其在 6s 设备上几乎 100% 流畅,但在 5s 设备上,确实不流畅。我什至不想在 4s 设备上测试!使用多个多行标签时,我达到了自动布局性能限制。
对时间分析器进行深入分析后,结果是动态标签高度(在我的例子中为3)之间存在约束,并且这些标签具有属性文本(用于设置行高,但这不是瓶颈),看起来延迟是由 UIView::layoutSubviews 引起的,它渲染标签、更新约束等...这就是为什么当我不更改标签文本时,一切都很顺利。这里唯一的解决方案是不要在自定义 UITableViewCell 子类的layoutSubviews 方法中以编程方式使用自动布局和 subview 布局。
对于那些想知道如何做到这一点的人,我实现了 100% 平滑的滚动,无需自动布局和具有动态高度的多个标签(多行)。这是我的 UITableView 子类(我使用基类,因为我有 2 个相似的单元格类型):
//
// ArticleTableViewCell.swift
//
import UIKit
class ArticleTableViewCell: BaseArticleTableViewCell {
var articleImage = UIImageView()
var surtitre = UILabel()
var titre = UILabel()
var amorce = UILabel()
var bordureTop = UIView()
var bordureLeft = UIView()
var articleImageWidth = CGFloat(0)
var articleImageHeight = CGFloat(0)
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.articleImage.clipsToBounds = true
self.articleImage.contentMode = UIViewContentMode.ScaleAspectFill
self.bordureTop.backgroundColor = UIColor(colorLiteralRed: 219/255, green: 219/255, blue: 219/255, alpha: 1.0)
self.bordureLeft.backgroundColor = UIColor.blackColor()
self.surtitre.numberOfLines = 0
self.surtitre.font = UIFont(name: "Graphik-Bold", size: 11)
self.surtitre.textColor = UIColor.blackColor()
self.surtitre.backgroundColor = self.contentView.backgroundColor
self.titre.numberOfLines = 0
self.titre.font = UIFont(name: "PublicoHeadline-Extrabold", size: 22)
self.titre.textColor = UIColor(colorLiteralRed: 26/255, green: 26/255, blue: 26/255, alpha: 1.0)
self.titre.backgroundColor = self.contentView.backgroundColor
self.amorce.numberOfLines = 0
self.amorce.font = UIFont(name: "Graphik-Regular", size: 12)
self.amorce.textColor = UIColor.blackColor()
self.amorce.backgroundColor = self.contentView.backgroundColor
self.contentView.addSubview(articleImage)
self.contentView.addSubview(surtitre)
self.contentView.addSubview(titre)
self.contentView.addSubview(amorce)
self.contentView.addSubview(bordureTop)
self.contentView.addSubview(bordureLeft)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
if let article = article {
var currentY = CGFloat(0)
let labelX = CGFloat(18)
let labelWidth = fullWidth - 48
// Taille de l'image avec un ratio de 372/243
articleImageWidth = ceil(fullWidth - 3)
articleImageHeight = ceil((articleImageWidth * 243) / 372)
self.bordureTop.frame = CGRect(x: 3, y: 0, width: fullWidth - 3, height: 1)
// Image
if article.imagePrincipale == nil {
self.articleImage.frame = CGRect(x: 0, y: 0, width: 0, height: 0)
self.bordureTop.hidden = false
} else {
self.articleImage.frame = CGRect(x: 3, y: 0, width: self.articleImageWidth, height: self.articleImageHeight)
self.bordureTop.hidden = true
currentY += self.articleImageHeight
}
// Padding top
currentY += 15
// Surtitre
if let surtitre = article.surtitre {
self.surtitre.frame = CGRect(x: labelX, y: currentY, width: labelWidth, height: 0)
self.surtitre.preferredMaxLayoutWidth = self.surtitre.frame.width
self.surtitre.setTextWithLineHeight(surtitre.uppercaseString, lineHeight: 3)
self.surtitre.sizeToFit()
currentY += self.surtitre.frame.height
currentY += 15
} else {
self.surtitre.frame = CGRect(x: 0, y: 0, width: 0, height: 0)
}
// Titre
self.titre.frame = CGRect(x: labelX, y: currentY, width: labelWidth, height: 0)
self.titre.preferredMaxLayoutWidth = self.titre.frame.width
self.titre.setTextWithLineHeight(article.titre, lineHeight: 3)
self.titre.sizeToFit()
currentY += self.titre.frame.height
// Amorce
if let amorce = article.amorce {
currentY += 15
self.amorce.frame = CGRect(x: labelX, y: currentY, width: labelWidth, height: 0)
self.amorce.preferredMaxLayoutWidth = self.amorce.frame.width
self.amorce.setTextWithLineHeight(amorce, lineHeight: 3)
self.amorce.sizeToFit()
currentY += self.amorce.frame.height
} else {
self.amorce.frame = CGRect(x: 0, y: 0, width: 0, height: 0)
}
// Boutons
currentY += 9
self.updateButtonsPosition(currentY)
self.layoutUpdatedAt(currentY)
currentY += self.favorisButton.frame.height
// Padding bottom
currentY += 15
// Couleurs
self.bordureLeft.frame = CGRect(x: 0, y: 0, width: 3, height: currentY - 2)
if let section = article.sectionSource {
if let couleurFoncee = section.couleurFoncee {
self.bordureLeft.backgroundColor = couleurFoncee
self.surtitre.textColor = couleurFoncee
}
}
// Mettre à jour le frame du contentView avec la bonne hauteur totale
var frame = self.contentView.frame
frame.size.height = currentY
self.contentView.frame = frame
}
}
}
和基类:
//
// BaseArticleTableViewCell.swift
//
import UIKit
class BaseArticleTableViewCell: UITableViewCell {
var backgroundThread: NSURLSessionDataTask?
var delegate: SectionViewController?
var favorisButton: FavorisButton!
var shareButton: ShareButton!
var updatedAt: UILabel!
var fullWidth = CGFloat(0)
var article: Article? {
didSet {
// Update du UI quand on set l'article
updateArticle()
}
}
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.selectionStyle = UITableViewCellSelectionStyle.None
self.contentView.backgroundColor = UIColor(colorLiteralRed: 248/255, green: 248/255, blue: 248/255, alpha: 1.0)
// Largeur de la cellule, qui est toujours plein écran dans notre cas
// self.contentView.frame.width ne donne pas la bonne valeur tant que le tableView n'a pas été layouté
fullWidth = UIScreen.mainScreen().bounds.width
self.favorisButton = FavorisButton(frame: CGRect(x: fullWidth - 40, y: 0, width: 28, height: 30))
self.shareButton = ShareButton(frame: CGRect(x: fullWidth - 73, y: 0, width: 28, height: 30))
self.updatedAt = UILabel(frame: CGRect(x: 18, y: 0, width: 0, height: 0))
self.updatedAt.font = UIFont(name: "Graphik-Regular", size: 10)
self.updatedAt.textColor = UIColor(colorLiteralRed: 138/255, green: 138/255, blue: 138/255, alpha: 1.0)
self.updatedAt.backgroundColor = self.contentView.backgroundColor
self.addSubview(self.favorisButton)
self.addSubview(self.shareButton)
self.addSubview(self.updatedAt)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// Avant qu'une cell soit réutilisée, faire un cleanup
override func prepareForReuse() {
super.prepareForReuse()
// Canceller un background thread si y'en a un actif
if let backgroundThread = self.backgroundThread {
backgroundThread.cancel()
self.backgroundThread = nil
}
resetUI()
}
// Updater le UI
func updateArticle() {
self.favorisButton.article = article
self.shareButton.article = article
if let delegate = self.delegate {
self.shareButton.delegate = delegate
}
}
// Faire un reset du UI avant de réutiliser une instance de Cell
func resetUI() {
}
// Mettre à jour la position des boutons
func updateButtonsPosition(currentY: CGFloat) {
// Déjà positionnés en X, width, height, reste le Y
var shareFrame = self.shareButton.frame
shareFrame.origin.y = currentY
self.shareButton.frame = shareFrame
var favorisFrame = self.favorisButton.frame
favorisFrame.origin.y = currentY + 1
self.favorisButton.frame = favorisFrame
}
// Mettre à jour la position du updatedAt et son texte
func layoutUpdatedAt(currentY: CGFloat) {
var frame = self.updatedAt.frame
frame.origin.y = currentY + 15
self.updatedAt.frame = frame
if let updatedAt = article?.updatedAtListe {
self.updatedAt.text = updatedAt
} else {
self.updatedAt.text = ""
}
self.updatedAt.sizeToFit()
}
}
在我的 ViewController 的 viewDidLoad 上,我预先计算了所有行高:
// Créer une cache des row height des articles
func calculRowHeight() {
self.articleRowHeights = [Int: CGFloat]()
// Utiliser une seule instance de chaque type de cell
let articleCell = tableView.dequeueReusableCellWithIdentifier("articleCell") as! BaseArticleTableViewCell
let chroniqueCell = tableView.dequeueReusableCellWithIdentifier("chroniqueCell") as! BaseArticleTableViewCell
var cell: BaseArticleTableViewCell!
for articleObj in section.articles {
let article = articleObj as! Article
// Utiliser le bon type de cell
if article.type == TypeArticle.Article {
cell = articleCell
} else {
cell = chroniqueCell
}
// Setter l'article et refaire le layout
cell.article = article
cell.layoutSubviews()
// Prendre la hauteur générée
self.articleRowHeights[article.id] = cell.contentView.frame.height
}
}
设置请求单元格的行高:
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
let tableViewSection = tableViewSectionAtIndex(indexPath.section)
let tableViewRow = tableViewSection.rows.objectAtIndex(indexPath.row) as! TableViewRow
switch tableViewRow.type! {
case TableViewRowType.Article :
let article = tableViewRow.article!
return self.articleRowHeights[article.id]!
default:
return UITableViewAutomaticDimension
}
}
返回cellForRowAtIndexPath
中的单元格(我的tableView中有多种单元格类型,因此需要进行一些检查):
// Cellule pour un section/row spécifique
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let tableViewSection = tableViewSectionAtIndex(indexPath.section)
let tableViewRow = tableViewSection.rows.objectAtIndex(indexPath.row) as! TableViewRow
switch tableViewRow.type! {
case TableViewRowType.Article :
let article = tableViewRow.article!
if article.type == TypeArticle.Article {
let cell = tableView.dequeueReusableCellWithIdentifier("articleCell", forIndexPath: indexPath) as! ArticleTableViewCell
cell.delegate = self
cell.article = article
if let imageView = articleImageCache[article.id] {
cell.articleImage.image = imageView
cell.shareButton.image = imageView
} else {
cell.articleImage.image = placeholder
loadArticleImage(article, articleCell: cell)
}
return cell
}
return UITableViewCell()
default:
return UITableViewCell()
}
}
关于ios - 具有自动布局的 UITableView 滚动时不平滑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38404608/
如果附加了 'not-scroll' 类,我希望我的 body 不滚动,否则它应该正常工作。 我已经搜索这个问题两天了,但找不到任何适合我的解决方案。 我想要的是向 body 添加一个 class,并
我发现似乎是 iOS Safari 中的错误(我正在 iOS 8 上进行测试)。当绝对定位的 iFrame 漂浮在一段可滚动内容上方时,滚动 iFrame 也会滚动下面的内容。以下 HTML (ava
我有以下代码来显示一系列投资组合图片,这些图片以 SVG 格式存储在滚动 div 中: 在 Safari 中滚动使用两根手指或鼠标滚轮当光标位于 SVG 之一上时不起作用。 该页
我想用 javascript 做的是: 一旦你向下滚动页面,将#sidebar-box-fixed 的位置从 position: relative; 更改为定位:固定;。改回position:rela
我对 Elasticsearch 的滚动功能有点困惑。在 elasticsearch 中,每当用户在结果集上滚动时,是否可以每次调用搜索 API?来自文档 "search_type" => "scan
我试图做到这一点,以便当我向上或向下滚动页面时,它会运行不同的相应功能。我发现了一个类似的问题here但我已经尝试了他们的答案并且没有运气。 注意:此页面没有正常显示的滚动条。没有地方可以滚动。 bo
(C语言,GTK库) 在我的表单上,我有一个 GtkDrawingArea 小部件,我在上面使用 Cairo 绘制 GdkPixbufs(从文件加载)。我想要完成的是能够在窗口大小保持固定的情况下使用
最近我一直在尝试创建一个拉到(刷新,加载更多)swiftUI ScrollView !!,灵感来自 https://cocoapods.org/pods/SwiftPullToRefresh 我正在努
我正在开发一个应用程序,其中有两个带有可放置区域的列表和一个带有可拖动项目的侧面菜单。 当我滚动屏幕时,项目的位置困惑。 我试图在谷歌上寻找一些东西,最后得到了这个问题:jQuery draggabl
我在 UIWebView 中加载了一个 HTML 表单,而我的 UIWebView 恰好从 View 的中间开始并扩展。我必须锁定此 webView 不滚动并将其放在 ScrollView 之上以允许
如何在每个元素而不是整个元素上应用淡入淡出(与其高度相比)? HTML: CSS: * { padding: 0; margin: 0; box-sizing: border
我想使用带有垂直轴的 PageView 并使用鼠标滚动在页面之间移动,但是当我使用鼠标滚动时页面不滚动...仅页面单击并向上/向下滑动时滚动。 有什么办法吗? 我想保留属性 pageSnapping:
我制作这个程序是为了好玩,但我被卡住了,因为程序在屏幕外运行。如何在不完全更改代码的情况下实现滚动条。 public static void main(String args[]) throws IO
我想使用带有垂直轴的 PageView 并使用鼠标滚动在页面之间移动,但是当我使用鼠标滚动时页面不滚动...仅页面单击并向上/向下滑动时滚动。 有什么办法吗? 我想保留属性 pageSnapping:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
使用 jquery 技术从 css-tricks.com 获得滚动/跟随侧边栏,如果您不知道我在说什么,这里是代码: $(function() { var $sidebar = $
我是 jQuery Mobile 新手。我需要向我的应用程序添加 Facebook 滑动面板功能。 我经历了 sliding menu panel ,它工作正常,但我在菜单面板中的内容超出了窗口大小,
有没有办法在 js 或 jQuery 或任何其他工具中检测 ctrl + 滚动。我正在尝试执行一些动态布局代码,我需要检测不同分辨率下的屏幕宽度,我通过使用 setTimeout() 的计时器实现了这
我有一部分html代码:
我想控制 RichTextBox 滚动,但在控件中找不到任何方法来执行此操作。 这样做的原因是我希望当鼠标光标位于 RichTextBox 控件上时鼠标滚轮滚动有效(它没有事件焦点:鼠标滚轮事件由表单
我是一名优秀的程序员,十分优秀!