관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] UITableView의 backgroundView 프로퍼티 (#썸네일, 스켈레톤 뷰) 본문

iOS 응용 (swift)

[iOS - swift] UITableView의 backgroundView 프로퍼티 (#썸네일, 스켈레톤 뷰)

jake-kim 2023. 10. 10. 01:17

UITableView의  backgroundView 프로퍼티

  • 보통 리스트 형태나 그리드 형태로 데이터를 보여줄 때, 데이터를 불러오기 전에 스켈레톤 뷰 같은것을 보여주어야 하는데 이 때 UITalbeView나 UICollectionView 내부에 있는 backgroundView 프로퍼티를 사용하면 매우 쉽게 적용이 가능 (별도의 뷰 필요 없이 tableView.backgroundView 사용)
  • 이 backgroundView는 tableView의 cell 앞쪽에 위치

https://developer.apple.com/documentation/uikit/uitableview/1614986-backgroundview

ex) tableView에 사용할 cell 정의

final class MyTableViewCell: UITableViewCell {
    static let id = "MyTableViewCell"
    private let label = {
        let label = UILabel()
        label.text = "label1234"
        label.font = .systemFont(ofSize: 24, weight: .regular)
        label.numberOfLines = 0
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()
    
    @available(*, unavailable)
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        contentView.addSubview(label)
        NSLayoutConstraint.activate([
            label.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
            label.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
            label.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
            label.topAnchor.constraint(equalTo: contentView.topAnchor),
        ])
    }
    
    override func prepareForReuse() {
        super.prepareForReuse()
        self.prepare(text: "")
    }
    
    func prepare(text: String) {
        label.text = text
    }
}
  • UIViewController에서 해당 셀을 가진 UITableView 준비
class ViewController: UIViewController {
    private let tableView = {
        let view = UITableView()
        view.separatorStyle = .none
        view.bounces = true
        view.showsVerticalScrollIndicator = true
        view.contentInset = .zero
        view.register(MyTableViewCell.self, forCellReuseIdentifier: MyTableViewCell.id)
        view.estimatedRowHeight = 34
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()
    
    private var dataSource = [String]()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
    }

    private func setupUI() {
        view.addSubview(tableView)
        NSLayoutConstraint.activate([
            tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            tableView.topAnchor.constraint(equalTo: view.topAnchor),
        ])
    }
}
  • dataSource 준비
tableView.dataSource = self

extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        dataSource.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: MyTableViewCell.id, for: indexPath) as! MyTableViewCell
        cell.prepare(text: dataSource[indexPath.row])
        return cell
    }
}
  • 데이터가 보이기 전에 특정 뷰가 보이도록 tableView.backgroundView 적용
    private func setupUI() {
        let thumbnailView = UIImageView(image: UIImage(systemName: "circle"))
        tableView.backgroundView = thumbnailVi
        
      ...
  • viewDidAppear에서 3초 딜레이 후 tableView에 데이터를 삽입하여 backgroundView 확인
DispatchQueue.main.asyncAfter(deadline: .now() + 3, execute: {
    self.dataSource = (1...100).map(String.init)
    self.tableView.reloadData()
})

(결과)

  • tableView의 cell 앞쪽에 위치하는 backgroundView 확인

  • 응용하여 cell이 그려지기 전에 그라데이션 배경을 주기
let gradientLayer = CAGradientLayer()
gradientLayer.colors = [UIColor.blue.cgColor, UIColor.green.cgColor]
gradientLayer.frame = tableView.bounds

let gradientBackgroundView = UIView()
gradientBackgroundView.layer.addSublayer(gradientLayer)
tableView.backgroundView = gradientBackgroundView

(결과)

* 전체 코드: https://github.com/JK0369/ExTableViewBackgroundView

 

* 참고

https://developer.apple.com/documentation/uikit/uitableview/1614986-backgroundview

Comments