본문 바로가기

iOS 개발/Apple App Store 클론 코딩

AppleAppStore - 6. App 화면의 Cell 구현

반응형

안녕하세요. Skillist입니다.

 

이번엔 App Tab의 VC를 구현해봐요.

다음은 제가 구현한 화면의 스크린샷 입니다.

데이터들은 크게 중요한게 아니 구현한 화면이 중요하죠.

 

역시나 Compositional Layout을 활용하였습니다.

넘나 소중해요.

 

그럼, 투데이 VC와 마찬가지로, 예상이 되죠?section에 따라 header와 cell(item)으로 구현했겠죠?? 맞습니다.

 

그래서 header와 cell을 구성해볼게요.

 

------------------------------------------------------------------------------------------------------------------

 

맨먼저, largeItem Cell을 구현할게요

largeItem Cell은 header가 없습니다.  스크린샷에서 보이는 영역이 item 하나라 생각하면 됩니다.

레이아웃부터 구현해볼게요

 

12라인 : 상단의 line을 표시할 View입니다.

 

18라인 : 파란색으로 보여줄 label입니다.

 

26, 34라인 : 검정색 Text를 보여주는 label입니다. ".label" 컬러를 지정하여, 다크모드일때는 하얀색으로 보입니다.

 

42라인 : 이미지를 보여줄 이미지 뷰입니다.

너무 간단하네요

 

------------------------------------------------------------------------------------------------------------------

다음으로 레이아웃 배치를 해볼게요. 역시 SnapKit을 사용했습니다.

스냅킷 짱!짱!



72라인 : 라인을 최상단에 위치하고 height를 1로 지정했습니다.

 

78라인 : 라인뷰 아래에 파란색 label을 위치했습니다.

 

83, 88라인 : 파란색 label 아래에 label 2개를 위치했습니다.

 

93라인 : label 하단에 이미지뷰를 추가했습니다. height는 width의 일정 비율로 구성했어요.

 

SnapKit을 구성하다보니,

어떤 view를 기준으로 잡아야지 효율적인지? 레이아웃 구성이 편한지?

기준점이 꽤나 중요하더라구요.

 

다음은 데이터 설정 입니다.

 

title과 이미지 관련 정보를 받아와, 설정합니다.

 

구현할때와는 다르게 너무 쉽죠? 왜케 쉽죠???

 

------------------------------------------------------------------------------------------------------------------

다음은 smallItem Cell입니다.

좌우 스크롤이 가능한 section입니다.

 

레이아웃을 좀 뜯어볼까요??

section입니다.

상단에는 header가 있고, 하단에는 group이 있습니다.

group에는 3개의 item이 있어요.

우리는 item과 header만 구현해줄거에요. group은 3개의 아이템을 묶어주면 되니깐요.

 그래서 우린 header와 item 레이아웃을 구성해보죠.

 

------------------------------------------------------------------------------------------------------------------

 

header입니다.

10라인 : header는 UICollectionReusableView 상속해야합니다.

 

11라인 : 상단의 line을 보여줍니다.

 

17, 25라인 : header의 title과 버튼입니다.

 

 

다음은 레이아웃 배치에요.

44라인 : 뷰를 추가합니다.

 

52~68라인 : 상단부터 레이아웃을 차근차근 배치합니다. 

 

71라인 : header의 title를 설정합니다. button의 action도 설정해야 하는데, 우선 패스하겠습니다.

 

------------------------------------------------------------------------------------------------------------------

 

이번엔 item cell입니다.

왼쪽엔 앱 아이콘이, 오른쪽엔 앱 버튼이, 중앙엔 label이 있습니다.

그럼 너무 쉽죠. 레이아웃 구성하여 배치만 하면 되네요

 

레이아웃 선언에 대한 설명은 생략할게요.

 

아이콘 이미지뷰를 기준으로 잡았고, 이미지뷰를 시작으로 하나하나씩 레이아웃 배치를 진행하고 있습니다.

 

데이터 설정도 진행하고 있습니다.

------------------------------------------------------------------------------------------------------------------

 

이렇게 AppVC에서 활용하는 Cell을 구성해봤습니다.

갑자기 너무 졸리네요;;

 

이만 마무리 하고, 다음 글에서 AppVC를 구현해볼게요

 

잘못되거나 부족한 내용 등, 피드백 감사합니다!

 

Skillist의 AppleAppStore 프로젝트

https://github.com/DeveloperSkillist/AppleAppStoreCloneCode

 

 

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓  전체 코드  ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

class AppLargeItemCollectionViewCell: UICollectionViewCell {
    private lazy var lineView: UIView = {
        let view = UIView()
        view.backgroundColor = .darkGray
        return view
    }()
    
    private lazy var subTitle: UILabel = {
        let label = UILabel()
        label.numberOfLines = 0
        label.font = .systemFont(ofSize: 15)
        label.textColor = .link
        return label
    }()
    
    private lazy var mainTitle: UILabel = {
        let label = UILabel()
        label.font = .systemFont(ofSize: 25, weight: .semibold)
        label.numberOfLines = 1
        label.textColor = .label
        return label
    }()
    
    private lazy var mainInfoTitle: UILabel = {
        let label = UILabel()
        label.font = .systemFont(ofSize: 25, weight: .semibold)
        label.numberOfLines = 1
        label.textColor = .label
        return label
    }()
    
    private lazy var imageView: DownloadableImageView = {
        let imageView = DownloadableImageView(frame: .zero)
        imageView.contentMode = .scaleAspectFill
        imageView.backgroundColor = UIColor(named: "white,darkgray")
        imageView.layer.cornerRadius = 15
        imageView.clipsToBounds = true
        return imageView
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        setupLayout()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func setupLayout() {
        [
            lineView,
            subTitle,
            mainTitle,
            mainInfoTitle,
            imageView
        ].forEach {
            addSubview($0)
        }
        
        lineView.snp.makeConstraints {
            $0.top.trailing.equalToSuperview()
            $0.leading.equalToSuperview()
            $0.height.equalTo(1)
        }
        
        subTitle.snp.makeConstraints {
            $0.top.equalTo(lineView).inset(5)
            $0.leading.trailing.equalToSuperview()
        }
        
        mainTitle.snp.makeConstraints {
            $0.top.equalTo(subTitle.snp.bottom).offset(5)
            $0.leading.trailing.equalTo(subTitle)
        }
        
        mainInfoTitle.snp.makeConstraints {
            $0.top.equalTo(mainTitle.snp.bottom).offset(5)
            $0.leading.trailing.equalTo(subTitle)
        }
        
        imageView.snp.makeConstraints {
            $0.top.equalTo(mainInfoTitle.snp.bottom).offset(10)
            $0.leading.trailing.equalTo(subTitle)
            $0.height.lessThanOrEqualTo(self.frame.width * 0.7)
            $0.bottom.equalToSuperview().inset(5)
        }
    }
    
    func setup(item: AppLargeItem) {
        subTitle.text = item.subText
        subTitle.textColor = item.subTextColor
        
        mainTitle.text = item.mainText
        mainTitle.textColor = item.mainTextColor
        
        mainInfoTitle.text = item.mainInfoText
        mainInfoTitle.textColor = item.mainInfoTextColor
        
        if let url = item.imageURL {
            imageView.downloadImage(url: url)
        } else if let image = item.image {
            imageView.image = image
        }
    }
}
class AppSmallItemsCollectionViewCell: UICollectionViewCell {
    private lazy var imageView: DownloadableImageView = {
        var imageView = DownloadableImageView()
        imageView.contentMode = .scaleToFill
        imageView.layer.cornerRadius = 10
        imageView.backgroundColor = .label
        imageView.clipsToBounds = true
        return imageView
    }()
    
    private lazy var mainText: UILabel = {
        var label = UILabel()
        label.textColor = .label
        label.font = .systemFont(ofSize: 18, weight: .bold)
        label.numberOfLines = 2
        return label
    }()
    
    private lazy var subText: UILabel = {
        var label = UILabel()
        label.textColor = .darkGray
        label.font = .systemFont(ofSize: 15, weight: .semibold)
        return label
    }()
    
    private lazy var appActionButton: UIButton = {
        var button = UIButton()
        button.setTitle("down_title".localized, for: .normal)
        button.setTitleColor(.link, for: .normal)
        button.backgroundColor = UIColor(named: "lightgray,darkgray")
        button.layer.cornerRadius = 15
        return button
    }()
    
    private lazy var inAppPurchaseText: UILabel = {
        var label = UILabel()
        label.textColor = .darkGray
        label.font = .systemFont(ofSize: 13)
        return label
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupLayout()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func setupLayout() {
        [
            imageView,
            mainText,
            subText,
            appActionButton,
            inAppPurchaseText
        ].forEach {
            addSubview($0)
        }
        
        imageView.snp.makeConstraints {
            $0.top.bottom.equalToSuperview().inset(5)
            $0.leading.equalToSuperview()
            $0.width.height.equalTo(70)
        }
        
        appActionButton.snp.makeConstraints {
            $0.trailing.equalToSuperview()
            $0.centerY.equalToSuperview()
            $0.width.equalTo(70)
        }
        
        inAppPurchaseText.snp.makeConstraints {
            $0.centerX.equalTo(appActionButton)
            $0.top.equalTo(appActionButton.snp.bottom)
            $0.bottom.equalToSuperview()
            $0.trailing.equalTo(appActionButton)
        }
        
        mainText.snp.makeConstraints {
            $0.top.equalTo(imageView).offset(5)
            $0.leading.equalTo(imageView.snp.trailing).offset(10)
            $0.trailing.equalTo(appActionButton.snp.leading).offset(-16)
        }
        
        subText.snp.makeConstraints {
            $0.top.equalTo(mainText.snp.bottom).offset(5)
            $0.leading.trailing.equalTo(mainText)
        }
    }
    
    func setup(item: AppSmallItem) {
        mainText.text = item.mainText
        subText.text = item.subText
        inAppPurchaseText.text = "in_app_purchase".localized
        
        if let url = item.imageURL {
            imageView.downloadImage(url: url)
        } else if let image = item.image {
            imageView.image = image
        }
        
        inAppPurchaseText.isHidden = !item.isInAppPurchase
    }
}
class AppSmallItemsCollectionViewCell: UICollectionViewCell {
    private lazy var imageView: DownloadableImageView = {
        var imageView = DownloadableImageView()
        imageView.contentMode = .scaleToFill
        imageView.layer.cornerRadius = 10
        imageView.backgroundColor = .label
        imageView.clipsToBounds = true
        return imageView
    }()
    
    private lazy var mainText: UILabel = {
        var label = UILabel()
        label.textColor = .label
        label.font = .systemFont(ofSize: 18, weight: .bold)
        label.numberOfLines = 2
        return label
    }()
    
    private lazy var subText: UILabel = {
        var label = UILabel()
        label.textColor = .darkGray
        label.font = .systemFont(ofSize: 15, weight: .semibold)
        return label
    }()
    
    private lazy var appActionButton: UIButton = {
        var button = UIButton()
        button.setTitle("down_title".localized, for: .normal)
        button.setTitleColor(.link, for: .normal)
        button.backgroundColor = UIColor(named: "lightgray,darkgray")
        button.layer.cornerRadius = 15
        return button
    }()
    
    private lazy var inAppPurchaseText: UILabel = {
        var label = UILabel()
        label.textColor = .darkGray
        label.font = .systemFont(ofSize: 13)
        return label
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupLayout()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func setupLayout() {
        [
            imageView,
            mainText,
            subText,
            appActionButton,
            inAppPurchaseText
        ].forEach {
            addSubview($0)
        }
        
        imageView.snp.makeConstraints {
            $0.top.bottom.equalToSuperview().inset(5)
            $0.leading.equalToSuperview()
            $0.width.height.equalTo(70)
        }
        
        appActionButton.snp.makeConstraints {
            $0.trailing.equalToSuperview()
            $0.centerY.equalToSuperview()
            $0.width.equalTo(70)
        }
        
        inAppPurchaseText.snp.makeConstraints {
            $0.centerX.equalTo(appActionButton)
            $0.top.equalTo(appActionButton.snp.bottom)
            $0.bottom.equalToSuperview()
            $0.trailing.equalTo(appActionButton)
        }
        
        mainText.snp.makeConstraints {
            $0.top.equalTo(imageView).offset(5)
            $0.leading.equalTo(imageView.snp.trailing).offset(10)
            $0.trailing.equalTo(appActionButton.snp.leading).offset(-16)
        }
        
        subText.snp.makeConstraints {
            $0.top.equalTo(mainText.snp.bottom).offset(5)
            $0.leading.trailing.equalTo(mainText)
        }
    }
    
    func setup(item: AppSmallItem) {
        mainText.text = item.mainText
        subText.text = item.subText
        inAppPurchaseText.text = "in_app_purchase".localized
        
        if let url = item.imageURL {
            imageView.downloadImage(url: url)
        } else if let image = item.image {
            imageView.image = image
        }
        
        inAppPurchaseText.isHidden = !item.isInAppPurchase
    }
}
반응형