ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • SwiftUI - monospaced를 이용한 Text 고정폭 설정하기
    SwiftUI 2023. 7. 20. 17:56

    안녕하세요. 그린입니다 🍏

    이번 포스팅에서는 SwiftUI에서 Text의 고정폭을 설정하는 방법을 monospaced와 함께 알아보겠습니다🙌

     

    우선 monospaced가 어떤 역할을 하는지부터 공식문서를 통해 살펴보겠습니다 🕺🏻

     

    monospaced

    기본 글꼴과 동일한 폰트 패밀리의 고정 너비 글꼴을 반환해주는 메서드입니다.

    만약 동일한 폰트 패밀리의 적합한 글꼴이 없을 경우 SwiftUI가 기본 고정 너비 글꼴로 반환해줍니다.

     

    func monospaced() -> Font

    선언을 보시면 SwiftUI의 사용하는 메서드로 Font 타입으로 반환해줍니다.

     

    다만 아쉬운점은 iOS 15 이상부터 사용이 가능해요 🥲

     

    그리고 기본적으로 Text나 그 외 텍스트를 감싸는 HStack등에서 붙일 수 있지만, font 지정 시 design 옵션을 통해 .monospaced 값을 주어 동일한 효과를 줄 수 있어요!

     

    이 부분은 바로 밑에서 예시를 통해 조금 더 자세히 알아볼께요 🙋🏻

     

    우선 적용해보기 전에 기본적으로 적용되지 않은 뷰부터 보겠습니다.

    private struct BasicView: View {
      @State var num: Int = 100
      
      var body: some View {
        VStack(spacing: 10) {
          HStack {
            Text("Number is")
              .font(.system(size: 32))
            
            Spacer()
            
            Text("\(num)")
              .font(.system(size: 32))
              .border(.green)
            
          }
          .border(.red)
          .padding(.horizontal, 90)
          
          Button(
            action: {
              num = .random(in: 100...999)
            },
            label: {
              Text("Change Number")
            }
          )
        }
      }
    }

    해당 num가 버튼 터치 시 계속 변경되는 뷰가 있어요!

     

    먼저 시뮬레이터에서 뷰의 변화를 보시죠.

     

    보시면 전체 프레임은 변하지 않지만 숫자 프레임에 제가 초록 색상으로 보더를 잡아두었어요.

    그런데 보더를 보시면 변하죠?

    즉, 숫자 Text의 width가 계속 변하게 되는것이죠!

    이는 1보다 9가 차지하는 너비가 커서 고정폭이 설정되지 않았기에 자꾸 변합니다.

    타이머 같이 계속 시간이 변화될때 마다 이 폭이 흔들리거나 움직이면 뷰가 너무 어색하겠죠? 🫠

     

    그럼 이제 한번 monospaced를 적용해 어색하지 않게 만들어볼까요?

     

    monospaced 적용하기

    private struct MonospacedView: View {
      @State var num: Int = 100
      
      var body: some View {
        VStack(spacing: 10) {
          HStack {
            Text("Number is")
              .font(.system(size: 32))
            
            Spacer()
            
            Text("\(num)")
              .font(.system(size: 32))
              .border(.green)
            
          }
          .border(.red)
          .padding(.horizontal, 70)
          🙋🙋🙋🙋🙋🙋
          .monospaced()
          
          Button(
            action: {
              num = .random(in: 100...999)
            },
            label: {
              Text("Change Number")
            }
          )
        }
      }
    }

    Number is Text와 변화하는 num Text를 감싼 HStack에 적용시킬 수 있습니다.

    그럼 내부에 Text들은 모두 고정폭을 가지게 되죠.

     

    한번 시뮬레이터에서 볼까요?

     

     

    이제 숫자 영역의 폭이 고정이기에 초록색 보더가 움직이지 않는걸 확인할 수 있어요!

    즉, 1과 9 모두 같은 32 사이즈의 시스템 폰트 고정폭을 가지기에 어색하지 않죠ㅎㅎ

    그런데 보시면 Number is도 동일한 고정폭으로 설정되어 있잖아요..?

     

    만약 나는 숫자에 해당하는 Text만 고정폭을 쓰고 싶어~ 한다면 뭘 사용하면 좋을까요?
    물론 HStack에서 선언하지 않고 해당 숫자 Text에만 붙여도 되지만 항상 Text를 그렇게 분리하기도 귀찮잖아요?

     

    monospacedDigit

    공식문서 ㄱㄱ~

     

    고정 너비 숫자를 사용하는 수정된 폰트를 반환하고 다른 문자는 비례 간격으로 둡니다.

    즉, 숫자만 고정 폭을 사용한다~ 이말이네요!

     

    func monospacedDigit() -> Font

    이렇게 간단히 호출하고 Font를 반환합니다.

     

    다행인건 이 메서드는 iOS 13 이상이면 사용할 수 있어요.
    즉 SwiftUI 환경에선 다 사용할 수 있다는 말! 👍

     

    그 외 추가적인 디스크립션은 monospaced와 거의 동일함으로 바로 적용해보죠!

     

    monospacedDigit 적용하기

    private struct MonospacedDigitView: View {
      @State var num: Int = 100
      
      var body: some View {
        VStack(spacing: 10) {
          HStack {
            Text("Number is")
              .font(.system(size: 32))
            
            Spacer()
            
            Text("\(num)")
              .font(.system(size: 32))
              .border(.green)
            
          }
          .border(.red)
          .padding(.horizontal, 70)
          🙋🏻🙋🏻🙋🏻🙋🏻🙋🏻🙋🏻🙋🏻🙋🏻
          .monospacedDigit()
          
          Button(
            action: {
              num = .random(in: 100...999)
            },
            label: {
              Text("Change Number")
            }
          )
        }
      }
    }

    간단하죠?

     

    정상적인지 시뮬레이터에서 볼까요?

     

    아주 정상적 ㅎㅎ

    문자는 비례되어 폭이 정해지고 숫자는 고정폭으로 잘 적용되네요!

     

    자 그럼 마지막으로, 아까 monospaced를 살펴볼때 메서드로 붙이지 않고 Font 모디파이어를 붙여줄때 옵션을 줄 수 있다고 했습니다.
    그거 봐보시죠 🕺🏻

     

    Font 모디파이어에서 design 옵션으로 설정하기

    private struct FontMonospacedView: View {
      @State var num: Int = 100
      
      var body: some View {
        VStack(spacing: 10) {
          HStack {
            Text("Number is")
              🙋🏻🙋🏻🙋🏻🙋🏻🙋🏻🙋🏻
              .font(.system(size: 32, design: .serif))
            
            Spacer()
            
            Text("\(num)")
              🙋🏻🙋🏻🙋🏻🙋🏻🙋🏻🙋🏻
              .font(.system(size: 32, design: .monospaced))
              .border(.green)
            
          }
          .border(.red)
          .padding(.horizontal, 70)
          
          Button(
            action: {
              num = .random(in: 100...999)
            },
            label: {
              Text("Change Number")
            }
          )
        }
      }
    }

    보시는것처럼 이렇게 각 시스템 32 크기 폰트를 선언 시 design 옵션으로 어떤 스타일을 줄것인지 넣을 수 있어요.

    monospaced가 기본적으로 제공되죠!

     

    저기 들어가는 design 옵션은 총 4가지 입니다.

     

    1️⃣ default

    2️⃣ serif - 획의 끝이 뾰족한 형태

    3️⃣ rouned - 둥근 형태

    4️⃣ monospaced - 우리가 살펴본 고정폭 형태

     

    원하는 옵션을 잘 사용해서 더 적합한 폰트를 사용해봐도 좋겠네요!

     

    그럼 이제 위 코드를 시뮬레이터 정상적으로 의도대로 되는지 확인해보시죠 😃

     

    아주 정상적 😉

     

    마무리

    쉽게 SwiftUI Font 고정폭에 대해 다가가봤어요!

    참고로 해당 샘플 프로젝트는 아래 제 깃헙 레포에 올려두었으니 참고하셔도 좋습니다!

    https://github.com/GREENOVER/playground/tree/main/monospacedDigit

     

    참고 자료

    https://developer.apple.com/documentation/swiftui/font/monospaced() 

     

    monospaced() | Apple Developer Documentation

    Returns a fixed-width font from the same family as the base font.

    developer.apple.com

    https://developer.apple.com/documentation/swiftui/font/monospaceddigit() 

     

    monospacedDigit() | Apple Developer Documentation

    Returns a modified font that uses fixed-width digits, while leaving other characters proportionally spaced.

    developer.apple.com

    https://developer.apple.com/documentation/swiftui/font/system(_:design:weight:) 

     

    system(_:design:weight:) | Apple Developer Documentation

    Gets a system font that uses the specified style, design, and weight.

    developer.apple.com

Designed by Tistory.