mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-10 07:13:28 +01:00
XCode project for app, moved app project to folder
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
//
|
||||
// CollapsingTextView.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 7/23/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
final class CollapsingTextView: UITextView {
|
||||
var isCollapsed = true {
|
||||
didSet {
|
||||
setNeedsLayout()
|
||||
}
|
||||
}
|
||||
|
||||
var maximumNumberOfLines = 2 {
|
||||
didSet {
|
||||
setNeedsLayout()
|
||||
}
|
||||
}
|
||||
|
||||
var lineSpacing: CGFloat = 2 {
|
||||
didSet {
|
||||
setNeedsLayout()
|
||||
}
|
||||
}
|
||||
|
||||
let moreButton = UIButton(type: .system)
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
|
||||
layoutManager.delegate = self
|
||||
|
||||
textContainerInset = .zero
|
||||
textContainer.lineFragmentPadding = 0
|
||||
textContainer.lineBreakMode = .byTruncatingTail
|
||||
textContainer.heightTracksTextView = true
|
||||
textContainer.widthTracksTextView = true
|
||||
|
||||
moreButton.setTitle(NSLocalizedString("More", comment: ""), for: .normal)
|
||||
moreButton.addTarget(self, action: #selector(CollapsingTextView.toggleCollapsed(_:)), for: .primaryActionTriggered)
|
||||
addSubview(moreButton)
|
||||
|
||||
setNeedsLayout()
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
guard let font = font else { return }
|
||||
|
||||
let buttonFont = UIFont.systemFont(ofSize: font.pointSize, weight: .medium)
|
||||
moreButton.titleLabel?.font = buttonFont
|
||||
|
||||
let buttonY = (font.lineHeight + lineSpacing) * CGFloat(maximumNumberOfLines - 1)
|
||||
let size = moreButton.sizeThatFits(CGSize(width: 1000, height: 1000))
|
||||
|
||||
let moreButtonFrame = CGRect(x: bounds.width - moreButton.bounds.width,
|
||||
y: buttonY,
|
||||
width: size.width,
|
||||
height: font.lineHeight)
|
||||
moreButton.frame = moreButtonFrame
|
||||
|
||||
if isCollapsed {
|
||||
textContainer.maximumNumberOfLines = maximumNumberOfLines
|
||||
|
||||
let boundingSize = attributedText.boundingRect(with: CGSize(width: textContainer.size.width, height: .infinity), options: [.usesLineFragmentOrigin, .usesFontLeading], context: nil)
|
||||
let maximumCollapsedHeight = font.lineHeight * Double(maximumNumberOfLines)
|
||||
|
||||
if boundingSize.height.rounded() > maximumCollapsedHeight.rounded() {
|
||||
var exclusionFrame = moreButtonFrame
|
||||
exclusionFrame.origin.y += moreButton.bounds.midY
|
||||
exclusionFrame.size.width = bounds.width // Extra wide to make sure it wraps to next line.
|
||||
textContainer.exclusionPaths = [UIBezierPath(rect: exclusionFrame)]
|
||||
|
||||
moreButton.isHidden = false
|
||||
} else {
|
||||
textContainer.exclusionPaths = []
|
||||
|
||||
moreButton.isHidden = true
|
||||
}
|
||||
} else {
|
||||
textContainer.maximumNumberOfLines = 0
|
||||
textContainer.exclusionPaths = []
|
||||
|
||||
moreButton.isHidden = true
|
||||
}
|
||||
|
||||
invalidateIntrinsicContentSize()
|
||||
}
|
||||
}
|
||||
|
||||
private extension CollapsingTextView {
|
||||
@objc func toggleCollapsed(_: UIButton) {
|
||||
isCollapsed.toggle()
|
||||
}
|
||||
}
|
||||
|
||||
extension CollapsingTextView: NSLayoutManagerDelegate {
|
||||
func layoutManager(_: NSLayoutManager, lineSpacingAfterGlyphAt _: Int, withProposedLineFragmentRect _: CGRect) -> CGFloat {
|
||||
lineSpacing
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user