본문 바로가기
ios View

[SwiftUI] TextEditor / placeholder, 외곽선, 정렬

by 리트레서 2024. 5. 12.

Swiftui에서 TextField가 주어진 width 크기를 초과하면 자동으로 줄이 바뀌지 않고 horizontal로 스크롤되어 ui는 텍스트 크기와 상관 없이 한 줄로 유지됩니다.

struct AddDiaryView: View {
  @State var text: String = ""
  var body: some View {
    VStack(content: {
      TextField(
        "aaaa",
        text: $text
      )
      .lineLimit(12)
      .autocorrectionDisabled(true)
    })
  }
}

 

제가 필요한 것은 Textfield의 width 크기를 초과했을 때 vertical 방향으로 텍스트가 추가되는 것을 원하기 때문에 다른 방법을 찾아보았습니다.


1. axis 파라미터

방법을 찾다가 axis 파라미터.vertical을 전달하는 방법을 찾았습니다. 

하지만 공식문서를 보면 axis 파라미터는 ios 16.0버전 이상부터 사용가능해 ios 15.0 버전을 사용하는 저는 다른 방법을 사용해야 했습니다.

 

init(_:text:axis:) | Apple Developer Documentation

Creates a text field with a preferred axis and a text label generated from a localized title string.

developer.apple.com

 

 

2. TextEditor

TextEditor를 선언하여 텍스트를 입력해보았습니다.

텍스트가 입력됨에 따라 vertical 방향으로 뷰가 늘어나는 것을 확인했습니다.

struct AddDiaryView: View {
  @State var text: String = ""
  var body: some View {
    VStack(content: {
      TextEditor(text: $text)
      .autocorrectionDisabled(true)
    })
  }
}

 

 

 

 

 

이후 글자 크기와 글자 색을 설정하고 .multilineTextAlignment(.center)로 입력되는 글자를 가운데 정렬하였습니다.

 

struct AddDiaryView: View {
  @State var text: String = ""
  var body: some View {
    VStack(content: {
      TextEditor(text: $text)
        .font(.system(size: 18))
        .foregroundStyle(Color.black)
        .multilineTextAlignment(.center)
        .autocorrectionDisabled(true)
    })
  }
}

 

 

 

 

 

현재 사용자에게 어떤 정보를 입력해야하는 지 설명하는 텍스트가 없기 때문에 textfield에 있는 hint 파라미터처럼 placeholder를 구현하였습니다. 삼항식을 이용하여 텍스트가 공백일 때 투명도를 0.35로 설정하여 같이 겹쳐 있는 Text(hint)가 보이도록 구현했습니다.

struct AddDiaryView: View {
  @State var text: String = ""
  var body: some View {
    VStack(content: {
      ZStack(content: {
        if(text.isEmpty) {
          VStack(content: {
            Text("내용을 적어 주세요!")
              .font(.system(size: 18))
              .foregroundStyle(Color.gray)
              .padding(.top, 10)
           
            Spacer()
          })
        }
        
        VStack(content: {
          TextEditor(text: $text)
            .font(.system(size: 18))
            .foregroundStyle(Color.black)
            .multilineTextAlignment(.center)
            .autocorrectionDisabled(true)
            .opacity(text.isEmpty ? 0.35 : 1)
        })
      })
    })
  }
}

 

 

 

 

 

textEditor의 크기를 지정하지 않으면 vertical 방향으로 뷰가 계속 늘어나기 때문에 .frame modifier를 통해 뷰의 크기를 지정해주었습니다 또한 .padding modifier로 좌우 여백을 지정해주었습니다.

struct AddDiaryView: View {
  @State var text: String = ""
  var body: some View {
    VStack(content: {
      textEditorView
      Spacer()
    })
  }
  
  var textEditorView: some View {
    ZStack(content: {
      if(text.isEmpty) {
        VStack(content: {
          Text("내용을 적어 주세요!")
            .font(.system(size: 18))
            .foregroundStyle(Color.gray)
            .padding(.top, 10)
         
          Spacer()
        })
      }
      
      VStack(content: {
        TextEditor(text: $text)
          .font(.system(size: 18))
          .foregroundStyle(Color.black)
          .multilineTextAlignment(.center)
          .autocorrectionDisabled(true)
          .opacity(text.isEmpty ? 0.35 : 1)
      })
    })
    .frame(height: 200)
    .padding(EdgeInsets(top: 0, leading: 20, bottom: 0, trailing: 20))
  }
}

 

 

 

 

 

이후 텍스트 필드 영역을 눈으로 확인할 수 있게

.overlay( RoundedRectangle(cornerRadius:1).stroke(Color.gray, lineWidth: 1))를 통해 외곽선을 추가해줬습니다.

 

 

 

 

 

전체코드

struct AddDiaryView: View {
  @State var text: String = ""
  var body: some View {
    VStack(content: {
      textEditorView
      Spacer()
    })
  }
  
  var textEditorView: some View {
    ZStack(content: {
      if(text.isEmpty) {
        VStack(content: {
          Text("내용을 적어 주세요!")
            .font(.system(size: 18))
            .foregroundStyle(Color.gray)
            .padding(.top, 10)
         
          Spacer()
        })
      }
      
      VStack(content: {
        TextEditor(text: $text)
          .font(.system(size: 18))
          .foregroundStyle(Color.black)
          .multilineTextAlignment(.center)
          .autocorrectionDisabled(true)
          .opacity(text.isEmpty ? 0.35 : 1)
      })
    })
    .frame(height: 200)
    .overlay( RoundedRectangle(cornerRadius:1).stroke(Color.gray, lineWidth: 1))
    .padding(EdgeInsets(top: 0, leading: 20, bottom: 0, trailing: 20))
  }
}