Skip to content

Commit b163042

Browse files
committed
Demo增加视图附件演示, 优化代码结构, 大量视图附件时 布局处理待优化
1 parent 12eb5c4 commit b163042

File tree

7 files changed

+372
-88
lines changed

7 files changed

+372
-88
lines changed

Demo/Demo.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
9B6E89D623828178009EBEBE /* AttributedString.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9B6E89D423828178009EBEBE /* AttributedString.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
2121
9B74C1AE24A83A7100242418 /* CheckingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B74C1AD24A83A7100242418 /* CheckingViewController.swift */; };
2222
9B74C1B024A83D9A00242418 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B74C1AF24A83D9A00242418 /* ViewController.swift */; };
23+
9BB7011724B5C9360018DD68 /* VideoPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BB7011624B5C9360018DD68 /* VideoPlayerView.swift */; };
2324
9BD90EFE23840402000DBD29 /* FontViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BD90EFD23840402000DBD29 /* FontViewController.swift */; };
2425
9BD90F00238404C9000DBD29 /* ForegroundColorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BD90EFF238404C9000DBD29 /* ForegroundColorViewController.swift */; };
2526
9BD90F02238404D5000DBD29 /* BackgroundColorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BD90F01238404D5000DBD29 /* BackgroundColorViewController.swift */; };
@@ -68,6 +69,7 @@
6869
9B6E89D423828178009EBEBE /* AttributedString.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = AttributedString.framework; sourceTree = BUILT_PRODUCTS_DIR; };
6970
9B74C1AD24A83A7100242418 /* CheckingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckingViewController.swift; sourceTree = "<group>"; };
7071
9B74C1AF24A83D9A00242418 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
72+
9BB7011624B5C9360018DD68 /* VideoPlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerView.swift; sourceTree = "<group>"; };
7173
9BD90EFD23840402000DBD29 /* FontViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FontViewController.swift; sourceTree = "<group>"; };
7274
9BD90EFF238404C9000DBD29 /* ForegroundColorViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForegroundColorViewController.swift; sourceTree = "<group>"; };
7375
9BD90F01238404D5000DBD29 /* BackgroundColorViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundColorViewController.swift; sourceTree = "<group>"; };
@@ -129,6 +131,7 @@
129131
9B6E899423823F48009EBEBE /* LaunchScreen.storyboard */,
130132
9B6E899723823F48009EBEBE /* Info.plist */,
131133
9B74C1AF24A83D9A00242418 /* ViewController.swift */,
134+
9BB7011624B5C9360018DD68 /* VideoPlayerView.swift */,
132135
);
133136
path = Demo;
134137
sourceTree = "<group>";
@@ -259,6 +262,7 @@
259262
9B1C4964238405A7002CDC4B /* ParagraphStyleViewController.swift in Sources */,
260263
9BD90F1223840540000DBD29 /* StrokeViewController.swift in Sources */,
261264
9B6E898A23823F47009EBEBE /* AppDelegate.swift in Sources */,
265+
9BB7011724B5C9360018DD68 /* VideoPlayerView.swift in Sources */,
262266
9BD90F1A2384056F000DBD29 /* WritingDirectionViewController.swift in Sources */,
263267
9B1C49662384065D002CDC4B /* AttachmentViewController.swift in Sources */,
264268
9BD90F00238404C9000DBD29 /* ForegroundColorViewController.swift in Sources */,

Demo/Demo/Base.lproj/Main.storyboard

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
<rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
1717
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
1818
<subviews>
19-
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" translatesAutoresizingMaskIntoConstraints="NO" id="M9o-2j-0MG">
19+
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" delaysContentTouches="NO" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" translatesAutoresizingMaskIntoConstraints="NO" id="M9o-2j-0MG">
2020
<rect key="frame" x="0.0" y="88" width="375" height="641"/>
2121
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
2222
<prototypes>
@@ -1594,7 +1594,7 @@
15941594

15951595
This is a picture -&gt; \(.image(#imageLiteral(resourceName: "huaji"))) -&gt; Displayed in original size.
15961596

1597-
This is a picture -&gt; \(.image(#imageLiteral(resourceName: "huaji"), .custom(size: .init(width: 200, height: 200)))) -&gt; Displayed in custom size.
1597+
This is a picture -&gt; \(.image(#imageLiteral(resourceName: "huaji"), .custom(.center, size: .init(width: 50, height: 50)))) -&gt; Displayed in custom size.
15981598

15991599
This is the recommended size image -&gt; \(.image(#imageLiteral(resourceName: "huaji"), .proposed(.center))).
16001600

Demo/Demo/Details/AttachmentViewController.swift

Lines changed: 69 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//
88

99
import UIKit
10+
import AttributedString
1011

1112
class AttachmentViewController: UIViewController {
1213

@@ -15,14 +16,77 @@ class AttachmentViewController: UIViewController {
1516
override func viewDidLoad() {
1617
super.viewDidLoad()
1718

18-
textView.attributed.text = """
19+
let customView = UIView(frame: .init(x: 0, y: 0, width: 100, height: 100))
20+
customView.backgroundColor = .red
1921

20-
This is a picture -> \(.image(#imageLiteral(resourceName: "huaji"))) -> Displayed in original size.
22+
let customImageView = UIImageView(image: #imageLiteral(resourceName: "swift-image-1"))
23+
customImageView.contentMode = .scaleAspectFill
24+
customImageView.sizeToFit()
2125

22-
This is a picture -> \(.image(#imageLiteral(resourceName: "huaji"), .custom(size: .init(width: 200, height: 200)))) -> Displayed in custom size.
26+
let customLabel = UILabel()
27+
customLabel.text = "1234567890"
28+
customLabel.font = .systemFont(ofSize: 30, weight: .medium)
29+
customLabel.backgroundColor = #colorLiteral(red: 0.9568627477, green: 0.6588235497, blue: 0.5450980663, alpha: 1)
30+
customLabel.sizeToFit()
2331

24-
This is the recommended size image -> \(.image(#imageLiteral(resourceName: "huaji"), .proposed(.center)))).
32+
func clicked() {
33+
// 更改自定义视图的大小 (x y 无效)
34+
customView.frame = .init(x: 100, y: 0, width: .random(in: 100 ... 200), height: .random(in: 100 ... 200))
35+
// 更改自定义图片视图的图片
36+
customImageView.image = #imageLiteral(resourceName: "swift-icon")
37+
customImageView.sizeToFit()
38+
// 更改自定义标签的文本
39+
customLabel.text = "45678"
40+
customLabel.sizeToFit()
41+
}
2542

26-
"""
43+
textView.attributed.text = .init(
44+
"""
45+
46+
This is a picture -> \(.image(#imageLiteral(resourceName: "huaji"))) -> Displayed in original size.
47+
48+
This is a picture -> \(.image(#imageLiteral(resourceName: "swift-icon"), .custom(.center, size: .init(width: 50, height: 50)))) -> Displayed in custom size.
49+
50+
This is the recommended size image -> \(.image(#imageLiteral(resourceName: "swift-icon"), .proposed(.center)))).
51+
52+
-----------------------
53+
54+
\("ViewAttachment only support UITextView (以下视图附件仅UITextView支持):", .font(.systemFont(ofSize: 24, weight: .medium)))
55+
56+
\("Change something", .foreground(.blue), .action(clicked))
57+
58+
aaaa\(.view(customView, .original(.center)))aaa
59+
60+
bbbb\(.view(customLabel, .original(.origin)))bbb
61+
62+
cccc\(.view(customImageView, .original(.origin)))ccc
63+
64+
""",
65+
.font(.systemFont(ofSize: 18))
66+
)
67+
68+
var s = AttributedString("")
69+
for i in 0 ... 1000 {
70+
s += AttributedString(
71+
"""
72+
73+
\(i):\(.image(#imageLiteral(resourceName: "swift-icon"), .custom(.center, size: .init(width: 50, height: 50)))).
74+
75+
""")
76+
}
77+
78+
for i in 0 ... 2000 {
79+
let customView = UIView(frame: .init(x: 0, y: 0, width: 100, height: 100))
80+
customView.backgroundColor = .red
81+
82+
s += AttributedString(
83+
"""
84+
85+
\(i):\(.view(customView, .original(.center))).
86+
87+
""")
88+
}
89+
90+
textView.attributed.text = s
2791
}
2892
}

Demo/Demo/SimpleViewController.swift

Lines changed: 99 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//
88

99
import UIKit
10+
import AVKit
1011
import AttributedString
1112

1213
class SimpleViewController: UIViewController {
@@ -15,9 +16,55 @@ class SimpleViewController: UIViewController {
1516

1617
private var list: [Model] = []
1718

18-
override func viewDidLoad() {
19-
super.viewDidLoad()
19+
private let player = AVPlayer(
20+
url: URL(string: "https://devstreaming-cdn.apple.com/videos/wwdc/2020/10648/3/B4DA06E5-8715-4478-B755-EDFF6EC473F9/master.m3u8")!
21+
)
22+
private var playerView: VideoPlayerView = .init()
23+
24+
private func setup() {
25+
tableView.separatorInset = .init(top: 0, left: 10, bottom: 0, right: 10)
26+
}
27+
28+
private func setupPlayer() {
29+
let playerLayer = AVPlayerLayer(player: player)
30+
playerView = VideoPlayerView({ (view) in
31+
view.layer.addSublayer(playerLayer)
32+
})
33+
playerView.observe { (size, animation) in
34+
if let animation = animation {
35+
CATransaction.begin()
36+
CATransaction.setAnimationDuration(animation.duration)
37+
CATransaction.setAnimationTimingFunction(animation.timingFunction)
38+
playerLayer.frame = .init(origin: .zero, size: size)
39+
CATransaction.commit()
40+
41+
} else {
42+
playerLayer.frame = .init(origin: .zero, size: size)
43+
}
44+
}
45+
playerView.observe { (contentMode) in
46+
switch contentMode {
47+
case .scaleToFill:
48+
playerLayer.videoGravity = .resize
49+
50+
case .scaleAspectFit:
51+
playerLayer.videoGravity = .resizeAspect
52+
53+
case .scaleAspectFill:
54+
playerLayer.videoGravity = .resizeAspectFill
55+
56+
default:
57+
playerLayer.videoGravity = .resizeAspectFill
58+
}
59+
}
60+
playerView.contentMode = .scaleAspectFit
61+
playerView.backgroundColor = .black
2062

63+
// 更新播放视图大小
64+
playerView.frame = .init(x: 0, y: 0, width: view.bounds.width, height: 9 / 16 * view.bounds.width)
65+
}
66+
67+
private func setupAttributedString() {
2168
///
2269
/// .init(
2370
/// """
@@ -74,6 +121,19 @@ class SimpleViewController: UIViewController {
74121
\(.image(#imageLiteral(resourceName: "swift-image-1")))
75122
""",
76123
"""
124+
\("Unsafe Swift", .font(.systemFont(ofSize: 40, weight: .semibold)))
125+
126+
\(
127+
"""
128+
What exactly makes code “unsafe”? Join the Swift team as we take a look at the programming language's safety precautions — and when you might need to reach for unsafe operations. We'll take a look at APIs that can cause unexpected states if not used correctly, and how you can write code more specifically to avoid undefined behavior. Learn how to work with C APIs that use pointers and the steps to take when you want to use Swift's unsafe pointer APIs. To get the most out of this session, you should have some familiarity with Swift and the C programming language. And for more information on working with pointers, check out \"Safely Manage Pointers in Swift\".
129+
""", .font(.systemFont(ofSize: 17))
130+
)
131+
132+
\(.view(playerView))
133+
134+
That's cool! 😎
135+
""",
136+
"""
77137
\("Features:", .font(.systemFont(ofSize: 30, weight: .semibold)))
78138
\("foregroundColor", .foreground(#colorLiteral(red: 0.5568627715, green: 0.3529411852, blue: 0.9686274529, alpha: 1)))
79139
\("backgroundColor", .background(#colorLiteral(red: 0.6642242074, green: 0.6642400622, blue: 0.6642315388, alpha: 1)))
@@ -131,15 +191,46 @@ class SimpleViewController: UIViewController {
131191
"""
132192
]
133193

134-
list = array.map { .init($0) }
194+
let width = UIScreen.main.bounds.width - view.safeAreaInsets.left - view.safeAreaInsets.right - 20
195+
list = array.map { .init($0, width: width) }
196+
tableView.reloadData()
197+
}
198+
199+
private func reload() {
200+
// 更新播放视图大小
201+
playerView.frame = .init(x: 0, y: 0, width: view.bounds.width, height: 9 / 16 * view.bounds.width)
202+
// 获取最大宽度 重新设置内容
203+
let width = UIScreen.main.bounds.width - view.safeAreaInsets.left - view.safeAreaInsets.right - 20
204+
list = list.map { .init($0.content, width: width) }
135205
tableView.reloadData()
136206
}
137207

208+
override func viewDidLoad() {
209+
super.viewDidLoad()
210+
211+
setup()
212+
setupPlayer()
213+
setupAttributedString()
214+
}
215+
216+
override func viewDidAppear(_ animated: Bool) {
217+
super.viewDidAppear(animated)
218+
player.play()
219+
}
220+
221+
override func viewDidDisappear(_ animated: Bool) {
222+
super.viewDidDisappear(animated)
223+
player.pause()
224+
}
225+
226+
override func viewSafeAreaInsetsDidChange() {
227+
super.viewSafeAreaInsetsDidChange()
228+
reload()
229+
}
230+
138231
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
139232
super.traitCollectionDidChange(previousTraitCollection)
140-
141-
list = list.map { .init($0.content) }
142-
tableView.reloadData()
233+
reload()
143234
}
144235
}
145236

@@ -186,11 +277,11 @@ extension SimpleViewController {
186277
let content: AttributedString
187278
let height: CGFloat
188279

189-
init(_ content: AttributedString) {
280+
init(_ content: AttributedString, width: CGFloat) {
190281
self.content = content
191282
self.height = content.value.boundingRect(
192283
with: .init(
193-
width: UIScreen.main.bounds.width - 20,
284+
width: width,
194285
height: .greatestFiniteMagnitude
195286
),
196287
options: [

Demo/Demo/VideoPlayerView.swift

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
//
2+
// VideoPlayerView.swift
3+
// Demo
4+
//
5+
// Created by Lee on 2020/7/8.
6+
// Copyright © 2020 LEE. All rights reserved.
7+
//
8+
9+
import UIKit
10+
11+
class VideoPlayerView: UIView {
12+
13+
private var updateContentMode: ((UIView.ContentMode) -> Void)?
14+
private var updateLayout: ((CGSize, CAAnimation?) -> Void)?
15+
16+
override init(frame: CGRect) {
17+
super.init(frame: frame)
18+
}
19+
20+
init(_ add: (UIView) -> Void) {
21+
super.init(frame: .zero)
22+
clipsToBounds = true
23+
add(self)
24+
}
25+
26+
func observe(contentMode: @escaping ((UIView.ContentMode) -> Void)) {
27+
updateContentMode = { (mode) in
28+
contentMode(mode)
29+
}
30+
updateContentMode?(self.contentMode)
31+
}
32+
33+
func observe(layout: @escaping ((CGSize, CAAnimation?) -> Void)) {
34+
updateLayout = { (size, animation) in
35+
layout(size, animation)
36+
}
37+
layoutSubviews()
38+
}
39+
40+
required init?(coder aDecoder: NSCoder) {
41+
fatalError("init(coder:) has not been implemented")
42+
}
43+
44+
override public var contentMode: UIView.ContentMode {
45+
get {
46+
return super.contentMode
47+
}
48+
set {
49+
super.contentMode = newValue
50+
self.updateContentMode?(newValue)
51+
}
52+
}
53+
54+
override public func layoutSubviews() {
55+
super.layoutSubviews()
56+
57+
updateLayout?(bounds.size, layer.animation(forKey: "bounds.size"))
58+
}
59+
}

0 commit comments

Comments
 (0)