Skip to content

Commit

Permalink
[GWL-51] Design System Page Control 생성 (#54)
Browse files Browse the repository at this point in the history
* feat: GWPageControl 구현

* feat: GWRoundedShadwView 구현

* chor: 접근 제어자 수정

* feat: 접근 제어자 수정, GWShadow 파일 분리
  • Loading branch information
MaraMincho authored Nov 16, 2023
1 parent 58fa5d9 commit 16f6422
Show file tree
Hide file tree
Showing 3 changed files with 197 additions and 0 deletions.
123 changes: 123 additions & 0 deletions iOS/Projects/Shared/DesignSystem/Sources/GWPageConrol.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
//
// GWPageConrol.swift
// DesignSystem
//
// Created by MaraMincho on 11/16/23.
// Copyright © 2023 kr.codesquad.boostcamp8. All rights reserved.
//

import Foundation

import UIKit

// MARK: - GWPageControl

public final class GWPageControl: UIView {
let countOfPage: Int
var currentPageIndex: Int = 0
let spacing: CGFloat = 8
var pages: [GWRoundShadowView] = []
var pageswidthConstraint: [NSLayoutConstraint] = []

// MARK: - 과연 UIVIew를 optional로 만드는게 맞을까?

/// 2 와 5 사이 숫자를 입력하세요 아닐경우 nil이 리턴됩니다.
public init(count: Int = 2) {
countOfPage = (UIPageControlDefaultProperty.range).contains(count) ?
count :
UIPageControlDefaultProperty.numOfMinPage

super.init(frame: .init(origin: .zero, size: CGSize(width: 60, height: 10)))

makePages()
makePageConstraints()
selectPage(at: 0)
}

@available(*, unavailable)
required init?(coder _: NSCoder) {
fatalError()
}

private enum UIPageControlDefaultProperty {
static let numOfMinPage = 2
static let numOfMaxPage = 5

static let range = numOfMaxPage ... numOfMaxPage

static let selectedPageColor = DesignSystemColor.main03
static let deselectedPageColor = DesignSystemColor.gray02

static let selectedPageWidth: CGFloat = 40
static let deselectedPageWidth: CGFloat = 10
}
}

private extension GWPageControl {
func makePages() {
pages = (0 ..< countOfPage).enumerated().map { _, _ -> GWRoundShadowView in
return pageViewObject
}
}

func makePageConstraints() {
var targetLeadingAnchor = safeAreaLayoutGuide.leadingAnchor
var targetSpacing: CGFloat = 0

pages.forEach { page in
// 중요: 맨 처음 Page객체는 왼쪽으로 붙여야 하기에 필수 불가결적으로 다음 로직이 필요합니다.
if targetLeadingAnchor != safeAreaLayoutGuide.leadingAnchor {
targetSpacing = spacing
}

addSubview(page)
page.leadingAnchor.constraint(equalTo: targetLeadingAnchor, constant: targetSpacing).isActive = true
page.heightAnchor.constraint(equalToConstant: spacing).isActive = true

let widthAnchor = page.widthAnchor.constraint(equalToConstant: UIPageControlDefaultProperty.deselectedPageWidth)
widthAnchor.isActive = true
pageswidthConstraint.append(widthAnchor)

targetLeadingAnchor = page.trailingAnchor
}
}

var pageViewObject: GWRoundShadowView {
let view = GWRoundShadowView(
shadow: .init(
shadowColor: DesignSystemColor.gray02.cgColor,
shadowOffset: CGSize(width: 0, height: 1),
shadowOpacity: 0.2, shadowRadius: 4.0
),
cornerRadius: 4,
backgroundColor: DesignSystemColor.gray03.cgColor
)

view.translatesAutoresizingMaskIntoConstraints = false
return view
}
}

public extension GWPageControl {
func selectPage(at pageIndex: Int) {
guard 0 ..< pages.count ~= pageIndex else {
return
}
let page = pages[pageIndex]
page.update(color: UIPageControlDefaultProperty.selectedPageColor)

let pageWidthConstraint = pageswidthConstraint[pageIndex]
pageWidthConstraint.constant = UIPageControlDefaultProperty.selectedPageWidth
}

func deselectPage(at pageIndex: Int) {
guard 0 ..< pages.count ~= pageIndex else {
return
}
let page = pages[pageIndex]
page.update(color: UIPageControlDefaultProperty.deselectedPageColor)

let pageWidthConstraint = pageswidthConstraint[pageIndex]
pageWidthConstraint.constant = UIPageControlDefaultProperty.deselectedPageWidth
}
}
57 changes: 57 additions & 0 deletions iOS/Projects/Shared/DesignSystem/Sources/GWRoundShadowView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//
// GWRoundShadowView.swift
// DesignSystem
//
// Created by MaraMincho on 11/16/23.
// Copyright © 2023 kr.codesquad.boostcamp8. All rights reserved.
//

import UIKit

// MARK: - GWRoundShadowView

public final class GWRoundShadowView: UIView {
let containerView = UIView()
let cornerRadius: CGFloat
let customShadow: GWShadow
private var shadowLayer: CAShapeLayer!
private var fillColor: CGColor = UIColor.blue.cgColor

public func update(color: UIColor) {
fillColor = color.cgColor
}

override public func layoutSubviews() {
super.layoutSubviews()
if shadowLayer == nil {
shadowLayer = CAShapeLayer()

shadowLayer.path = UIBezierPath(roundedRect: bounds, cornerRadius: cornerRadius).cgPath
shadowLayer.fillColor = fillColor

shadowLayer.shadowColor = customShadow.shadowColor
shadowLayer.shadowPath = shadowLayer.path
shadowLayer.shadowOffset = customShadow.shadowOffset
shadowLayer.shadowOpacity = customShadow.shadowOpacity
shadowLayer.shadowRadius = customShadow.shadowRadius

layer.insertSublayer(shadowLayer, at: 0)
}

if shadowLayer.fillColor != fillColor {
shadowLayer.fillColor = fillColor
}
}

public init(shadow: GWShadow, cornerRadius: CGFloat, backgroundColor: CGColor) {
customShadow = shadow
self.cornerRadius = cornerRadius
fillColor = backgroundColor
super.init(frame: .zero)
}

@available(*, unavailable)
required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
17 changes: 17 additions & 0 deletions iOS/Projects/Shared/DesignSystem/Sources/GWShadow.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// GWShadow.swift
// DesignSystem
//
// Created by MaraMincho on 11/16/23.
// Copyright © 2023 kr.codesquad.boostcamp8. All rights reserved.
//
import CoreGraphics

// MARK: - GWShadow

public struct GWShadow {
let shadowColor: CGColor
let shadowOffset: CGSize
let shadowOpacity: Float
let shadowRadius: CGFloat
}

0 comments on commit 16f6422

Please sign in to comment.