SwiftUI: Как сделать так, чтобы TextField соответствовал многострочному контенту? - PullRequest
1 голос
/ 25 октября 2019

В прилагаемом примере кода я получаю много лишних пробелов в моем TextField. Если я изменю содержимое на одну строку, скажем «содержимое», то оно уместится плотно. Как я могу получить такое же удобное поведение, как у одной строки для многострочного текста?

Предварительный просмотр и код были сделаны с помощью Xcode 11.1 / Swift 5.1

import SwiftUI

struct TextFieldDemo: View {
    var content: Binding<String>

    init(content: Binding<String>) {
        self.content = content
    }

    var body: some View {
        TextField("Custom placeholder", text: content)
            .background(Color.yellow)
    }
}

#if DEBUG
struct TextInputRowPreviews: PreviewProvider {

    static var previews: some View {
        let content = "content\ncontent\ncontent\ncontent\ncontent\ncontent"
        return TextFieldDemo(content: .constant(content))
                .previewLayout(.sizeThatFits)
    }
}
#endif

Screenshot of preview when content is multi-line

Вот пример, если я изменю строку «let content» на

let content = "content"

Screenshot of preview when content is single-line

1 Ответ

1 голос
/ 25 октября 2019

Кажется, нет прямого аргумента для правильного управления многострочным заполнением. Возможно, они недоразвиваются. Но следующее даст вам прямое решение для обхода того, что вы ожидаете.

extension String{
    var extraLines : String{ get{
         return self +  String(repeating:"\n",  count: self.components(separatedBy:  "\n").count - 1)
    }}
 }


struct TextFieldDemo: View {
var content: Binding<String>

init(content: Binding<String>) {
    self.content = content
}

@State var height : CGFloat? //current height

let constHeightRatio : CGFloat = 0.55 //use for assembly with other fonts.
let defaultHeight : CGFloat = 250 //use for assembly with other views.

var body: some View {
    TextField("Custom placeholder", text: content).environment(\.multilineTextAlignment, .center).alignmentGuide(.bottom) { (ViewDimensions) -> CGFloat in
        if self.height == nil {self.height = ViewDimensions.height}
            return  ViewDimensions.height
    }.frame( height: (height ?? defaultHeight) * constHeightRatio, alignment: .bottom).background(Color.yellow)
}
}



#if DEBUG
struct TextInputRowPreviews: PreviewProvider {

static var previews: some View {
    let content = "content\ncontent\ncontent".extraLines
    return
         TextFieldDemo(content: .constant(content))
}
}
#endif

Это прекрасно работает для одиночного просмотра. Если требуется сборка вида (с другими стеками и т. Д.), Вы можете настроить defaultHeight и / или constHeightRatio, чтобы добиться того, что вы хотите. Надеюсь, это работает и для вас.

...