본문 바로가기

iOS 개발/Apple App Store 클론 코딩

AppleAppStore - 3. Today 화면의 cell 구현 1

반응형

안녕하세요. Skillist입니다.

 

작성할 내용은 많은데, 이게 은근 공수가 들어서 진도가 안나가네요. ㅠㅜㅠㅜㅠㅜ

암튼 시작해볼게요.

 

코코아팟을 통해, SwiftLint와 SnapKit을 추가했어요. 다음 주소를 통해 확인해보세요.

https://skillist.tistory.com/277

 

프로젝트에 Swiftlint 추가하기

안녕하세요. skillist입니다~~ 오늘은 SwiftLint를 추가해볼께요. 관련 글 작성 할 생각은 없었는데요, 프로젝트 진행하면서 swiftlint를 추가할 일이 생겼어요. 그래서 겸사겸사 작성해봅니다. 순서대

skillist.tistory.com

 

 

먼저 구현한 스크린샷 부터 보시죠.

일반 모드와 다크 모드의 스크린샷입니다.

 

 

현재, 네트워크 통신을 통해 이미지를 받아오지 않지만,

API를 통해 실제 이미지를 다운받아온 경우, 바로 적용할 수 있도록 이미지로 구현했습니다.

사실상, 다음 스크린샷의 "Skillist Project"와 "회색 백그라운드"는 더미 이미지인거죠.

더미 이미지를 급하게 만들다 보니, 좌우 대칭이 맞지 않습니다. 참고하세요.

그 외 다른 Text는 String입니다.

 

구현방법은 다양하겠지만,

저는 UICollectionView와 UICollectionViewCompositionalLayout을 활용하여, section으로 구현했습니다.

 

이번엔 Cell 구현부터 볼게요

 

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

 

제일먼저, Today Title 영역입니다.

 

12라인 : 오늘의 날짜를 가져와 보여주는 label입니다. 오늘의 날짜는 30라인에서 받아옵니다.

 

20라인 : "투데이"라는 글을 보여줍니다. 로컬라이즈로 구현했어요.

 

28라인 : 우측의 동그라미의 뷰인데요, AppStore를 보면 계정 사진을 보여주는 영역이죠. Today Tab 뿐만 아니라, App Tab등 재활용 하기 위하여, 따로 구현했습니다. 단순하게? 이미지뷰(url을 통해 다운할수 있도록 커스텀 했어요)에 라운드 처리로 구현했어요.

 

다음은 레이아웃 제약사항 구성입니다.

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

 

56라인 : 날짜를 보여주는 라벨을 우측 상단에 위치합니다.

 

61라인 : "투데이" text를 날짜 아래에 위치합니다.

 

66라인 : size를 30으로 맞추고, 우측에 위치합니다.

 

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

 

다음은 largeItem Cell입니다.

label은 3개이며 위에서 부터 subTitle, mainTitle, bottomTitle입니다.

센터의 text는 이미지입니다.

 

12라인 : 최상단에 위치할 subTitle입니다.

 

20라인 : subTitle 하단에 위치할 mainTitle입니다.

 

28라인 : 하단에 위치할 bottomTitle입니다.

 

36라인 : Cell의 이미지를 보여줄 이미지뷰입니다.

 

아직 코드가 쉬워서 상세 설명은 없습니다.

 

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

 

64라인 : 이미지뷰를 superview에 맞춰줍니다.

 

68라인 : subTitle의 위치를 상단에 맞춰줍니다.

 

73라인 : mainTitle을 subTitle 하단에 맞춰줍니다.

 

78라인 : bottomTitle을 하단에 위치합니다.

 

83라인 : Cell의 그림자를 구현합니다.

 

Cell의 데이터를 설정해줘야겠죠??

91~95라인 : 이미지 또는 url을 받아, 보여줍니다.

 

97~102라인 : text와 color를 설정합니다.

 

더 작성하고 싶지만, 길면 집중이 안되니, 짧게 짧게 가볼게요.

 

고생하셨습니다~

 

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

 

Skillist의 AppleAppStore 프로젝트

https://github.com/DeveloperSkillist/AppleAppStoreCloneCode

 

 

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

class TodayAccountCollectionViewCell: UICollectionViewCell {
    private lazy var dateLabel: UILabel = {
        let label = UILabel()
        label.textColor = .darkGray
        label.font = .systemFont(ofSize: 15, weight: .semibold)
        label.text = currentDate
        return label
    }()
    
    private lazy var largeTitle: UILabel = {
        let label = UILabel()
        label.textColor = .label
        label.font = .systemFont(ofSize: 34, weight: .bold)
        label.text = "today_title".localized
        return label
    }()
    
    private lazy var accountProfileView = AccountProfileView()
    
    private var currentDate: String {
        let dataFormatter = DateFormatter()
        dataFormatter.dateFormat = "MM. dd. E"
        dataFormatter.locale = Locale(identifier: Locale.current.identifier)
        return dataFormatter.string(from: Date())
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        setupLayout()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func setupLayout() {
        [
            dateLabel,
            largeTitle,
            accountProfileView
        ].forEach {
            addSubview($0)
        }
        
        dateLabel.snp.makeConstraints {
            $0.leading.trailing.equalToSuperview()
        }
        
        largeTitle.snp.makeConstraints {
            $0.top.equalTo(dateLabel.snp.bottom)
            $0.leading.equalTo(dateLabel)
            $0.bottom.equalTo(self.snp.bottom).inset(8)
        }
        
        accountProfileView.snp.makeConstraints {
            $0.trailing.equalTo(dateLabel)
            $0.bottom.equalToSuperview().inset(10)
            $0.width.height.equalTo(30)
        }
    }
}
class TodayLargeItemCollectionViewCell: UICollectionViewCell {
    private lazy var subTitle: UILabel = {
        let label = UILabel()
        label.numberOfLines = 0
        label.font = .systemFont(ofSize: 20)
        label.textColor = .darkGray
        return label
    }()
    
    private lazy var mainTitle: UILabel = {
        let label = UILabel()
        label.font = .systemFont(ofSize: 30, weight: .semibold)
        label.numberOfLines = 0
        label.textColor = .label
        return label
    }()
    
    private lazy var bottomTitle: UILabel = {
        let label = UILabel()
        label.font = .systemFont(ofSize: 20)
        label.numberOfLines = 0
        label.textColor = .darkGray
        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")
    }
    
    func setupLayout() {
        [
            imageView,
            subTitle,
            mainTitle,
            bottomTitle
        ].forEach {
            addSubview($0)
        }
        
        imageView.snp.makeConstraints {
            $0.edges.equalToSuperview()
        }
        
        subTitle.snp.makeConstraints {
            $0.top.equalToSuperview().inset(20)
            $0.leading.trailing.equalToSuperview().inset(20)
        }
        
        mainTitle.snp.makeConstraints {
            $0.top.equalTo(subTitle.snp.bottom).offset(10)
            $0.leading.trailing.equalTo(subTitle)
        }
        
        bottomTitle.snp.makeConstraints {
            $0.leading.trailing.equalTo(subTitle)
            $0.bottom.equalToSuperview().inset(20)
        }
        
        self.layer.shadowColor = UIColor.black.cgColor
        self.layer.shadowOffset = .zero
        self.layer.shadowOpacity = 0.5
        self.layer.shadowRadius = 10
        self.layer.masksToBounds = false
    }
    
    func setup(largeItem: TodayLargeItem) {
        if let imageUrl = largeItem.imageURL {
            imageView.downloadImage(url: imageUrl)
        } else if let image = largeItem.image {
            imageView.image = image
        }
        
        subTitle.text = largeItem.subText
        subTitle.textColor = largeItem.subTitleColor
        mainTitle.text = largeItem.mainText
        mainTitle.textColor = largeItem.mainTitleColor
        bottomTitle.text = largeItem.bottomText
        bottomTitle.textColor = largeItem.bottomTitlecolor
    }
    
    override func prepareForReuse() {
        imageView.image = nil
        subTitle.text = ""
        mainTitle.text = ""
        bottomTitle.text = ""
    }
}
반응형