Reputation: 205
I currently have a UICollectionView to create a news page with several news items, kind of like what Facebook is using. Because I am not using a live server just yet, I am trying to code most of the functionalities by using temporary static entries (see code).
My next goal: I would like to add "show more" to a news cell when the text inside that cell is longer than I want it to be. Tapping "show more" will expand the cell and display the rest of the text. Tapping it again will set it back to its initial height.
let cellId = "cellId"
class Post {
var title: String?
var statusText: String?
var nameDate: String?
}
class NewsController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
var posts = [Post]()
override func viewDidLoad() {
super.viewDidLoad()
let postDennis = Post()
postDennis.title = "How to start programming in Swift!"
postDennis.statusText = "Swift is a powerful and intuitive programming language for macOS, iOS, watchOS and tvOS. Writing Swift code is interactive and fun, the syntax is concise yet expressive, and Swift includes modern features developers love. Swift code is safe by design, yet also produces software that runs lightning-fast. Swift is free and open source, and it’s available to a wide audience of developers, educators and students under the Apache 2.0 open-source licence."
postDennis.nameDate = "\nAugust 21st, Dennis van Mazijk"
let postMai = Post()
postMai.title = "What is Swift?"
postMai.statusText = "Hello, this is some news!"
postMai.nameDate = "\nAugust 18th, Mai Satou"
posts.append(postDennis)
posts.append(postMai)
collectionView?.alwaysBounceVertical = true
collectionView?.contentInset = UIEdgeInsets(top: 10, left: 0, bottom: 0, right: 0)
collectionView?.backgroundColor = UIColor(white: 0.95, alpha: 1)
collectionView?.registerClass(FeedCell.self, forCellWithReuseIdentifier: cellId)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return posts.count
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let feedCell = collectionView.dequeueReusableCellWithReuseIdentifier(cellId, forIndexPath: indexPath) as! FeedCell
feedCell.post = posts[indexPath.item]
return feedCell
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
if let statusText = posts[indexPath.item].statusText {
let rect = NSString(string: statusText).boundingRectWithSize(CGSizeMake(view.frame.width, 1000), options: NSStringDrawingOptions.UsesFontLeading.union(NSStringDrawingOptions.UsesLineFragmentOrigin), attributes: [NSFontAttributeName: UIFont.systemFontOfSize(14)], context: nil)
let cellHeight: CGFloat = 40
return CGSizeMake(view.frame.width, rect.height + cellHeight)
}
return CGSizeMake(view.frame.width, 100)
}
}
class FeedCell: UICollectionViewCell {
var post: Post? {
didSet {
if let header = post?.title {
if let extra = post?.nameDate {
let attributedText = NSMutableAttributedString(string: header.trunc(40), attributes: [NSFontAttributeName: UIFont.boldSystemFontOfSize(14)])
attributedText.appendAttributedString(NSAttributedString(string: extra, attributes: [NSFontAttributeName: UIFont.boldSystemFontOfSize(12), NSForegroundColorAttributeName: UIColor(red: 155/255, green: 161/255, blue: 171/255, alpha: 1)]))
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 4
attributedText.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle, range: NSMakeRange(0, attributedText.string.characters.count))
nameLabel.attributedText = attributedText
}
}
if let statusText = post?.statusText {
statusTextView.text = statusText
}
}
}
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
let nameLabel: UILabel = {
let label = UILabel()
label.numberOfLines = 2
return label
}()
let profileImageView: UIImageView = {
let imageView = UIImageView()
imageView.image = UIImage(named: "news_profile")
imageView.contentMode = .ScaleAspectFit
return imageView
}()
let statusTextView: UITextView = {
let textView = UITextView()
textView.scrollEnabled = false
return textView
}()
func setupViews() {
backgroundColor = UIColor.whiteColor()
addSubview(nameLabel)
addSubview(profileImageView)
addSubview(statusTextView)
addConstraintsWithFormat("H:|-8-[v0(44)]-8-[v1]|", views: profileImageView, nameLabel)
addConstraintsWithFormat("H:|-4-[v0]-4-|", views: statusTextView)
addConstraintsWithFormat("V:|-12-[v0]", views: nameLabel)
addConstraintsWithFormat("V:|-8-[v0(44)]-4-[v1]", views: profileImageView, statusTextView)
}
}
Upvotes: 0
Views: 2586
Reputation: 1343
You've already implemented sizeForItemAtIndexPath
. Now you want to keep an array of selected cell indices and modify cellHeight
's value when the indexPath.item is contained within your new array. To do that you'll trigger reloadRowsAtIndexPaths
when someone taps the Show More button.
You can also use this new array in your cellForItemAtIndexPath to change the numberOfLines in your cell if you're currently trimming it.
Upvotes: 3