如何根据条件为单元格正确分配样式,而不会在快速滚动后出现奇怪的样式行为?
Posted
技术标签:
【中文标题】如何根据条件为单元格正确分配样式,而不会在快速滚动后出现奇怪的样式行为?【英文标题】:How to properly assign a style based on a condition to a cell, without getting a weird style behaviour after fast scrolling? 【发布时间】:2020-04-22 20:08:25 【问题描述】:我阅读了很多关于滚动 TableView 的内容,一般的答案是我必须使用 prepareForReuse 再次设置元素样式并重置图像。
我的问题仍然存在。如果我滚动得足够快,我在单元格中的预览图像不是一个圆圈,而是一个 5px 的圆形边框,尽管条件从未满足。
这里的魔力在哪里,我总是有想要的条件结果? postType == 0 = 照片(应该是圆形的),postType == 2 = 文本,应该有圆角。
主视图
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableViewNew.dequeueReusableCell(withIdentifier: "cellNewPosts", for: indexPath) as! MainNewTableViewCell
cell.post = posts[indexPath.row]
return cell
我的自定义单元格
import UIKit
import AVKit
import SDWebImage
class MainNewTableViewCell: UITableViewCell
// Storyboard
@IBOutlet weak var viewContainer: ShadowedView!
didSet
viewContainer.layer.cornerRadius = 10
viewContainer.backgroundColor = .white
viewContainer.shadowColor = colorGrey
viewContainer.shadowRadius = 1
@IBOutlet weak var imageViewPreview: UIImageView!
didSet
imageViewPreview.backgroundColor = .white
imageViewPreview.layer.cornerRadius = imageViewPreview.frame.height / 2
@IBOutlet weak var viewContainerPreview: UIView!
didSet
viewContainerPreview.backgroundColor = .white
viewContainerPreview.layer.cornerRadius = viewContainerPreview.frame.height / 2
viewContainerPreview.layer.borderWidth = 2
viewContainerPreview.layer.borderColor = colorLightGrey.cgColor
@IBOutlet weak var labelPostFromCity: UILabel!
didSet
labelPostFromCity.layer.shadowColor = colorLightGrey.cgColor
labelPostFromCity.layer.shadowRadius = 1
labelPostFromCity.layer.shadowOpacity = 1
labelPostFromCity.layer.shadowOffset = CGSize(width: 1, height: 1)
labelPostFromCity.layer.masksToBounds = false
@IBOutlet weak var labelPostFromCountry: UILabel!
@IBOutlet weak var labelPostDate: UILabel!
@IBOutlet weak var imageTextBubble: UIImageView!
didSet
imageTextBubble.tintColor = colorDarkPastelBlue
@IBOutlet weak var imageHeart: UIImageView!
@IBOutlet weak var labelAmountLikes: UILabel!
@IBOutlet weak var labelAmountComments: UILabel!
// Variables
// AVPlayer Looper
var playerLooper: NSObject?
var playerLayer: AVPlayerLayer!
var queuePlayer: AVQueuePlayer?
var player: AVPlayer?
var mediaToUpload: Data?
var movieString: String?
var movieUrl: URL?
var post: PostModel?
didSet
guard let _postFromCity = post?.postFromCity else return
guard let _postFromCountry = post?.postFromCountry else return
guard let _postDate = post?.postDate else return
guard let _postMediaUrl = post?.postMediaUrl else return
guard let _postType = post?.postType else return
guard let _postText = post?.postText else return
setupViewCell(postFromCity: _postFromCity, postFromCountry: _postFromCountry, postDate: _postDate, postMediaUrl: _postMediaUrl, postType: _postType, postText: _postText)
func setupViewCell(postFromCity: String, postFromCountry: String, postDate: Double, postMediaUrl: String, postType: Int, postText: String)
imageViewPreview.image = nil
labelPostFromCity.text = postFromCity
labelPostFromCountry.text = postFromCountry
let postDate = postDate
let formattedPostDate = Date(timeIntervalSince1970: postDate)
let timeAgo = formattedPostDate.timeAgo(numericDates: false)
labelPostDate.text = timeAgo
if postType == 0
imageViewPreview.layer.cornerRadius = imageViewPreview.frame.height / 2
viewContainerPreview.layer.cornerRadius = viewContainerPreview.frame.height / 2
let mappedUrl = URL(string: postMediaUrl)
imageViewPreview.sd_imageIndicator = SDWebImageActivityIndicator.white
imageViewPreview.sd_setImage(with: mappedUrl) (_, _, _, _) in
if postType == 1
if postType == 2
imageViewPreview.layer.cornerRadius = 0
viewContainerPreview.layer.cornerRadius = 10
let xxx = UIColor.clear.image(CGSize(width: 50, height: 50))
let xxxx = textToImage(drawText: postText, inImage: xxx, atPoint: CGPoint(x: 0, y: 0))
imageViewPreview.image = xxxx
// Add text to the fake preview image
func textToImage(drawText text: String, inImage image: UIImage, atPoint point: CGPoint) -> UIImage
let textColor = UIColor.black
let textFont = UIFont(name: "Helvetica Bold", size: ????!
let scale = UIScreen.main.scale
UIGraphicsBeginImageContextWithOptions(image.size, false, scale)
let textFontAttributes = [
NSAttributedString.Key.font: textFont,
NSAttributedString.Key.foregroundColor: textColor,
] as [NSAttributedString.Key : Any]
image.draw(in: CGRect(origin: CGPoint.zero, size: image.size))
let rect = CGRect(origin: point, size: image.size)
text.draw(in: rect, withAttributes: textFontAttributes)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
override func awakeFromNib()
super.awakeFromNib()
self.selectionStyle = .none
override func prepareForReuse()
imageViewPreview.layer.cornerRadius = imageViewPreview.frame.height / 2
viewContainerPreview.layer.cornerRadius = viewContainerPreview.frame.height / 2
super.prepareForReuse()
extension UIColor
func circleImage(_ size: CGSize = CGSize(width: 1, height: 1)) -> UIImage
return UIGraphicsImageRenderer(size: size).image(actions: rendererContext in
self.setFill()
rendererContext.cgContext.fillEllipse(in: CGRect(origin: .zero, size: size))
)
【问题讨论】:
【参考方案1】:希望这会有所帮助
在单元格类的layoutSubview()
中添加条件
func layoutSubview()
if postType == 0
imageViewPreview.layer.cornerRadius = imageViewPreview.frame.height / 2
viewContainerPreview.layer.cornerRadius = viewContainerPreview.frame.height / 2
let mappedUrl = URL(string: postMediaUrl)
imageViewPreview.sd_imageIndicator = SDWebImageActivityIndicator.white
imageViewPreview.sd_setImage(with: mappedUrl) (_, _, _, _) in
else if postType == 2
imageViewPreview.layer.cornerRadius = 0
viewContainerPreview.layer.cornerRadius = 10
let xxx = UIColor.clear.image(CGSize(width: 50, height: 50))
let xxxx = textToImage(drawText: postText, inImage: xxx, atPoint: CGPoint(x: 0, y: 0))
imageViewPreview.image = xxxx
【讨论】:
以上是关于如何根据条件为单元格正确分配样式,而不会在快速滚动后出现奇怪的样式行为?的主要内容,如果未能解决你的问题,请参考以下文章
根据输入到单元格中的数字为单元格分配颜色和值,而无需点击运行按钮
Xamarin form-UWP - 在快速滚动列表时显示数据之前的黑色单元格
单行 UITableView 直到滚动才显示 detailTextLabel
根据其他节点的条件或行值动态更改 AG 网格上一个单元格样式