한 조각씩 배우는 Swift UI - (2) Spacer ~ 배운과정 실습

dongle·2022년 11월 17일
0

컴포넌트 사이의 공간을 만들어주는 Spacer


이때 Spacer를 사용해 각 컨포넌트 사이에 공간을 주어 분리해줄 수 있다

struct Person: Identifiable {
    var id = UUID()
    let name: String
    let imageName: String
}

struct ContentView: View {
    var body: some View {
        VStack{
            Image(systemName: "heart")
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(width: 200)
            Spacer() // 공간을 줌
            Text("Heart!")
            Spacer() // 공간을 줌
            Button {
                print("Blink!")
            } label: {
                Text("HIT!")
            }
        }
        
    }
    
}

수평으로는 가능할까?

struct ContentView: View {
    var body: some View {
        VStack{
            Image(systemName: "heart")
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(width: 200)
            Spacer()
            HStack { // 수평으로 배치하는 Stact
                Image(systemName: "heart.fill") // 꽉 찬 하트
                Spacer()
                Text("Bolt") // Bolt 라는 텍스트
            }
            .padding(.horizontal, 100) // 간격 조정
            Spacer() // 공간을 줌
            Button {
                print("Blink!")
            } label: {
                Text("HIT!")
            }
        }
        
    }
    
}

HStack을 사용해 수평으로 꽉찬 하트와 Bolt 라는 텍스트를 배치해주었습니다.

이때, Spacer()를 사용하게 되면 각각 화면의 끝으로 이동하게 됩니다.

이를

.padding(.horizontal, 간격을 줄 만큼의 숫자)

을 사용해 둘의 간격을 임의로 조절해 줄 수 있습니다.

색상을 그려주는 Color

기본 사용

Color(.blue)

모서리 부분까지 채워주기

Color(.blue).edgesIgnoringSafeArea(.all)

추가)

Color(.blue).edgesIgnoringSafeArea(.top) // 위쪽 SafeArea만 채워짐

Color(.blue).edgesIgnoringSafeArea(.bottom) // 아래쪽 SafeArea만 채워짐

Color(.blue).edgesIgnoringSafeArea([.top, .bottom]) // 위 아래 둘 다 채워짐, all과는 다름
// 가로모드로 돌렸을 때 all은 다 채워지지만, [.top, .bottom]은 다 채워지지 않음

크기 지정 후 원하는 도형으로 모양을 바꾸기

 Color(.blue)
            .frame(width: 300, height: 200)
            // 크기 지정, 너비 300, 높이 200
            .clipShape(RoundedRectangle(cornerRadius: 30))
            // 도형으로 자르기(여기서는 모서리가 둥근 사각형, 모서리 둥글기는 30

특정 색상 가져오기

Color(red: 0.4, green: 0.5, blue: 0.1)

RGB 사용해서 가져오기

Color(hue: 0.3, saturation: 0.4, brightness: 0.5)

hue, saturation, brightness 로 만들기


직접 Asset의 ColorSet으로 원하는 색을 가져와 쓸 수 있습니다.

UI를 그릴 때는 View

struct ContentView: View {
    var body: some View {
        MyView()
    }
}
        
struct MyView: View {
    var body: some View {
        Text("Hi dongle")
    }
}

// View 안에는 View 만 들어갈 수 있음
  • View 안에는 View만 들어가야 합니다.
    View가 아닌 것이 들어가면 오류가발생하게 됩니다.
    ex) Text()는 View가 아니므로 View 안에서 쓸 수 없음

앱화면을 다시 그리기 위한 상태 State

왜 사용해야 할까?
기존 Struct로 "Hi"를 유저가 볼 수 있도록 만들고, "Hi dongle"을 보여주고 싶다면 다시 새로운 Struct를 이용해 만들어야 하는 불편함이 있었기 때문입니다.

즉, Struct(구조체)로 만든 내용은 앱화면을 다시 그리기가 힘들어집니다.

작동 원리

@State var name: String = ""

State가 변하면 다시 화면을 그려주게 됨

struct ContentView: View {
    
    @State var name: String = ""
    var body: some View {
        VStack{
            Text("Hi \(name)") // 초기 name은 공백이므로 이름이 보여지지 않음
            
            Button {
                name = "Dongle!" // 버튼을 누르게 되면 Dongle!이 name에 저장되어 State도 변하게되어 Hi Dongle!로 화면이 다시 그려짐
            } label: {
                Text("Click!")
            }
        }
    }
}

View의 설정? 옵션? modifier에 대해 알아보자

간단하게 보자면 설정이나 옵션이라고 생각할 수 있다.

struct ContentView: View {
    
    var body: some View {
        Image(systemName: "heart")
            .resizable()
            .aspectRatio(contentMode: .fit)
            .frame(width: 100)
            .background(.green)
            .foregroundColor(.red)
    }
}

.을 찍고 옵션처럼 효과를 하나 하나 주는 것 이라고 생각하면 되는데, 사실은 위의 코드로 예를 들어보자면 Image에 .resizable()한 이미지를 만들고, 그 이미지에 .aspectRatio(contentMode: .fit)한 이미지를 만들어준다고 생각하면 됩니다.

컴포넌트 사이에 공간을 주는 padding


이런 상황에서 두 컴포넌트 사이의 간격을 조정해주는 방법으로는

padding()

을 사용하면 됩니다.

여러가지 padding 응용

.padding(.bottom, 100) // 아래로 여백 100만큼
.padding(.leading, 100) // 옆으로 여백 100 만큼


padding()을 주고 배경을 줄 경우 늘어나니 주의할 것, (영역의 혼란을 줄 수 있으므로)

컴포넌트의 사이즈를 잡아주는 frame

var body: some View {
        Image(systemName: "heart")
            .resizable()
            .aspectRatio(contentMode: .fit)
            .frame(width: 300, height: 200)
            .background(.green)
    }

frame() 너비, 높이 정렬을 사용할 수 있으며, 기본은 center 가운데이다

실습 - 이제까지 배운걸로 간단하게 만들어보기(1)


두근 버튼을 누르면 가득 채워진 하트와 빈 하트가 번갈아가면서 나옴

@State var isPitapat: Bool = false
    
    var body: some View {
        ZStack{
            Color.yellow.edgesIgnoringSafeArea(.all)
            VStack {
                Spacer()
                
                Image(systemName: isPitapat ? "heart.fill" : "heart") // 만약 isPitapat이 true면 heart.fill flase면 heart 반환
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: 200)
                
                Spacer()
                
                HStack {
                    Text("하트를 원하시면")
                    
                    Button{
                        isPitapat.toggle() // 스위치 역할, true, false 번갈아가면서
                        
                    } label: {
                        Text("두근!")
                            .padding() // 여백
                            .background(.orange) // 배경 오렌지
                            .cornerRadius(10) // 모서리 둥글게
                        
                    }
                }
            }
        }
    }

참고

profile
개발자를 꿈꾸는 학생입니다!

0개의 댓글

관련 채용 정보