๐ผ ImageSlideshow
ImageSlideshow ์ค์น, ๋ทฐ ์์ฑํ๊ธฐ, ์ด๋ฏธ์ง ๋ฑ๋กํ๋ ๋ฒ์ ์ด์ ํฌ์คํ ์ ์ฐธ๊ณ ํด์ฃผ์ธ์. ํด๋น ํฌ์คํ ์์๋ Label Page Indicator ์ ์ฉํ๋ ๋ฒ, ์ด๋ฏธ์ง ํด๋ฆญ์ ์ ์ฒด ํ๋ฉด์ผ๋ก ์ ํํ๋ ๋ฒ์ ๋ํด ๋ค๋ค๋ณด๊ฒ ์ต๋๋ค.
3. Custom Label Page Indicator ์ ์ฉํ๊ธฐ
๊ธฐ๋ณธ์ผ๋ก ์ ๊ณต๋๋ Label Page Indicator ๋ฅผ ์ด์ฉํ ๊ฒฝ์ฐ, ๊ธฐ์กด ์ฝ๋์์ ๋ค์ ํ ์ค์ ์ถ๊ฐํ๋ฉด ๋ฉ๋๋ค.
slideshow.pageIndicator = LabelPageIndicator()
Github ๋ฌธ์๋, ์ ๋๋ฆฌ๋ ์ ํฌ๋ธ๋ Label Page Indicator ๋ฅผ ๋๋ฑ ์ ์ฉํ์ จ๋๋ฐ์. ์ ๋ ์ด๋ฏธ์ง ์ฌ์ด์ฆ๊ฐ ์์์ ๊ทธ๋ฐ์ง width ์กฐ์ ์ด ์ ์์ ์ผ๋ก ๋์ง ์์ 1/... ์ฒ๋ผ ์๋ ค์ ๋ํ๋ฌ์ต๋๋ค. ๐ฅฒ Label ์ SubView ๋ก ์ ์ฉํ๋ ๋ฐฉ๋ฒ๋ ํด๋ดค๋๋ฐ, ์คํฌ๋กค์ ๋งค๋๋ฝ์ง ์๋๋ผ๊ณ ์. ๊ณ ๋ฏผํ๋ค๊ฐ extension ์ ํตํด LabelPageIndicator ์ ํฐํธ์ฌ์ด์ฆ์ width ๋ฅผ ์ปค์คํ ํ๊ฒ ์ง์ ํด์คฌ์ต๋๋ค.
You can also use your own page indicator by adopting the PageIndicatorView protocol.
import Foundation
import ImageSlideshow
extension LabelPageIndicator {
public func setCustomLabel() {
self.textColor = .white
let systemFont = UIFont.systemFont(ofSize: 12.0)
self.attributedText = NSAttributedString(string: self.text ?? "",
attributes: [NSAttributedString.Key.font : systemFont])
}
public override func sizeToFit() {
let maximumString = String(repeating: "16", count: numberOfPages) as NSString
self.frame.size = maximumString.size(withAttributes: [.font: font as Any])
setCustomLabel()
}
}
์ด๋ฒ์๋ TableView Cell ์์ ImageSlideshow ๋ฅผ ์ด์ฉํ๊ณ , Cell ์์ LabelPageIndicator ์ค์ ์ ํด์ฃผ์์ต๋๋ค. Cell ์ ๊ธฐ๋ณธ UI ์ ๊ด๋ จ๋ ๋์์ด๋ผ ์๊ฐํด์ Cell Class ์์ ์ ์ฉ์ ํ์ต๋๋ค.
class ReviewCell: UITableViewCell {
//...
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code ...
reviewImageSlide.setCornerRadius()
let labelPageIndicator = LabelPageIndicator()
reviewImageSlide.pageIndicator = labelPageIndicator
reviewImageSlide.pageIndicatorPosition = .init(horizontal: .right(padding: 10),
vertical: .customBottom(padding: 10))
}
}
์ด๋ฏธ์ง๋ Cell ๋ง๋ค ๋์ ์ผ๋ก ๋ณํ๊ธฐ ๋๋ฌธ์ TableViewDatasource ๋ด์์ ์ ์ฉํ์ต๋๋ค.
// MARK: TableView - Datasource
extension ReviewTableViewController: UITableViewDataSource {
// ...
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// dequeueReusableCell ...
let imageInputs = FirebaseStorage.getImageInputs(images: images)
cell.reviewImageSlide.setImageInputs(imageInputs)
cell.reviewImageSlide.contentScaleMode = .scaleAspectFill
}
}
์ฌ๊ธฐ๊น์ง ์ ์๋๋๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์ค๋ฅธ์ชฝ ํ๋จ์ Label Page Indicator ๊ฐ ๋ํ๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค! ํด๋น ์ฌ์ง์ ๊ฐ๋ฐ์ค์ธ ์ดํ๊ณผ ๊ด๋ จ์ด ์์ต๋๋ค.
4. Full Screen view ์ ํํ๊ธฐ + Label Page Indicator ์ ์ฉํ๊ธฐ
๊ฐ๋ฐํ๋ ์ ๋๋ฆฌ๋ ์ ํฌ๋ธ๋ฅผ ์ฐธ๊ณ ํ ๋ด์ฉ์ ๋๋ค.
ImageSlideshow ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ด๋ฏธ์ง๋ง ๋ํ๋๋ ์ ์ฒดํ๋ฉด์ ์ ๊ณตํ๊ณ Pinch Zoom ์ ํตํด ํ๋๊ฐ ๊ฐ๋ฅํฉ๋๋ค. ์ง์ ๊ฐ๋ฐํด์ผํ๋ ๋ถ๋ถ์ ์ด๋ฏธ์ง๋ฅผ ํฐ์นํ์ ๋ ์ ์ฒดํ๋ฉด์ด ๋ํ๋๋๋ก ํ๋ ๋ถ๋ถ์ ๋๋ค.
์ด๋ฏธ์ง๋ฅผ ํฐ์นํ๋ ๊ฒ์ด๋๊น UITapGestureRecognizer ๋ฅผ ์ด์ฉํ๋ฉด ๋๊ฒ ์ง์?! Tap Gesture ๋ํ UI ์ค์ ์ ๊ด๋ จ๋๊ฒ์ด๋ผ ์๊ฐํด์ Cell ๋ด๋ถ์์ ์ค์ ํ์ต๋๋ค. ์ด๋ฏธ์ง๋ฅผ ํญ ํ์๋, didTapImageSlide ์ก์ ํจ์๊ฐ ํธ์ถ๋๊ณ , ํด๋น ํจ์๋ showFullScreen ํจ์๋ฅผ ํธ์ถํฉ๋๋ค.
showFullScreen ์ Closure ๋ก ์ค์ ํ๋๋ฐ์, ๋ณด์ฌ์ค์ผํ ์ด๋ฏธ์ง๊ฐ Cell ๋ง๋ค ๋ฌ๋ผ์ง๊ธฐ ๋๋ฌธ์ Closure ๋ก ์ค์ ํ์ต๋๋ค. ์ดํ ReviewTableViewDatasource ์์ ์ํํ ์ฝ๋๋ฅผ Closure ์ ๋๊ฒจ์ฃผ๋ ์์ผ๋ก ์์ฑํฉ๋๋ค.
class ReviewCell: UITableViewCell {
//...
typealias EmptyClosure = (() -> ())
var showFullScreen: EmptyClosure = {}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(didTapImageSlide(_:)))
reviewImageSlide.addGestureRecognizer(tapGesture)
// ...
}
@objc func didTapImageSlide(_ sender: UITapGestureRecognizer) {
showFullScreen()
}
}
๊ทธ๋ฆฌ๊ณ ์ ์ฒดํ๋ฉด์ผ๋ก ๋ณ๊ฒฝ๋์์ ๋, ๊ธฐ์กด์ LabelPageIndicator ๋ ๋๋ฌด ์๊ธฐ๋๋ฌธ์ ํฐ ์ฌ์ด์ฆ์ Label ์ ์ ์ํด์คฌ์ต๋๋ค. ์๋ tableView ์ฝ๋์์ TopAnchor, centerXAnchor ๋ฅผ ํตํด ์๋จ ๊ฐ์ด๋ฐ์ ์์น์์ผฐ์ต๋๋ค.
class ReviewCell: UITableViewCell {
//...
let fullScreenLabelIndicator: UILabel = {
let label = UILabel()
label.textColor = .white
label.font = UIFont.systemFont(ofSize: 16)
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
}
ReviewTableViewDatasource ํ๋กํ ์ฝ ํจ์์ธ tableView(_, cellForRowAt) ํจ์์์ ์์ Closure ๋ฅผ ์ง์ ํด์ค์๋ค. ํด๋น ์ฝ๋์์๋ ํ์ฌ ํ์ด์ง์ ๋ํ Label ๋ง ์ง์ ํด์ฃผ๊ณ ์์ด์. ํ์ด์ง๊ฐ ๋ณํ ๋๋ง๋ค Label ์ ๋ณ๊ฒฝํด์ฃผ๊ธฐ ์ํด์ ImageSlideshowDelegate ํ๋กํ ์ฝ์ ์ฑํํ๊ณ ํจ์๋ฅผ ์ฌ์ ์ํฉ๋๋ค.
// MARK: TableView - Datasource
extension ReviewTableViewController: UITableViewDataSource {
// ...
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// dequeueReusableCell ...
cell.showFullScreen = { [unowned self] in
let fullScreenController = cell.reviewImageSlide.presentFullScreenController(from: self, completion: nil)
fullScreenController.slideshow.pageIndicator = LabelPageIndicator()
fullScreenController.view.addSubview(fullScreenLabelIndicator)
fullScreenLabelIndicator.topAnchor.constraint(equalTo: fullScreenController.view.safeAreaLayoutGuide.topAnchor, constant: 10).isActive = true
fullScreenLabelIndicator.centerXAnchor.constraint(equalTo: fullScreenController.view.centerXAnchor).isActive = true
let currentPageString = String(cell.reviewImageSlide.currentPage + 1)
let maxPageString = String(cell.reviewImageSlide.images.count)
fullScreenLabelIndicator.text = currentPageString + "/" + maxPageString
fullScreenController.slideshow.delegate = self
}
}
}
// MARK: - ImageSlideshowDelegate
extension ReviewTableViewController: ImageSlideshowDelegate {
// ์ด๋ฏธ์ง ํ์ด์ง๊ฐ ๋ณ๊ฒฝ๋์์๋
func imageSlideshow(_ imageSlideshow: ImageSlideshow, didChangeCurrentPageTo page: Int) {
let maxPageString = String(imageSlideshow.images.count)
fullScreenLabelIndicator.text = String(page + 1) + "/" + maxPageString
}
}
์ฌ๊ธฐ๊น์ง ํ์ธํด๋ณด์๋ฉด ํฐ์น์ ์ ์ฒดํ๋ฉด์ผ๋ก ์ ํ๋๊ณ , ์๋จ์ Label Page Indicator ๊ฐ ๋ํ๋ ๊ฒ์ ํ์ธํ์ค ์ ์์ต๋๋ค! ๐คฉ ํด๋น ์ฌ์ง์ ๊ฐ๋ฐ์ค์ธ ์ดํ๊ณผ ๊ด๋ จ์ด ์์ต๋๋ค.
์ฐธ๊ณ ๋งํฌ