mirror of
https://github.com/Ranchero-Software/NetNewsWire
synced 2025-08-12 06:26:36 +00:00
Port TimelineAvatarView to iOS
This commit is contained in:
101
iOS/MasterTimeline/Cell/MasterTimelineAvatarView.swift
Normal file
101
iOS/MasterTimeline/Cell/MasterTimelineAvatarView.swift
Normal file
@@ -0,0 +1,101 @@
|
||||
//
|
||||
// MasterTimelineAvatarView.swift
|
||||
// NetNewsWire-iOS
|
||||
//
|
||||
// Created by Maurice Parker on 9/17/19.
|
||||
// Copyright © 2019 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
final class MasterTimelineAvatarView: UIView {
|
||||
|
||||
var image: UIImage? = nil {
|
||||
didSet {
|
||||
if image !== oldValue {
|
||||
imageView.image = image
|
||||
setNeedsLayout()
|
||||
setNeedsDisplay()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private let imageView: UIImageView = {
|
||||
let imageView = NonIntrinsicImageView(image: AppAssets.feedImage)
|
||||
imageView.contentMode = .scaleAspectFit
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private var hasExposedVerticalBackground: Bool {
|
||||
return imageView.frame.size.height < bounds.size.height
|
||||
}
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
commonInit()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
commonInit()
|
||||
}
|
||||
|
||||
convenience init() {
|
||||
self.init(frame: .zero)
|
||||
}
|
||||
|
||||
override func didMoveToSuperview() {
|
||||
setNeedsLayout()
|
||||
setNeedsDisplay()
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
imageView.setFrameIfNotEqual(rectForImageView())
|
||||
}
|
||||
|
||||
override func draw(_ dirtyRect: CGRect) {
|
||||
if hasExposedVerticalBackground {
|
||||
AppAssets.avatarBackgroundColor.set()
|
||||
} else {
|
||||
UIColor.clear.set()
|
||||
}
|
||||
UIRectFill(dirtyRect)
|
||||
}
|
||||
}
|
||||
|
||||
private extension MasterTimelineAvatarView {
|
||||
|
||||
func commonInit() {
|
||||
addSubview(imageView)
|
||||
}
|
||||
|
||||
func rectForImageView() -> CGRect {
|
||||
guard let image = image else {
|
||||
return CGRect.zero
|
||||
}
|
||||
|
||||
let imageSize = image.size
|
||||
let viewSize = bounds.size
|
||||
if imageSize.height == imageSize.width {
|
||||
if imageSize.height >= viewSize.height * 0.75 {
|
||||
// Close enough to viewSize to scale up the image.
|
||||
return CGRect(x: 0.0, y: 0.0, width: viewSize.width, height: viewSize.height)
|
||||
}
|
||||
let offset = floor((viewSize.height - imageSize.height) / 2.0)
|
||||
return CGRect(x: offset, y: offset, width: imageSize.width, height: imageSize.height)
|
||||
}
|
||||
else if imageSize.height > imageSize.width {
|
||||
let factor = viewSize.height / imageSize.height
|
||||
let width = imageSize.width * factor
|
||||
let originX = floor((viewSize.width - width) / 2.0)
|
||||
return CGRect(x: originX, y: 0.0, width: width, height: viewSize.height)
|
||||
}
|
||||
|
||||
// Wider than tall: imageSize.width > imageSize.height
|
||||
let factor = viewSize.width / imageSize.width
|
||||
let height = imageSize.height * factor
|
||||
let originY = floor((viewSize.height - height) / 2.0)
|
||||
return CGRect(x: 0.0, y: originY, width: viewSize.width, height: height)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,11 +17,7 @@ class MasterTimelineTableViewCell: NNWTableViewCell {
|
||||
private let dateView = MasterTimelineTableViewCell.singleLineUILabel()
|
||||
private let feedNameView = MasterTimelineTableViewCell.singleLineUILabel()
|
||||
|
||||
private lazy var avatarImageView: UIImageView = {
|
||||
let imageView = NonIntrinsicImageView(image: AppAssets.feedImage)
|
||||
imageView.contentMode = .scaleAspectFit
|
||||
return imageView
|
||||
}()
|
||||
private lazy var avatarView = MasterTimelineAvatarView()
|
||||
|
||||
private lazy var starView = {
|
||||
return NonIntrinsicImageView(image: AppAssets.timelineStarImage)
|
||||
@@ -78,7 +74,7 @@ class MasterTimelineTableViewCell: NNWTableViewCell {
|
||||
|
||||
unreadIndicatorView.setFrameIfNotEqual(layout.unreadIndicatorRect)
|
||||
starView.setFrameIfNotEqual(layout.starRect)
|
||||
avatarImageView.setFrameIfNotEqual(layout.avatarImageRect)
|
||||
avatarView.setFrameIfNotEqual(layout.avatarImageRect)
|
||||
setFrame(for: titleView, rect: layout.titleRect)
|
||||
setFrame(for: summaryView, rect: layout.summaryRect)
|
||||
feedNameView.setFrameIfNotEqual(layout.feedNameRect)
|
||||
@@ -89,7 +85,7 @@ class MasterTimelineTableViewCell: NNWTableViewCell {
|
||||
}
|
||||
|
||||
func setAvatarImage(_ image: UIImage) {
|
||||
avatarImageView.image = image
|
||||
avatarView.image = image
|
||||
}
|
||||
|
||||
}
|
||||
@@ -140,7 +136,7 @@ private extension MasterTimelineTableViewCell {
|
||||
addSubviewAtInit(unreadIndicatorView, hidden: true)
|
||||
addSubviewAtInit(dateView, hidden: false)
|
||||
addSubviewAtInit(feedNameView, hidden: true)
|
||||
addSubviewAtInit(avatarImageView, hidden: true)
|
||||
addSubviewAtInit(avatarView, hidden: true)
|
||||
addSubviewAtInit(starView, hidden: true)
|
||||
|
||||
}
|
||||
@@ -211,23 +207,23 @@ private extension MasterTimelineTableViewCell {
|
||||
return
|
||||
}
|
||||
|
||||
showView(avatarImageView)
|
||||
avatarImageView.layer.cornerRadius = MasterTimelineDefaultCellLayout.avatarCornerRadius
|
||||
avatarImageView.clipsToBounds = true
|
||||
showView(avatarView)
|
||||
avatarView.layer.cornerRadius = MasterTimelineDefaultCellLayout.avatarCornerRadius
|
||||
avatarView.clipsToBounds = true
|
||||
|
||||
if avatarImageView.image !== cellData.avatar {
|
||||
avatarImageView.image = image
|
||||
if avatarView.image !== cellData.avatar {
|
||||
avatarView.image = image
|
||||
setNeedsLayout()
|
||||
}
|
||||
}
|
||||
|
||||
func makeAvatarEmpty() {
|
||||
|
||||
if avatarImageView.image != nil {
|
||||
avatarImageView.image = nil
|
||||
if avatarView.image != nil {
|
||||
avatarView.image = nil
|
||||
setNeedsLayout()
|
||||
}
|
||||
hideView(avatarImageView)
|
||||
hideView(avatarView)
|
||||
}
|
||||
|
||||
func hideView(_ view: UIView) {
|
||||
|
||||
Reference in New Issue
Block a user