Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- swiftUI
- swift documentation
- MVVM
- SWIFT
- 클린 코드
- 리펙터링
- ribs
- 스위프트
- collectionview
- HIG
- uiscrollview
- Observable
- Human interface guide
- 리펙토링
- clean architecture
- UICollectionView
- tableView
- 애니메이션
- 리팩토링
- Protocol
- combine
- Clean Code
- map
- UITextView
- ios
- rxswift
- uitableview
- RxCocoa
- Xcode
- Refactoring
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] Thumbnail 나열된 뷰 구현 방법 (Twitter 썸네일 나열 뷰) 본문
Thumbnail이 나열된 뷰
- 트위터에서 프로필이 나열된 형태의 뷰가 존재
- 이 뷰에서 동그란 썸네일이 나열된 형태이며, 얼핏 보기에 어려워 보이지만 UIStackView를 사용하면 쉽게 구현이 가능
구현 아이디어
- 1. stackView의 spacing 프로퍼티에 음수값을 대입
- 2. 안에 넣는 뷰들은 나중에 추가되는 뷰가 아래로 가야하므로 layer.zPosition을 통해 제어
- 3. 안에 넣는 뷰들의 borderWidth와 color를 배경 색과 같게하여, 마치 썸네일이 겹치는 부분은 배경색으로 표현되게끔구현
구현
- 상수값 color 준비
import UIKit
class ViewController: UIViewController {
private let color = UIColor.lightGray
}
- 필요한 stackView와 데이터 준비
private let stackView: UIStackView = {
let stackView = UIStackView()
stackView.axis = .horizontal
// 1.
stackView.spacing = -15
stackView.translatesAutoresizingMaskIntoConstraints = false
return stackView
}()
private var images = (0...5).map { _ in UIImage(named: "dog") }
- viewDidLoad에서 레이아웃 관련 메소드와, 이미지 뷰들을 배치하는 메소드 호출
override func viewDidLoad() {
super.viewDidLoad()
setUpLayout()
setData()
}
- setUpLayout에서 스택 뷰 레이아웃 결정
private func setUpLayout() {
view.backgroundColor = color
view.addSubview(stackView)
NSLayoutConstraint.activate([
stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
])
}
- setData()에서 데이터 만큼 UIImageView를 만들어서 stackView에 넣을것인데, 모두 원 형태여야 하므로, RoundableImageView 따로 정의
- contentMode도 미리 scaleAspectFill로 설정 (비율에 맞게 커지며 나머지 부분은 잘리는 속성)
final class RoundableImageView: UIImageView {
init() {
super.init(frame: .zero)
layer.masksToBounds = true
contentMode = .scaleAspectFill
}
required init?(coder: NSCoder) {
fatalError()
}
override func layoutSubviews() {
super.layoutSubviews()
layer.cornerRadius = frame.height / 2
}
}
- 다시 되돌아 와서, setData() 구현
- 핵심 부분은 imageViews를 구하는 부분
private func setData() {
let imageViews = { ... }
imageViews.forEach(stackView.addArrangedSubview(_:))
}
- 데이터를 순회하며 constraint 설정
let imageViews = images.enumerated().map { index, image in
let imageView = RoundableImageView()
imageView.image = image
imageView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
imageView.heightAnchor.constraint(equalToConstant: 50),
imageView.widthAnchor.constraint(equalToConstant: 50),
])
// TODO
}
- 안에 넣는 뷰들은 나중에 추가되는 뷰가 아래로 가야하므로 layer.zPosition을 통해 제어
imageView.layer.zPosition = CGFloat(-index)
- borderWidth와 borderColor를 적절히 설정하여 마치 썸네일이 겹치는 부분은 배경색으로 표현되게끔구현
imageView.layer.borderWidth = 3
imageView.layer.borderColor = color.cgColor
- setData() 완성 코드
private func setData() {
let imageViews = images.enumerated().map { index, image in
let imageView = RoundableImageView()
imageView.image = image
imageView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
imageView.heightAnchor.constraint(equalToConstant: 50),
imageView.widthAnchor.constraint(equalToConstant: 50),
])
// 2.
imageView.layer.zPosition = CGFloat(-index)
// 3.
imageView.layer.borderWidth = 3
imageView.layer.borderColor = color.cgColor
return imageView
}
imageViews.forEach(stackView.addArrangedSubview(_:))
}
'UI 컴포넌트 (swift)' 카테고리의 다른 글
Comments