wonjinatti

Lecture 2 – Shape of card Card Game

Shape

이제는 카드를 만들기 위해 직사각형을 만들어 봅니다. 이번 예제에서는 이모지를 많이 활용 합니다. 메뉴바에서 edit 를 열어 보면…

이제 코드를 작성해 봅니다. 이모지를 넣고 직사각형을 만듭니다.

struct ContentView: View {
    var body: some View {
        VStack (content: {
            Rectangle()
            Text("👻").font(.largeTitle)
        })
        .foregroundStyle(.orange)
        .imageScale(.small)
        .padding()
    }
}

직사각형 또한 뷰처럼 행동합니다. 또 다른 shape를 알아보면 Circle(), RoundedRectangle은 인수가 필요합니다. 즉 RoundedRectangle(cornerRadius: 12) 모서리의 반경을 나타냅니다.

Rectangle를 RoundedRectangle로 변경 후 이모지를 카드 위에 올리겠습니다. 이 때 VStack를 ZStack으로 바꾸게 되면 보이는 화면의 높이에 의해 이모지가 카드위로 올라가게 됩니다.

struct ContentView: View {
    var body: some View {
        ZStack (content: {
            RoundedRectangle(cornerRadius: 12)
            Text("👻").font(.largeTitle)
        })
        .foregroundStyle(.orange)
        .imageScale(.small)
        .padding()
    }
}

좀 더 카드 모양에 가까히 만들기 위해 Stroke(획) 설정을 하게 되면

struct ContentView: View {
    var body: some View {
        ZStack (content: {
            RoundedRectangle(cornerRadius: 12)
                .strokeBorder(style: StrokeStyle(lineWidth: 10, dash: [10,2]))
            Text("👻").font(.largeTitle)
        })
        .foregroundStyle(.orange)
        .imageScale(.small)
        .padding()
    }
}

위와 같이 테두리 점선을 만들 수 있습니다. 어려 옵션들을 다 적용시키고 공부하는데는 한계가 있으므로 간단히 구현하면 아래와 같습니다.

.strokeBorder(style: StrokeStyle(lineWidth:  2)

음 이제 라이트 모드에서와 다크모드에서 어떻게 보이는지 알아봐야 합니다. 그래서 Preview 에 있는 왼쪽 3개의 아이콘 중 맨 오른쪽 실행

이 때 Color Sheme Variants 는 라이트 모드 다크 모드를 의미.

다크모드 일 때도 카드가 흰색으로 보이게 할려면 어떻게 할까요? 아래와 같이 변경합니다.

    var body: some View {
        ZStack (content: {
            RoundedRectangle(cornerRadius: 12)
                .foregroundColor(.white)
            RoundedRectangle(cornerRadius: 12)
                .strokeBorder(style: StrokeStyle(lineWidth: 2))
            Text("👻").font(.largeTitle)
        })
        .foregroundStyle(.orange)
        .padding()
    }

하나의 직사각형을 더 만드는 것 입니다. 여기서 ZStack의 개념에 유의하세요.

두번째 줄인 Orientation Variants 은 폰을 가로, 세로로 놓였을 때의 보이는 모양입니다.

기본적인 브리뷰의 셋팅 값은 스위치 아이콘 셋팅 부분에서 알 수 있다.

Stack

그런데 카드가 너무 크고 여러장의 카드를 한 화면에 배치할려고 합니다. 그러면 HStack을 써서 활용해 볼까요.

        HStack {
            ZStack (content: {
                RoundedRectangle(cornerRadius: 12)
                    .foregroundColor(.white)
                RoundedRectangle(cornerRadius: 12)
                    .strokeBorder(style: StrokeStyle(lineWidth: 2))
                Text("👻").font(.largeTitle)
            })
            ZStack (content: {
                RoundedRectangle(cornerRadius: 12)
                    .foregroundColor(.white)
                RoundedRectangle(cornerRadius: 12)
                    .strokeBorder(style: StrokeStyle(lineWidth: 2))
                Text("👻").font(.largeTitle)
            })
            ZStack (content: {
                RoundedRectangle(cornerRadius: 12)
                    .foregroundColor(.white)
                RoundedRectangle(cornerRadius: 12)
                    .strokeBorder(style: StrokeStyle(lineWidth: 2))
                Text("👻").font(.largeTitle)
            })
            ZStack (content: {
                RoundedRectangle(cornerRadius: 12)
                    .foregroundColor(.white)
                RoundedRectangle(cornerRadius: 12)
                    .strokeBorder(style: StrokeStyle(lineWidth: 2))
                Text("👻").font(.largeTitle)
            })
        }
        .foregroundStyle(.orange)
        .padding()
    }

하지만 zStack이 중복되는 것을 보아 코드가 좋지 않습니다. 그리고 body에 코드가 너무 길어 가독성이 떨어 집니다.  그래서 CardView 라는 구조체를 만들어 보겠습니다. CardView라는 구조체는 인수가 필요하지 않습니다.

struct ContentView: View {
    var body: some View {
        HStack {
            CardView()
            CardView()
            CardView()
            CardView()
        }
        .foregroundStyle(.orange)
        .padding()
    }
}

struct CardView: View {
    var body: some View {
        ZStack (content: {
            RoundedRectangle(cornerRadius: 12)
                .foregroundColor(.white)
            RoundedRectangle(cornerRadius: 12)
                .strokeBorder(style: StrokeStyle(lineWidth: 2))
            Text("👻").font(.largeTitle)
        })
    }
}

#Preview {
    ContentView()
}

카드가 앞면인지 뒷면인지를 나타내는 argument 를 추가 해 볼 까요?

struct CardView: View {
    var isFaceUp: Bool

Argument for parameter 라는 에러 발생 즉 인수를 넣어야 하네요. 모든 구조체안에 변수가 존재하면 값을 넗어야 합니다.

struct ContentView: View {
    var body: some View {
        HStack {
            CardView(isFaceUp: true)
            CardView()
            CardView()
            CardView()
        }
        .foregroundStyle(.orange)
        .padding()
    }
}

struct CardView: View {
    var isFaceUp: Bool = false
    var body: some View {
        ZStack (content: {
            RoundedRectangle(cornerRadius: 12)
                .foregroundColor(.white)
            RoundedRectangle(cornerRadius: 12)
                .strokeBorder(style: StrokeStyle(lineWidth: 2))
            Text("👻").font(.largeTitle)
        })
    }
}

 이제 ContentView의 제일 윗부분 코드에서는 인수를 넣어 Bool 값을 true로 주었고 나머지의 CardView는 false 라는 기본값을 가집니다. 그리고 간단히 앞면일 경우와 뒷면일 경우에 카드를 다르게 보이기 위해 if 문을 입력하면.

struct CardView: View {
    var isFaceUp: Bool = false
    var body: some View {
        ZStack (content: {
            if isFaceUp {RoundedRectangle(cornerRadius: 12)
                    .foregroundColor(.white)
                RoundedRectangle(cornerRadius: 12)
                    .strokeBorder(style: StrokeStyle(lineWidth: 2))
                Text("👻").font(.largeTitle)
            } else {
                RoundedRectangle(cornerRadius: 12)
            }
        })
    }
}

Leave a comment