왕논의 연구실

[swift] 디자인 트렌드 적용 본문

iOS/Swift

[swift] 디자인 트렌드 적용

ywangnon 2022. 5. 25. 15:37

머테리얼 디자인과 뉴모피즘을 swift로 구현해보려고 합니다.

그런데, 머테리얼 디자인은 구글에서 지원해주는데, 현재는 유지보수 모드로만 운영되고 있습니다.

 

1. 머테리얼 디자인

Material Components for iOS

 

GitHub - material-components/material-components-ios: [In maintenance mode] Modular and customizable Material Design UI componen

[In maintenance mode] Modular and customizable Material Design UI components for iOS - GitHub - material-components/material-components-ios: [In maintenance mode] Modular and customizable Material ...

github.com

 

MDC iOS의 유지 관리 모드의 의미

유지 보수 모드로 들어가면 다음과 같은 지원 정책이 적용됩니다.

  • 릴리스는 최선의 노력과 필요에 따라 삭감됩니다.
  • 기능 및 지원 요청은 자동으로 닫힙니다.
  • 버그는 최선을 다해 해결될 것입니다.
  • material.io 에 대한 모든 iOS 관련 문서는 제거됩니다.
  • GitHub에 대한 문서는 더 이상 유지 관리하지 않습니다.
  • Contributions는 여전히 받아 들여질 것입니다. 최고의 노력을 다해서 review하겠지만, 모두 Merge로 이어지지 않을 것입니다.

 

2. 뉴모피즘 디자인

뉴모피즘은 Dribble이라는 디자인 사이트에서 시작된 것으로, 공식적인 라이브러리 없이 개인이나 팀에서 라이브러리를 만들고 있습니다. 하지만, 일단 코드로 간단하게 만들어보겠습니다.

완성본

위 볼록한 View입니다.

class NeumorphicView: UIView {
    
    var cornerRadius: CGFloat = 15
    
    // 검은 그림자
    // lazy 키워드로 호출될 때(init의 setupView 함수 내에서 insertSublayer의 인자값으로 호출될 때) 실행된다.
    lazy var darkShadow: CALayer = {
        let darkShadow = CALayer()
        darkShadow.shadowColor = UIColor(red: 0.87, green: 0.89, blue: 0.93, alpha: 1.0).cgColor
        darkShadow.backgroundColor = UIColor.secondarySystemBackground.cgColor
        darkShadow.shadowOffset = CGSize(width: 2, height: 2)
        darkShadow.shadowOpacity = 1
        darkShadow.shadowRadius = 2
        darkShadow.cornerRadius = 15
        
        return darkShadow
    }()
    
    // 하얀 그림자
    lazy var lightShadow: CALayer = {
        let lightShadow = CALayer()
        lightShadow.shadowColor = UIColor.white.cgColor
        lightShadow.backgroundColor = UIColor.secondarySystemBackground.cgColor
        lightShadow.shadowOffset = CGSize(width: -2, height: -2)
        lightShadow.shadowOpacity = 1
        lightShadow.shadowRadius = 2
        lightShadow.cornerRadius = cornerRadius
        
        return lightShadow
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func setupView() {
        backgroundColor = .secondarySystemBackground
        self.layer.cornerRadius = cornerRadius
        self.layer.insertSublayer(lightShadow, at: 0)
        self.layer.insertSublayer(darkShadow, at: 0)
    }
    
    /// 위치와 크기 재조정 함수
    override func layoutSubviews() {
        super.layoutSubviews()
        darkShadow.frame = self.bounds
        lightShadow.frame = self.bounds
    }
}

아래 오목한 view입니다.

class NeumorphicInnerView: UIView {
    
    var cornerRadius: CGFloat = 15
    
    lazy var darkShadow: CALayer = {
        let darkShadow = CALayer()
        darkShadow.shadowOffset = CGSize(width: 5, height: 5)
        darkShadow.shadowOpacity = 1
        darkShadow.shadowRadius = 3
        darkShadow.cornerRadius = cornerRadius
        
        return darkShadow
    }()
    
    lazy var lightShadow: CALayer = {
        let lightShadow = CALayer()
        lightShadow.shadowOffset = CGSize(width: -5, height: -5)
        lightShadow.shadowOpacity = 1
        lightShadow.shadowRadius = 3
        lightShadow.cornerRadius = cornerRadius

        return lightShadow
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func setupView() {
        backgroundColor = .secondarySystemBackground
        self.layer.cornerRadius = cornerRadius
        self.layer.masksToBounds = true
        self.layer.addSublayer(darkShadow)
        self.layer.addSublayer(lightShadow)
        
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        darkShadow.frame = self.bounds
        lightShadow.frame = self.bounds
        
        let path = UIBezierPath(roundedRect: bounds.insetBy(dx: -3, dy: -3), cornerRadius: cornerRadius)
        let cutout = UIBezierPath(roundedRect: bounds, cornerRadius: cornerRadius).reversing()
        path.append(cutout)
        
        darkShadow.shadowPath = path.cgPath
        lightShadow.shadowPath = path.cgPath
        
        darkShadow.shadowColor = UIColor.black.withAlphaComponent(0.2).cgColor
        lightShadow.shadowColor = UIColor.white.withAlphaComponent(0.9).cgColor
    }
}

 

만들면서 느낀 점은 색이 별로 안들어가기에 색의 조합에 굉장히 신경을 많이 써야한다는 것입니다. 그림자와 배경색등에 신경을 잘못쓰면 화면에 붙은 채로 볼록한 느낌이 아니라, 그냥 화면에 떠서 그림자가 드리워진 느낌이 들었습니다. 처음에는 흰색 배경에 shadowRadius를 크게 줘서 위쪽의 흰색 그림자 느낌이 약했습니다. 그러니까 볼록한 느낌이 아니라, 배경 위에 뷰가 떠있는 느낌을 주었습니다. 그래서 배경도 약간 진하게 secondarySystemBackground로 주고, shadowRadius도 줄여서 퍼짐을 줄이니깐 위쪽의 흰색 그림자가 좀 더 부각되며 볼록한 느낌을 주었습니다.

 

구현 코드

'iOS > Swift' 카테고리의 다른 글

[Swift] Struct vs Class  (0) 2022.06.18
[Swift] 모바일 저장소 - Realm  (0) 2022.06.08
[Swift]동적 아이콘 변경  (0) 2021.09.22
[Swift]삼항연산자(?), 옵셔널 기본처리(??)  (0) 2021.09.22
[Swift]디버깅 식별자  (0) 2021.09.22