SwiftUI:如何使 TextField 适合多行内容?

Posted

技术标签:

【中文标题】SwiftUI:如何使 TextField 适合多行内容?【英文标题】:SwiftUI: How do I make TextField fit multi-line content? 【发布时间】:2019-10-25 09:01:04 【问题描述】:

在附加的代码示例中,我的 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

如果我将“让内容”行更改为

,这是示例
let content = "content"

【问题讨论】:

添加.lineLimit(nil)并检查 @Anbu.Karthik 感谢您的意见,但这并没有什么不同 据我所知,有使用文本字段进行这种动态行扩展的解决方案。而是使用文本视图。 更糟糕的是,如果您设置更大的框架,内容将无法完全显示....对我来说看起来像苹果错误​​ 【参考方案1】:

似乎没有直接的论据来正确管理多行填充。他们可能不发达。但以下内容将为您提供一个直接的解决方案来满足您的期望。

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 以实现您想要的。希望它也对你有用。

【讨论】:

谢谢,听起来这一定是前进的方向。但是,执行此操作时,我收到警告“在视图更新期间修改状态,这将导致未定义的行为。”在 iPhone 模拟器上它给出了几乎正确的视图,在预览中它变得太小了,而在带有 Swift Playgrounds 的 iPad 上它变得太大了。 是的。您需要尽可能设置defaultHeight。基本上,您只需为不同大小的类提供不同的值。如您所见,UITextView 未在 SwiftUI 中实现,如果您现在确实需要多行,我建议您使用 Text 作为显示输出,它可以很好地管理多行,同时使用文本字段进行单行输入。这意味着显示文本字段,而不是显示文本。当您单击它时,您可以将其替换为单独的文本字段。

以上是关于SwiftUI:如何使 TextField 适合多行内容?的主要内容,如果未能解决你的问题,请参考以下文章

使 SwiftUI TextField 足够大以容纳字符串

如何使文本适合圆形/图像SwiftUI的边界

SwiftUI:TextField 内的填充

删除第一个字符时,SwiftUI TextField 冻结

SwiftUI如何让绑定到同一个状态的多个TextField呈现出不同输入行为

SwiftUI如何让绑定到同一个状态的多个TextField呈现出不同输入行为