|
|
|
@ -11,6 +11,9 @@ public class PlayerView: UIView { |
|
|
|
private let langRow: UIStackView = UIStackView() |
|
|
|
private var lastBoundsSize: CGSize = .zero |
|
|
|
private var lastLangText: String? = nil |
|
|
|
private var isExpanded: Bool = false |
|
|
|
private let compactPreferredHeight: CGFloat = 72 |
|
|
|
private let expandedPreferredHeight: CGFloat = 220 |
|
|
|
|
|
|
|
public override init(frame: CGRect) { |
|
|
|
stackView = UIStackView() |
|
|
|
@ -73,12 +76,14 @@ public class PlayerView: UIView { |
|
|
|
cnLabel.textAlignment = .left |
|
|
|
cnLabel.numberOfLines = 0 |
|
|
|
cnLabel.lineBreakMode = .byTruncatingTail |
|
|
|
cnLabel.isHidden = true |
|
|
|
|
|
|
|
enLabel.font = .systemFont(ofSize: 15) |
|
|
|
enLabel.textColor = UIColor(red: 144.0 / 255.0, green: 202.0 / 255.0, blue: 249.0 / 255.0, alpha: 1.0) |
|
|
|
enLabel.textAlignment = .left |
|
|
|
enLabel.numberOfLines = 0 |
|
|
|
enLabel.lineBreakMode = .byTruncatingTail |
|
|
|
enLabel.isHidden = true |
|
|
|
|
|
|
|
let para = NSMutableParagraphStyle() |
|
|
|
para.lineSpacing = 2 |
|
|
|
@ -110,7 +115,7 @@ public class PlayerView: UIView { |
|
|
|
stackView.addArrangedSubview(cnLabel) |
|
|
|
stackView.addArrangedSubview(enLabel) |
|
|
|
|
|
|
|
layoutMargins = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16) |
|
|
|
layoutMargins = UIEdgeInsets(top: 10, left: 16, bottom: 10, right: 16) |
|
|
|
addSubview(stackView) |
|
|
|
|
|
|
|
let guide = layoutMarginsGuide |
|
|
|
@ -141,11 +146,22 @@ public class PlayerView: UIView { |
|
|
|
if let en = en { |
|
|
|
enLabel.attributedText = NSAttributedString(string: en, attributes: [.paragraphStyle: para]) |
|
|
|
} |
|
|
|
let currentCn = cnLabel.attributedText?.string ?? "" |
|
|
|
let currentEn = enLabel.attributedText?.string ?? "" |
|
|
|
let hasContent = |
|
|
|
!currentCn.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty |
|
|
|
|| !currentEn.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty |
|
|
|
setExpanded(hasContent) |
|
|
|
setNeedsLayout() |
|
|
|
} |
|
|
|
|
|
|
|
public override var intrinsicContentSize: CGSize { |
|
|
|
CGSize(width: UIView.noIntrinsicMetric, height: isExpanded ? expandedPreferredHeight : compactPreferredHeight) |
|
|
|
} |
|
|
|
|
|
|
|
public override func layoutSubviews() { |
|
|
|
super.layoutSubviews() |
|
|
|
layer.cornerRadius = isExpanded ? 16 : 18 |
|
|
|
layer.shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: layer.cornerRadius).cgPath |
|
|
|
let currentLangText = langLabel.text |
|
|
|
if bounds.size != lastBoundsSize || currentLangText != lastLangText { |
|
|
|
@ -155,6 +171,17 @@ public class PlayerView: UIView { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private func setExpanded(_ expanded: Bool) { |
|
|
|
if expanded == isExpanded { return } |
|
|
|
isExpanded = expanded |
|
|
|
cnLabel.isHidden = !expanded |
|
|
|
enLabel.isHidden = !expanded |
|
|
|
layoutMargins = expanded |
|
|
|
? UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16) |
|
|
|
: UIEdgeInsets(top: 10, left: 16, bottom: 10, right: 16) |
|
|
|
invalidateIntrinsicContentSize() |
|
|
|
} |
|
|
|
|
|
|
|
private func updateDynamicTextLineLimit() { |
|
|
|
let fittingWidth = max(0, bounds.width - layoutMargins.left - layoutMargins.right) |
|
|
|
if fittingWidth <= 0 { return } |
|
|
|
@ -182,7 +209,7 @@ public class PlayerView: UIView { |
|
|
|
let enLineHeight = enLabel.font.lineHeight * 1.1 + 2 |
|
|
|
let combinedLineHeight = cnLineHeight + enLineHeight |
|
|
|
|
|
|
|
let perLabelLines = max(1, min(Int(availableHeight / combinedLineHeight), 6)) |
|
|
|
let perLabelLines = max(1, min(Int(availableHeight / combinedLineHeight), 10)) |
|
|
|
|
|
|
|
if perLabelLines != lastDynamicTextLines { |
|
|
|
lastDynamicTextLines = perLabelLines |
|
|
|
|