본문 바로가기

프로젝트/Image Generator (w∕OpenAI)

05. 인터페이스 디자인 #2

인터페이스 디자인 #2
앱 설정, 디자인 다듬기


앱 설정

기기의 모든 상태에 대처할 수 있다면 더할 나위 없이 좋겠지만,
가진이 없다면 예상이 되는 상황은 미리 차단하는 것도 방법이다.

앱 설정
| 화면 방향 고정하기

인터페이스를 디자인할 때 offset 등의 고정값을 사용하지 않았기 때문에 큰 문제는 없지만,
이렇게 화면의 방향이 바뀌면 서로의 영역을 침범하는 문제가 생긴다.
따라서 이 앱에서는 Portrait 모드만 지원하도록 앱의 Deployment Info를 변경한다.
이제부터 이 앱은 iPhone의 Portrait 모드 상태로만 제공된다.

앱 설정
| 화면 모드 고정하기

애플은 iOS13부터 darkmode를 지원하기 시작했다.
기본으로 제공하는 API에는 대비가 돼있어 크게 신경 쓸 부분은 없지만 위의 OpenAI의 로고와 같이
하나만 고려하고 만든 UI는 문제가 생길 수 있다.

앱의 Build Settings > Info.plist Values의 'User Interface Style'을 변경해
앱이 어떤 Style로 동작할지를 지정할 수 있다.
기본값은 Automatic이다.

 

디자인 다듬기
| InfoView, Image

Image("openai.logo")
    .resizable()
    .frame(width: 60, height: 60)
    .overlay {
        RoundedRectangle(cornerRadius: 15)
            .stroke(.white, lineWidth: 3)
    }

지금 상황은 openai 로고에 테두리를 추가만 한 상태이다.

그래서 배경색과 로고의 색이 일치하는 dark mode에서는 문제가 눈에 띄지 않았지만,
light mode에서는 처리되지 않은 이미지의 모서리가 드러난다.

Image("openai.logo")
    .resizable()
    .frame(width: 60, height: 60)
    .cornerRadius(15)
    .overlay {
        RoundedRectangle(cornerRadius: 15)
            .stroke(.white, lineWidth: 3)
    }

테두리를 추가하기 전에 동일한 곡률로 이미지의 테두리를 오려주면 문제를 해결할 수 있다.

light mode에서도 튀어나오는 모서리 없이 의도한 대로 보인다.

디자인 다듬기
| scheme 분기하기

기본으로 제공하는 많은 API는 scheme에 자동으로 반응하지만
직접 만든 View들은 이에 대응하지 못한다.
대표적인 예가 이 앱의 ProgressView다.

light mode에서는 문제없는 progressView가 dark mode에서는 대비가 너무 강하고 progressView는 보이지도 않는다.

struct ContentView: View {
    @Environment(\.colorScheme) private var colorScheme

    @ObservedObject var viewModel = ViewModel()
    @State var processState = false
    @State var alertState = false
    @State var image: UIImage?
    @State var text = ""

    var body: some View {
        NavigationView {
            VStack {
                Spacer()

현재 앱이 어떤 Scheme을 사용하고 있는지 Evironment 변수인 colorScheme으로 확인할 수 있다.

.overlay {
    if processState {
        ZStack(alignment: .center) {
            Color(uiColor: .black)
                .opacity(0.3)
                .ignoresSafeArea()

            Rectangle()
                .frame(width: 100, height: 100)
                .blurEffect()
                .blurEffectStyle(colorScheme == .dark ? .systemChromeMaterialDark : .systemChromeMaterial)
                .cornerRadius(15)

            ProgressView()
                .vibrancyEffect()
        }
    }
}

해당 변수에 따라 적용할 modifier를 변경하기만 하면 된다.
값이 dark인 경우 systemChromeMaterialDark를 사용하고,
light인 경우 systemChromeMaterial을 사용하도록 구현했다.

값에 따라 다른 방식의 modifier를 적용할 수 있다.
이미 배경에 dimming이 추가된 상태라 material 효과는 시인성이 떨어지므로
systemThinMaterial을 사용하도록 다시 변경한다.

.overlay {
    if processState {
        ZStack(alignment: .center) {
            Color(uiColor: .black)
                .opacity(0.3)
                .ignoresSafeArea()

            Rectangle()
                .frame(width: 100, height: 100)
                .blurEffect()
                .blurEffectStyle(colorScheme == .dark ? .systemThinMaterialDark : .systemThinMaterialLight)
                .cornerRadius(15)

            ProgressView()
                .vibrancyEffect()
        }
    }
}

 

디자인 다듬기
| AppIcon

XCode의 버전이 올라가면서 굉장히 편리하게 바뀐 부분이다.

왼쪽이 기존, 오른쪽이 최근이 방법이다.
이전에는 크기 별로 전부 하나씩 지정해야 했다면 최근에는 가장 큰 사이즈인 1024만 지정하면 전체에 일괄 적용된다.

디자인 다듬기
| LaunchScreen

최근 기기들의 성능이 좋아지면서 볼 일이 그리 많지는 않지만 왠지 아쉬운 요소가
Splash Screen이라고도 불리는 Launch Screen이다.

LaunchScreen 파일을 하나 추가하면

UIKit을 사용해 Launch Screen을 디자인할 수 있다.

간단하게 디자인 해 주고

Target 설정의 'App Icons and Launch Screen' 항목으로 지정해 주면
앱이 실행되는 시점에 자동으로 표시된다.

'프로젝트 > Image Generator (w∕OpenAI)' 카테고리의 다른 글

04. 기능구현 #3  (0) 2022.12.28
03. 기능구현 #2  (0) 2022.12.27
02. 기능 구현 #1  (0) 2022.12.27
01. 인터페이스 디자인 #1  (0) 2022.12.24
00. 시작하며  (0) 2022.12.23