iOS 프로젝트/카멜레온

[iOS] 카멜레온 개발 일지 - 2 (UI/UX 디자인, 개발)

유정주 2022. 6. 14. 23:31
반응형

안녕하세요. 개발하는 정주입니다.

 

오늘은 카멜레온 개발 일지 - 2를 포스팅하려고 합니다.

개발일지 2탄에서는 UI/UX 디자인과 개발에 대한 내용을 주로 다루려고 합니다.

더 좋은 방법, 효율적으로 개선할 수 있는 부분이 보이신다면 댓글로 알려주시면 감사하겠습니다.

 

카멜레온 노션 페이지

 

카멜레온: 페이크 얼굴로 초상권을 보호하세요

카멜레온: 페이크 얼굴로 초상권을 지키세요 기간 : 2개월 (2022-03 ~ 2022-05) 인원 : 3명 (iOS 1명, API 서버 1명, ML 1명)

jeong9216.notion.site

 

* 해당 포스팅은 대략적인 개발 일지로 자세한 내용은 필요시에만 따로 포스팅합니다.

 

디자인 작업

저도 카멜레온 프로젝트의 디자인에 참여했습니다.

 

UI/UX 디자인

Mobbin 사이트에서 틀을 잡고 저희 프로젝트 컨셉과 HIG에 맞춰서 약간의 수정을 했는데요.

바닥부터 할 때와 Mobbin에서 틀을 잡고 할 때의 퀄리티 차이나 노력의 차이가 굉장히 크더라고요.

 

혹시 디자인을 해야하는데 마땅한 아이디어가 없다면 Mobbin 사이트를 참고해 보세요 ㅎㅎ

 

Mobbin - The world’s largest mobile app design reference library

Save hours of UI & UX research with our library of 50,000+ fully searchable mobile app screenshots.

mobbin.com

 

iPad 디자인

iPad 디자인도 신경써서 진행했습니다.

그냥 iPhone의 디자인대로 적용하는 것이 아니라 iPad의 사용성에 맞춰 수정해줬어요.

패드 사용성의 핵심은 컨텐츠를 크게 보는게 아니라 많이 보는 것이라는 말을 듣고 

이번 프로젝트에 꼭 반영하고 싶었습니다.

 

그래서 3열로 표시되는 아이폰의 디자인을 패드에서는 더 많이 보이게 수정해주었습니다.

컨텐츠의 크기를 고정하여 가로 길이에 맞게 컨텐츠의 수를 조절합니다.

관련 코드는 개발일지 3에서 collectionView 코드를 다룰 때 작성할게요!

 

아무튼 아이패드의 디자인을 이렇게 본격적으로 적용한건 처음이라

매우 뿌듯했습니다.

 

컬러 & 캐릭터 디자인

카멜레온 앱은 카멜레온이라는 이름에 맞게 녹색을 메인 컬러로 설정했습니다.

귀여운 캐릭터는 팀원이 손수 그렸습니다 ㅎㅎ

 

라이트 모드 / 다크 모드

결과적으로 앱의 컨셉을 잘 살린 디자인이 탄생했어요.

 

다크 모드는 고대비 모드처럼 블랙이 아니라 다크 그레이 느낌을 줬습니다.

저희 메인 컬러와 다크 모드 배경색이 잘 어울려서 다행이었습니다.

 

Lottie 애니메이션 적용하기

카멜레온 앱에 애니메이션 로딩을 넣고 싶었습니다.

전문 디자이너는 없었기에 Lottie 애니메이션 파일에 저희 컬러 디자인을 적용했어요.

Lottie를 적용한 화면 중 하나로 Launch 스크린입니다.

 

앱이 처음 시작되면 런치 스크린을 보여주면서 서버와의 통신을 확인하고 버전 체크를 합니다.

이 과정에서 애니메이션을 넣으면 좋겠다고 생각해서 Lottie 애니메이션을 적용했어요.

(화면 아래쪽의 그림이 파도처럼 출렁입니다.)

 

런치 스크린이기 때문에 시작 화면과 애니메이션의 시작점을 같게 해야 해요.

그래서 런치 스크린의 스토리보드에 애니메이션의 시작 프레임을 사진으로 넣어줬습니다.

 

실제 앱을 구동해보면 자연스럽게 애니메이션이 시작되는 것을 볼 수 있습니다.

 

Lottie 사용하기

Lottie는 spm으로 넣어줬습니다.

pod으로 넣는 것보다 라이브러리 관리가 간편해서 spm으로 가능한건 spm으로 처리하고 있어요.

 

Lottie 애니메이션을 넣는 뷰를 선언합니다.

var animationView: AnimationView!

 

AnimationView를 생성해 주세요.

let animationName = (userInterfaceStyle == .light) ? "bottomImage-Light" : "bottomImage-Dark"
animationView = .init(name: animationName)

저는 화면 모드에 따라 애니메이션을 따로 줬어요. (투명 배경을 어떻게 하는지 몰라서 배경색을 바꿨습니다 ㅠ)

init 생성자를 이용해 animation 파일 이름을 넣어주면 AnimationView 생성이 가능합니다.

 

애니메이션 속성도 설정해 줄게요.

animationView.loopMode = .loop
animationView.animationSpeed = 1.2
animationView.play()

loopMode를 이용해 한 번만 애니메이션을 줄건지, 무한 반복을 할건지 등 설정할 수 있습니다.

animationSpeed는 애니메이션 속도입니다.

모든 속성을 설정한 후 play 메서드를 호출하면 애니메이션이 시작 돼요.

 

자세한 사용법은 http://airbnb.io/lottie/#/ios 를 참고하세요.

 

extension UIColor

 

색상이 많아지다보니 고민이 생겼습니다.

색상의 이름을 외우는 것도 일이고 만약 색상의 이름을 바꾸면 그걸 사용하는 곳에서 모두 바꿔줘야 했습니다.

 

그래서 UIColor를 extension해서 사용하는 color value를 선언하고 getter를 설정했습니다.

extension UIColor {
 
    class var mainColor: UIColor {
        return UIColor(named: "MainColor") ?? .black
    }
    
    class var buttonColor: UIColor {
        return UIColor(named: "ButtonColor") ?? .black
    }
    ...
}

만약 색상의 이름이 바뀌더라도 여기 한 곳에서만 바꿔주면 되서 편리해졌습니다.

또 매번 옵셔널 처리 하는 것도 일이었는데 같이 해결이 되었네요.

 


extension UIButton

카멜레온 앱에는 next 버튼 형식이 모두 동일합니다.

그래서 매번 속성을 입히면 동일한 코드가 반복될 거 같아서 UIButton을 extension하여  속성을 적용하는 메서드를 정의해주었습니다.

반복되는 코드가 줄어들어 코드가 더 명확해지고 코드 양도 줄어드는 효과를 얻었습니다.

 

func applyMainButtonStyle(title: String) {        
    self.clipsToBounds = true
    self.layer.masksToBounds = true

    self.setBackgroundColor(UIColor.buttonColor, for: .normal)
    self.setBackgroundColor(UIColor.buttonClickColor, for: .selected)
    self.layer.cornerRadius = 20 //heigth: 40 고정

    self.setTitle(title, for: .normal)
    self.titleLabel?.font = UIFont.boldSystemFont(ofSize: 18)

    self.setTitleColor(.white, for: .normal)
    self.setTitleColor(.lightGray, for: .highlighted)

    if UITraitCollection.current.userInterfaceStyle == .light {
        self.setTitleColor(.white, for: .disabled)
    } else {
        self.setTitleColor(.lightGray, for: .disabled)
    }
}

모서리를 둥글게 하고 기본 상태와 selected의 색을 다르게 주었습니다.

 

화면 모드에 따라 비활성화 글자 색을 다르게 줬어요.

다크 모드일 때도 흰색으로 하면 비활성화 티가 잘 안 나고 라이트 모드일 때 light gray로 하면 부자연스럽더라고요.

좀 번거로워도 명확하고 이쁘게 가자! 해서 분기 처리 해주었습니다.

 

Custom UITabBarController

카멜레온 앱의 탭바는 상단 테두리가 둥글고 border가 들어갔습니다.

class CustomTabBarController: UITabBarController

그래서 Custom하여 사용하기로 했습니다.

 

결론부터 말씀 드리자면 이건 수정을 할 예정입니다.

위쪽 round를 따라 border를 적용하는 것이 쉽지 않더군요... ㅠㅠ

탭바 디자인을 적용한 내용을 가볍게 살펴보도록 해요.

 

색과 형태 설정

private func setupTabBar() {
    tabBar.clipsToBounds = true

    tabBar.tintColor = UIColor.mainColor
    tabBar.backgroundColor = UIColor(named:"TabBarColor")

    tabBar.layer.cornerRadius = tabBar.frame.height * 0.41
    tabBar.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]

    setupBorderView()

    view.bringSubviewToFront(tabBar)
}

탭바의 색과 형태를 잡는 코드입니다.

위에서 UIColor를 extension하여 선언한 mainColor 변수를 사용했습니다.

TabBarColor는 여기에서만 사용되기 때문에 굳이 UIColor쪽에 선언하지 않고 바로 탭바쪽에 넣었어요.

 

cornerRadius는 높이의 0.41%만큼 줬습니다. 0.01%가 생각보다 눈에 띄더라고요.

그리고 상단 모서리에만 적용하기 위해 maskedCorners에 MinXMinY, MaxXMinY를 설정했어요.

좌표로 생각하시면 편합니다. 0,0과 x,0에만 코너 적용을 하겠다는 의미입니다.

 

이대로 설정하면 색과 형태는 잘 적용이 될겁니다.

 

테두리 그리기

이게 참 골치더라고요?

간편하게 border를 주면 되겠지하고 시도했는데 round 위로 테두리가 그려지거나 탭바 전체를 두르는 형태를 보였습니다.

이건 제가 원하는 테두리가 아닌데... 하면서 여러 가지 서치를 했는데요.

테두리를 그리는 서브 뷰를 생성해서 붙이는 방법을 선택했습니다.

 

private func setupBorderView() {
    borderView = UIView(frame: .zero)
    borderView.translatesAutoresizingMaskIntoConstraints = false

    borderView.backgroundColor = UIColor(named: "TabBarBorderColor")
    borderView.alpha = 0.5
    borderView.layer.cornerRadius = tabBar.frame.height * 0.41
    borderView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]

    view.addSubview(borderView)
    borderView.widthAnchor.constraint(equalToConstant: tabBar.frame.width + 3).isActive = true
    borderView.heightAnchor.constraint(equalToConstant: tabBar.frame.height).isActive = true
    borderView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    borderView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -13).isActive = true
}

이 친구도 마찬가지로 색을 적용하고 상단만 둥글게 처리해주었습니다.

오토 레이아웃은 탭바에 맞췄습니다.

그래서 탭바를 숨기거나 하지 않는 이상 이쁘게 원하는대로 잘 나오게 되었어요.

 

문제점

카멜레온 앱은 홈 화면에서 벗어나면 탭바가 사라집니다.

 

이때 탭바를 hidden 시키는데 서브뷰가 같이 hidden이 안 되는 문제점이 있었습니다.

그래서 탭바는 사라지는데 테두리 뷰만 둥 떠있었어요...

 

숨기는 작업 자체는 간편했습니다. 

홈 화면에서 벗어날 때 borderView도 hidden 처리 해주면 잘 사라지죠.

하지만! 다시 hidden = false를 해주면 탭바 위로 borderView가 올라오는 문제가 있었습니다.

 

아직 이유도 잘 모르겠는 현상이라 이유를 아신다면 꼭 댓글로 남겨주세요 ㅠㅠ

 

bringtofront 등 방법을 사용해봤지만 마땅한 방법이 없었습니다.

결국에는 borderView의 hidden을 건드는 것이 아니라 alpha를 수정해서

viewDidAppear( )에서 다시 보이도록 수정해줬어요.

그래서 테두리가 다시 보이는데 약간의 딜레이가 있답니다 ㅎ..

 

종강하면 꼭 수정을 할 부분이기도 해요.

우선 원인 파악을 하고 마땅한 방법이 없다면 탭바를 커스텀하는 것이 아니라 커스텀 뷰를 만들 생각입니다.

꼭 원인을 찾아낼 수 있었으면 좋겠네요.

 

마무리

카멜레온 개발일지 2에서는 UI 개발과 디자인에 대한 이야기를 했습니다.

다음에 작성할 개발일지 3에서는 본격적으로 개발에 대한 이야기를 작성하려고 해요.

 

코드를 좀 정리하고 할지, 바로 작성할지는 모르겠지만

카멜레온에 대해 더 잘 이해할 수 있는 방향으로 진행하려고 합니다.

 

감사합니다!


아직은 초보 개발자입니다.

더 효율적인 코드 훈수 환영합니다!

공감 댓글 부탁드립니다.

 

 

 

반응형