Skip to content

Instantly share code, notes, and snippets.

@KirillovE
Created June 26, 2018 10:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KirillovE/b14d83115985f328c295f82e6b0f823d to your computer and use it in GitHub Desktop.
Save KirillovE/b14d83115985f328c295f82e6b0f823d to your computer and use it in GitHub Desktop.
Ручная вёрстка. Здесь расставляются элементы на экране, которые смещаются в определённых случаях
//
// NewsCell.swift
// newVK
//
// Created by Евгений Кириллов on 25.03.2018.
// Copyright © 2018 Триада. All rights reserved.
//
import UIKit
class NewsCell: UITableViewCell {
// MARK: - Outlets
@IBOutlet weak var avatar: UIImageView!
@IBOutlet weak private var authorName: UILabel!
@IBOutlet weak private var newsText: UILabel!
@IBOutlet weak private var numberOfViews: UILabel!
@IBOutlet weak private var numberOfReposts: UILabel!
@IBOutlet weak private var numberOfComments: UILabel!
@IBOutlet weak private var numberOfLikes: UILabel!
@IBOutlet weak private var date: UILabel!
@IBOutlet weak var attachedImage: UIImageView!
// MARK: - Source data
private let inset: CGFloat = 15
private let insetBetweenObjects: CGFloat = 5
private var nameDateOriginX: CGFloat = 0
private let attributeImageSize = CGSize(width: 15, height: 15)
private var attributeOriginY: CGFloat = 0
private var attachedImageAspectRatio: Double?
private let formatter = Formatting()
weak var heightDelegate: CellHeightDelegate?
var index: IndexPath?
// MARK: - Methods
override func awakeFromNib() {
super.awakeFromNib()
[avatar, authorName, newsText, numberOfViews, numberOfReposts, numberOfComments, numberOfLikes, date, attachedImage].forEach { $0.translatesAutoresizingMaskIntoConstraints = false }
nameDateOriginX = inset + avatar.frame.width + insetBetweenObjects
}
override func layoutSubviews() {
super.layoutSubviews()
avatarFrame()
authorNameFrame()
dateFrame()
newsTextFrame()
likeImageFrame()
likeCountFrame()
commentsImageFrame()
commentsCountFrame()
repostsImageFrame()
repostsCountFrame()
viewsImageFrame()
viewsCountFrame()
}
func configure(for news: News) {
setAuthorName(news.name)
setNewsText(news.text)
setViews(news.viewsCount)
setReposts(news.reposts.count)
setComments(news.comments.count)
setLikes(news.likes.count)
setDate("\(news.time) \(news.day)")
attachedImageAspectRatio = nil
if news.attachedImageURL != "" {
attachedImageAspectRatio = news.attachedImageWidth / news.attachedImageHeight
}
attachedImage.image = #imageLiteral(resourceName: "заглушка")
attachedImageFrame()
guard let index = index,
let height = getCellHeight(),
bounds.height != height else { return }
heightDelegate?.setHeight(height, to: index)
avatar.image = #imageLiteral(resourceName: "заглушка")
if news.sourceID < 0 {
avatar.layer.cornerRadius = avatar.frame.size.height / 4
} else {
avatar.layer.cornerRadius = avatar.frame.size.height / 2
}
}
}
// MARK: - Setting frames
extension NewsCell {
private func setAuthorName(_ name: String) {
authorName.text = name
authorNameFrame()
}
private func setDate(_ timeDate: String) {
date.text = timeDate
dateFrame()
}
private func setNewsText(_ text: String) {
newsText.text = text
newsTextFrame()
}
private func setLikes(_ count: Int) {
numberOfLikes.text = formatter.formatInt(count)
likeCountFrame()
}
private func setComments(_ count: Int) {
numberOfComments.text = formatter.formatInt(count)
commentsCountFrame()
}
private func setReposts(_ count: Int) {
numberOfReposts.text = formatter.formatInt(count)
repostsCountFrame()
}
private func setViews(_ count: Int) {
numberOfViews.text = formatter.formatInt(count)
viewsCountFrame()
}
}
// MARK: - Main frames
extension NewsCell {
private func avatarFrame() {
let avatarSideSize: CGFloat = 45
let avatarSize = CGSize(width: avatarSideSize, height: avatarSideSize)
let avatarOrigin = CGPoint(x: inset, y: inset)
avatar.frame = CGRect(origin: avatarOrigin, size: avatarSize)
}
private func authorNameFrame() {
var labelSize = getLabelSize(text: authorName.text!, font: authorName.font)
labelSize.height = 20 // высота для данного конкретного случая, взята из storyboard,
// без этого длинные названия смещаются ниже, что портит общую картину
let labelOrigin = CGPoint(x: nameDateOriginX, y: inset)
authorName.frame = CGRect(origin: labelOrigin, size: labelSize)
}
private func dateFrame() {
let labelSize = getLabelSize(text: date.text!, font: date.font)
let labelY = inset + avatar.frame.height - labelSize.height
let labelOrigin = CGPoint(x: nameDateOriginX, y: labelY)
date.frame = CGRect(origin: labelOrigin, size: labelSize)
}
private func newsTextFrame() {
let labelSize = getLabelSize(text: newsText.text!, font: newsText.font)
let labelY = inset + avatar.frame.height + insetBetweenObjects
let labelOrigin = CGPoint(x: inset, y: labelY)
newsText.frame = CGRect(origin: labelOrigin, size: labelSize)
}
private func attachedImageFrame() {
let imageSize: CGSize
let imageViewY = newsText.frame.origin.y + newsText.frame.height + insetBetweenObjects
let imageViewOrigin = CGPoint(x: 0, y: imageViewY)
if let aspectRatio = attachedImageAspectRatio {
let imageWidth = bounds.width
let imageHeight = imageWidth / CGFloat(aspectRatio)
imageSize = CGSize(width: imageWidth, height: ceil(imageHeight))
attachedImage.frame = CGRect(origin: imageViewOrigin, size: imageSize)
attributeOriginY = attachedImage.frame.origin.y + attachedImage.frame.height + insetBetweenObjects
} else {
imageSize = CGSize.zero
attachedImage.frame = CGRect(origin: imageViewOrigin, size: imageSize)
attributeOriginY = attachedImage.frame.origin.y
}
}
}
// MARK: - Attributes frames
extension NewsCell {
private func likeImageFrame() {
let labelOrigin = CGPoint(x: inset, y: attributeOriginY)
viewWithTag(1)?.frame = CGRect(origin: labelOrigin, size: attributeImageSize)
}
private func likeCountFrame() {
let labelSize = getLabelSize(text: numberOfLikes.text!, font: numberOfLikes.font)
let labelX = (viewWithTag(1)?.frame.origin.x)! + (viewWithTag(1)?.frame.width)!
let labelOrigin = CGPoint(x: labelX, y: attributeOriginY)
numberOfLikes.frame = CGRect(origin: labelOrigin, size: labelSize)
}
private func commentsImageFrame() {
let labelX = numberOfLikes.frame.origin.x + numberOfLikes.frame.width + insetBetweenObjects
let labelOrigin = CGPoint(x: labelX, y: attributeOriginY)
viewWithTag(2)?.frame = CGRect(origin: labelOrigin, size: attributeImageSize)
}
private func commentsCountFrame() {
let labelSize = getLabelSize(text: numberOfComments.text!, font: numberOfComments.font)
let labelX = (viewWithTag(2)?.frame.origin.x)! + (viewWithTag(2)?.frame.width)!
let labelOrigin = CGPoint(x: labelX, y: attributeOriginY)
numberOfComments.frame = CGRect(origin: labelOrigin, size: labelSize)
}
private func repostsImageFrame() {
let labelX = numberOfComments.frame.origin.x + numberOfComments.frame.width + insetBetweenObjects
let labelOrigin = CGPoint(x: labelX, y: attributeOriginY)
viewWithTag(3)?.frame = CGRect(origin: labelOrigin, size: attributeImageSize)
}
private func repostsCountFrame() {
let labelSize = getLabelSize(text: numberOfReposts.text!, font: numberOfReposts.font)
let labelX = (viewWithTag(3)?.frame.origin.x)! + (viewWithTag(3)?.frame.width)!
let labelOrigin = CGPoint(x: labelX, y: attributeOriginY)
numberOfReposts.frame = CGRect(origin: labelOrigin, size: labelSize)
}
private func viewsImageFrame() {
let labelX = numberOfReposts.frame.origin.x + numberOfReposts.frame.width + insetBetweenObjects
let labelOrigin = CGPoint(x: labelX, y: attributeOriginY)
viewWithTag(4)?.frame = CGRect(origin: labelOrigin, size: attributeImageSize)
}
private func viewsCountFrame() {
let labelSize = getLabelSize(text: numberOfViews.text!, font: numberOfViews.font)
let labelX = (viewWithTag(4)?.frame.origin.x)! + (viewWithTag(4)?.frame.width)!
let labelOrigin = CGPoint(x: labelX, y: attributeOriginY)
numberOfViews.frame = CGRect(origin: labelOrigin, size: labelSize)
}
}
// MARK: - Service extension
extension NewsCell {
private func getLabelSize(text: String, font: UIFont) -> CGSize {
let maxWidth = bounds.width - inset * 2
let textBlock = CGSize(width: maxWidth, height: CGFloat.greatestFiniteMagnitude)
let rect = text.boundingRect(with: textBlock, options: .usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font: font], context: nil)
let width = Double(rect.size.width)
let height = Double(rect.size.height)
let size = CGSize(width: ceil(width), height: ceil(height))
return size
}
private func getCellHeight() -> CGFloat? {
var heigth = 2 * inset + 2 * insetBetweenObjects + avatar.frame.height + newsText.frame.height + numberOfLikes.frame.height
let attachedImageHeight = attachedImage.frame.height
if attachedImageHeight != 0 {
heigth += attachedImageHeight + insetBetweenObjects
}
return heigth
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment