Skip to content

Commit fed0135

Browse files
committed
Renew demo application
1 parent 09a6ca7 commit fed0135

File tree

11 files changed

+502
-197
lines changed

11 files changed

+502
-197
lines changed

Demo/Sources/AppDelegate.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88

99
import UIKit
1010

11+
import CGFloatLiteral
12+
import ManualLayout
13+
import SnapKit
14+
import SwiftyColor
1115
import Then
1216
import UITextView_Placeholder
1317

@@ -22,9 +26,12 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {
2226
) -> Bool {
2327
let window = UIWindow(frame: UIScreen.main.bounds)
2428
window.backgroundColor = .white
25-
window.rootViewController = UINavigationController(rootViewController: ViewController())
2629
window.makeKeyAndVisible()
2730

31+
let messageListViewController = MessageListViewController()
32+
let navigationController = UINavigationController(rootViewController: messageListViewController)
33+
window.rootViewController = navigationController
34+
2835
self.window = window
2936
return true
3037
}

Demo/Sources/Models/Message.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//
2+
// Message.swift
3+
// RxKeyboard
4+
//
5+
// Created by Suyeol Jeon on 18/01/2017.
6+
// Copyright © 2017 Suyeol Jeon. All rights reserved.
7+
//
8+
9+
struct Message {
10+
var user: User
11+
var text: String
12+
}

Demo/Sources/Models/User.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//
2+
// User.swift
3+
// RxKeyboard
4+
//
5+
// Created by Suyeol Jeon on 18/01/2017.
6+
// Copyright © 2017 Suyeol Jeon. All rights reserved.
7+
//
8+
9+
enum User {
10+
case other
11+
case me
12+
}
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
//
2+
// MessageListViewController.swift
3+
// Demo
4+
//
5+
// Created by Suyeol Jeon on 09/10/2016.
6+
// Copyright © 2016 Suyeol Jeon. All rights reserved.
7+
//
8+
9+
import UIKit
10+
11+
import ReusableKit
12+
import RxKeyboard
13+
import RxSwift
14+
15+
class MessageListViewController: UIViewController {
16+
17+
// MARK: Constants
18+
19+
struct Reusable {
20+
static let messageCell = ReusableCell<MessageCell>()
21+
}
22+
23+
24+
// MARK: Properties
25+
26+
private var didSetupViewConstraints = false
27+
private let disposeBag = DisposeBag()
28+
29+
fileprivate var messages: [Message] = [
30+
Message(user: .other, text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit."),
31+
Message(user: .other, text: "Morbi et eros elementum, semper massa eu, pellentesque sapien."),
32+
Message(user: .me, text: "Aenean sollicitudin justo scelerisque tincidunt venenatis."),
33+
Message(user: .me, text: "Ut mollis magna nec interdum pellentesque."),
34+
Message(user: .me, text: "Aliquam semper nibh nec quam dapibus, a congue odio consequat."),
35+
Message(user: .other, text: "Nullam iaculis nisi in justo feugiat, at pharetra nulla dignissim."),
36+
Message(user: .me, text: "Fusce at nulla luctus, posuere mauris ut, viverra nunc."),
37+
Message(user: .other, text: "Nam feugiat urna non tortor ornare viverra."),
38+
Message(user: .other, text: "Donec vitae metus maximus, efficitur urna ac, blandit erat."),
39+
Message(user: .other, text: "Pellentesque luctus eros ac nisi ullamcorper pharetra nec vel felis."),
40+
Message(user: .me, text: "Duis vulputate magna quis urna porttitor, tempor malesuada metus volutpat."),
41+
Message(user: .me, text: "Duis aliquam urna quis metus tristique eleifend."),
42+
Message(user: .other, text: "Cras quis orci quis nisi vulputate mollis ut vitae magna."),
43+
Message(user: .other, text: "Fusce eu urna eu ipsum laoreet lobortis."),
44+
Message(user: .other, text: "Proin vitae tellus nec odio consequat varius ac non orci."),
45+
Message(user: .me, text: "Maecenas gravida arcu ut consectetur tincidunt."),
46+
Message(user: .me, text: "Quisque accumsan nisl ut ipsum rutrum, nec rutrum magna lobortis."),
47+
Message(user: .other, text: "Integer ac sem eu velit tincidunt hendrerit a in dui."),
48+
Message(user: .other, text: "Duis posuere arcu convallis tincidunt faucibus."),
49+
]
50+
51+
52+
// MARK: UI
53+
54+
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()).then {
55+
$0.alwaysBounceVertical = true
56+
$0.keyboardDismissMode = .interactive
57+
$0.backgroundColor = .clear
58+
$0.register(Reusable.messageCell)
59+
($0.collectionViewLayout as? UICollectionViewFlowLayout)?.do {
60+
$0.minimumLineSpacing = 6
61+
$0.sectionInset.top = 10
62+
$0.sectionInset.bottom = 10
63+
}
64+
}
65+
let messageInputBar = MessageInputBar()
66+
67+
68+
// MARK: Initializing
69+
70+
init() {
71+
super.init(nibName: nil, bundle: nil)
72+
self.title = "RxKeyboard Demo"
73+
}
74+
75+
required init?(coder aDecoder: NSCoder) {
76+
fatalError("init(coder:) has not been implemented")
77+
}
78+
79+
override func viewDidLoad() {
80+
super.viewDidLoad()
81+
self.view.addSubview(self.collectionView)
82+
self.view.addSubview(self.messageInputBar)
83+
84+
self.collectionView.dataSource = self
85+
self.collectionView.delegate = self
86+
87+
DispatchQueue.main.async {
88+
let indexPath = IndexPath(item: self.messages.count - 1, section: 0)
89+
self.collectionView.scrollToItem(at: indexPath, at: [], animated: true)
90+
}
91+
92+
RxKeyboard.instance.visibleHeight
93+
.drive(onNext: { [weak self] keyboardVisibleHeight in
94+
guard let `self` = self, self.didSetupViewConstraints else { return }
95+
self.messageInputBar.snp.updateConstraints { make in
96+
make.bottom.equalTo(self.bottomLayoutGuide.snp.top).offset(-keyboardVisibleHeight)
97+
}
98+
self.view.setNeedsLayout()
99+
UIView.animate(withDuration: 0) {
100+
self.collectionView.contentInset.bottom = keyboardVisibleHeight + self.messageInputBar.height
101+
self.collectionView.scrollIndicatorInsets.bottom = self.collectionView.contentInset.bottom
102+
self.view.layoutIfNeeded()
103+
}
104+
})
105+
.addDisposableTo(self.disposeBag)
106+
107+
RxKeyboard.instance.willShowVisibleHeight
108+
.drive(onNext: { keyboardVisibleHeight in
109+
self.collectionView.contentOffset.y += keyboardVisibleHeight
110+
})
111+
.addDisposableTo(self.disposeBag)
112+
113+
self.messageInputBar.rx.sendButtonTap
114+
.subscribe(onNext: { [weak self] text in
115+
guard let `self` = self else { return }
116+
let message = Message(user: .me, text: text)
117+
self.messages.append(message)
118+
let indexPath = IndexPath(item: self.messages.count - 1, section: 0)
119+
self.collectionView.insertItems(at: [indexPath])
120+
self.collectionView.scrollToItem(at: indexPath, at: [], animated: true)
121+
})
122+
.addDisposableTo(self.disposeBag)
123+
}
124+
125+
126+
// MARK: Auto Layout
127+
128+
override func updateViewConstraints() {
129+
super.updateViewConstraints()
130+
guard !self.didSetupViewConstraints else { return }
131+
self.didSetupViewConstraints = true
132+
133+
self.collectionView.snp.makeConstraints { make in
134+
make.edges.equalTo(0)
135+
}
136+
self.messageInputBar.snp.makeConstraints { make in
137+
make.left.right.equalTo(0)
138+
make.bottom.equalTo(self.bottomLayoutGuide.snp.top)
139+
}
140+
}
141+
142+
override func viewDidLayoutSubviews() {
143+
super.viewDidLayoutSubviews()
144+
if self.collectionView.contentInset.bottom == 0 {
145+
self.collectionView.contentInset.bottom = self.messageInputBar.height
146+
self.collectionView.scrollIndicatorInsets.bottom = self.collectionView.contentInset.bottom
147+
}
148+
}
149+
150+
}
151+
152+
153+
// MARK: - UICollectionViewDataSource
154+
155+
extension MessageListViewController: UICollectionViewDataSource {
156+
157+
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
158+
return self.messages.count
159+
}
160+
161+
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
162+
let cell = collectionView.dequeue(Reusable.messageCell, for: indexPath)
163+
cell.configure(message: self.messages[indexPath.item])
164+
return cell
165+
}
166+
167+
}
168+
169+
170+
// MARK: - UICollectionViewDelegateFlowLayout
171+
172+
extension MessageListViewController: UICollectionViewDelegateFlowLayout {
173+
174+
func collectionView(
175+
_ collectionView: UICollectionView,
176+
layout collectionViewLayout: UICollectionViewLayout,
177+
sizeForItemAt indexPath: IndexPath
178+
) -> CGSize {
179+
let message = self.messages[indexPath.item]
180+
return MessageCell.size(thatFitsWidth: collectionView.width, forMessage: message)
181+
}
182+
183+
}

0 commit comments

Comments
 (0)