source

Swift를 사용하여 상위 보기에 맞게 텍스트 크기를 조정하는 방법UI?

manycodes 2023. 8. 4. 23:10
반응형

Swift를 사용하여 상위 보기에 맞게 텍스트 크기를 조정하는 방법UI?

원 뷰 내부에 텍스트 뷰를 작성하려고 합니다.글꼴 크기는 원의 크기에 맞게 자동으로 설정되어야 합니다.스위프트에서 어떻게 이것이 가능합니까?UI? 크기 조정 ToFill 및 크기 조정 ToFit 수식자를 시도했지만 텍스트 보기에는 영향을 주지 않습니다.

struct ContentView : View {
    var body: some View {
        ZStack {
            Circle().strokeBorder(Color.red, lineWidth: 30)
            Text("Text").scaledToFill()
        }
    }
}

한 가지 가능한 "해킹"은 큰 글꼴 크기와 작은 스케일 팩터를 사용하여 자체적으로 축소하는 것입니다.

ZStack {
    Circle().strokeBorder(Color.red, lineWidth: 30)

    Text("Text")
        .padding(40)
        .font(.system(size: 500))
        .minimumScaleFactor(0.01)
     }
}

텍스트를 허용할 대상:

  • 어느 정도까지 움츠러들다.
  • 한 줄(또는 여러 줄)로

필요에 따라 이 척도 요인 한계를 선택합니다.일반적으로 읽을 수 없을 정도로 줄어들거나 설계를 나쁘게 보이게 하는 한계를 넘지 않습니다.

struct ContentView : View {
var body: some View {
    ZStack {
        Circle().strokeBorder(Color.red, lineWidth: 30)
        Text("Text")
            .scaledToFill()
            .minimumScaleFactor(0.5)
            .lineLimit(1)
    }
}

}

사용할 수 있음GeometryReader가로 모드에서도 작동할 수 있도록 합니다.

너비나 높이가 더 작은지 먼저 확인한 다음 이들 중 작은지에 따라 글꼴 크기를 조정합니다.

GeometryReader{g in
    ZStack {
        Circle().strokeBorder(Color.red, lineWidth: 30)
        Text("Text")
            .font(.system(size: g.size.height > g.size.width ? g.size.width * 0.4: g.size.height * 0.4))
    }
}

enter image description here enter image description here

원뿐만 아니라 모든 보기에 적용할 수 있는 사용자 지정 수정자에 텍스트 크기 조정 코드를 숨기고 텍스트가 차지해야 하는 보기 부분을 지정하는 매개 변수를 사용하는 솔루션이 있습니다.

(나는 @szemian의 솔루션이 여전히 이상적이지는 않지만, 그녀의 방법이 현재 Swift로 우리가 할 수 있는 최선인 것 같다는 것에 동의해야 합니다.다른 것들에 내재된 문제로 인한 UI 구현.@simibac의 답변은 텍스트 또는 텍스트 속성(숫자, 가중치 등)이 변경될 때마다 0.4를 대체할 새로운 마법 번호를 찾기 위해 만지작거려야 하며, @simibac's는 원의 크기를 지정할 수 없으며 텍스트의 글꼴 크기만 지정할 수 있습니다.)

struct FitToWidth: ViewModifier {
    var fraction: CGFloat = 1.0
    func body(content: Content) -> some View {
        GeometryReader { g in
        content
            .font(.system(size: 1000))
            .minimumScaleFactor(0.005)
            .lineLimit(1)
            .frame(width: g.size.width*self.fraction)
        }
    }
}

수식어를 사용하면 코드는 다음과 같이 됩니다.

    var body: some View {
        Circle().strokeBorder(Color.red, lineWidth: 30)
            .aspectRatio(contentMode: .fit)
            .overlay(Text("Text")
                .modifier(FitToWidth(fraction: fraction)))
    }

또한 Xcode의 미래 버전이 Swift를 제공할 때사용자 인터페이스의 향상된 기능을 통해.minimumScaleFactorhack, 수식어 코드만 업데이트해서 사용하시면 됩니다 :)

분수 매개변수의 작동 방식을 보려면 슬라이더를 사용하여 대화식으로 조정할 수 있는 코드를 다음에 제시된 코드는 다음과 같습니다.

struct ContentView: View {

    @State var fraction: CGFloat = 0.5

    var body: some View {
        VStack {
            Spacer()
            Circle().strokeBorder(Color.red, lineWidth: 30)
                .aspectRatio(contentMode: .fit)
                .overlay(Text("Text")
                .modifier(FitToWidth(fraction: fraction)))
            Slider(value: $fraction, in:0.1...0.9, step: 0.1).padding()
            Text("Fraction: \(fraction, specifier: "%.1f")")
            Spacer()
        }
    }
}

그리고 이것은 다음과 같습니다.

Code running on iPhone X

저는 고정된 크기의 버튼을 가지고 있었고 이것은 제가 긴 텍스트를 자동으로 줄일 수 있게 해주었습니다.

Text("This is a long label that will be scaled to fit:")
    .lineLimit(1)
    .minimumScaleFactor(0.5)

출처: 애플

저는 @Simibac과 @Anton의 답변을 섞었지만 iOS 14.0에 의해 깨졌습니다. 그래서 이것은 제가 그것을 고치기 위해 한 것입니다.Swift에 대해 작업해야 합니다.UI 1.0도 마찬가지입니다.

struct FitSystemFont: ViewModifier {
    var lineLimit: Int
    var minimumScaleFactor: CGFloat
    var percentage: CGFloat

    func body(content: Content) -> some View {
        GeometryReader { geometry in
            content
                .font(.system(size: min(geometry.size.width, geometry.size.height) * percentage))
                .lineLimit(self.lineLimit)
                .minimumScaleFactor(self.minimumScaleFactor)
                .position(x: geometry.frame(in: .local).midX, y: geometry.frame(in: .local).midY)
        }
    }
}

의 보다시피기프사를록다니습을 했습니다.frame(in:) 공간을 을 사용합니다..midX그리고..midY을 잡는은 iOS 된 중심을 잡는 것이기 입니다. iOS 14는 저에게 부서졌습니다.

저는 그런다확설다니정합장을음에 했습니다.View:

extension View {
    func fitSystemFont(lineLimit: Int = 1, minimumScaleFactor: CGFloat = 0.01, percentage: CGFloat = 1) -> ModifiedContent<Self, FitSystemFont> {
        return modifier(FitSystemFont(lineLimit: lineLimit, minimumScaleFactor: minimumScaleFactor, percentage: percentage))
    }
}

사용법은 다음과 같습니다.

Text("Your text")
    .fitSystemFont()

@JaimeeAz 답변을 기반으로 구축.최소 글꼴을 지정하는 옵션이 추가되었습니다.

import SwiftUI

public struct FitSystemFont: ViewModifier {
    public var lineLimit: Int?
    public var fontSize: CGFloat?
    public var minimumScaleFactor: CGFloat
    public var percentage: CGFloat

    public func body(content: Content) -> some View {
        GeometryReader { geometry in
            content
                .font(.system(size: min(min(geometry.size.width, geometry.size.height) * percentage, fontSize ?? CGFloat.greatestFiniteMagnitude)))
                .lineLimit(self.lineLimit)
                .minimumScaleFactor(self.minimumScaleFactor)
                .position(x: geometry.frame(in: .local).midX, y: geometry.frame(in: .local).midY)
        }
    }
}

public extension View {
    func fitSystemFont(lineLimit: Int? = nil, fontSize: CGFloat? = nil, minimumScaleFactor: CGFloat = 0.01, percentage: CGFloat = 1) -> ModifiedContent<Self, FitSystemFont> {
        return modifier(FitSystemFont(lineLimit: lineLimit, fontSize: fontSize, minimumScaleFactor: minimumScaleFactor, percentage: percentage))
    }
}

이를 달성하기 위해 당신은 필요하지 않습니다.ZStack에음배추수있다니습가에 할 수 .Text:

Text("Text text text?")
    .padding()
    .background(
       Circle()
          .strokeBorder(Color.red, lineWidth: 10)
          .scaledToFill()
          .foregroundColor(Color.white)
    )

결과는 다음과 같습니다.

저도 타이머와 같은 문제가 있었습니다.불행하게도 타이머는 1초에 한 번씩 텍스트를 변경합니다. 그래서 텍스트는 항상 이리저리 뛰어다니며 위아래로 조정됩니다.제 접근 방식은 "-44:44"의 경우 표시할 수 있는 가장 긴 타이머와 227.7pt의 큰 프레임을 만들 수 있는 50pt 크기를 계산하는 것이었습니다.227을 50으로 나눈 값(이전에 사용했던 포인트 크기)으로 포인트 크기당 4.5(원형 내림)의 폭입니다.주의: 1pt 크기로 5.3 포인트의 큰 프레임을 제공했습니다. 따라서 글꼴이 클수록 프레임 없이 실제 텍스트 크기에 더 가깝습니다.

지오메트리 판독기를 사용하고 있었기 때문에 간단히 고정된 텍스트 크기를 설정할 수 있었습니다.

Text("-44:44:44")
.font(.system(size: geometry.size.width / 4.5))

완벽하게 잘 작동합니다. '-'가 없거나 표시된 시간이 없으면 왼쪽과 오른쪽에 약간의 공간이 있지만 텍스트가 이리저리 이동하지 않습니다.

이는 표시된 자릿수에 따라 다른 스케일 계수로 정제할 수 있으므로 "-mm:ss"에 대한 또 다른 스케일 계수입니다.이렇게 하면 시간이 표시되거나 숨겨져 있을 때 "점프"가 발생할 수 있지만, 제가 필요로 하는 경우에는 거의 발생하지 않습니다.

언급URL : https://stackoverflow.com/questions/57035746/how-to-scale-text-to-fit-parent-view-with-swiftui

반응형