使用 TextEditor 模仿 iMessage 的行为进行文本输入 [英] Mimicking behavior of iMessage with TextEditor for text entry

查看:24
本文介绍了使用 TextEditor 模仿 iMessage 的行为进行文本输入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 Stack Overflow 遇到的第一个问题.

My first ever question here at Stack Overflow.

我正在为 iOS 和 macOS 编写一个小应用程序.文本输入是通过(现在)一个 TextField 和一个 Button 完成的.TextField 的问题在于它是单行并且不允许多行文本输入.因此,我尝试使用 TextEditor 代替,但我可以将其设置为不随着添加更多文本而增长,或者一开始就显示得很大.我想说的是,理想情况下,它会模仿 iMessage 中的文本条目的行为:开始时与 TextField 的大小相同,但如果需要的话会增长以容纳多行文本,例如 文本编辑器.

I'm writing a small application for iOS and macOS. Text entry is done via (now) a TextField and a Button. The issue with the TextField is that it's a single line and doesn't allow for multiline text entry. So, I tried using TextEditor instead, but I can either set it up to not grow as more text is added, or it shows up very big to begin with. What I'm saying is that ideally, it would mimic the behavior that the text entry in iMessage has: starts as the same size of a TextField but grows if needed to accommodate a multiline text like a TextEditor.

这是我用于此视图的代码:

Here's the code I am using for this view:

var inputView: some View {
        HStack {
            ZStack {
                //tried this here... 
                //TextEditor(text: $taskText)
                TextField("New entry...", text: $taskText, onCommit: { didTapAddTask() })
                    .frame(maxHeight: 35)
                    .padding(EdgeInsets(top: 0, leading: 12, bottom: 0, trailing: 0))
                    .clipped()
                    .accentColor(.black)
                    .cornerRadius(8)
                    .textFieldStyle(RoundedBorderTextFieldStyle())
                Text(taskText).opacity(0).padding(.all, 8) 
            }
            
            Button(action: AddNewEntry, label: { Image(systemName: "plus.circle")
                    .imageScale(.large)
                    .foregroundColor(.primary)
                    .font(.title) }).padding(15).foregroundColor(.primary)
        }
    }

有什么办法吗?我尝试了其他用户在不同问题中发现的不同方法,但我不太清楚.

Any way of doing this? I tried different approaches found in different questions from other users, but I can't quite figure out.

外观如下:

TextEdit 的外观

我也尝试过类似的方法,并为 .frame 设置了不同的值:

I also have tried something like this and played with different values for the .frame:

        TextEditor(text: $taskText)
            .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 200)
            .border(Color.primary, width: 1)
            .padding(EdgeInsets(top: 0, leading: 12, bottom: 0, trailing: 0))

感谢任何帮助.

谢谢.

哦,我目前使用的是 Xcode 12.5.1,目标是 iOS 14.x 和 macOS Big Sur.

Oh, and I'm using Xcode 12.5.1 and target is iOS 14.x and macOS Big Sur for now.

编辑以回答 jnpdx.当我从 Dynamic TextEditor 与其他视图重叠添加代码时这是它的外观,它不会动态变化.

EDIT to answer jnpdx. When I add the code from Dynamic TextEditor overlapping with other views this is how it looks, and it does not change dynamically.

应用启动时的外观

键入文本时的外观

推荐答案

这是一个示例,使用带有 TextEditor 旁边的 Button 的原始代码.TextEditor 会一直增长,直到达到由 maxHeight 定义的限制.它还具有消息视图(因为您提到了 iMessage),但您可以轻松地将其删除.

Here's an example, using your original code with the Button next to the TextEditor. The TextEditor grows until it hits the limit, defined by maxHeight. It also has a view for the messages (since you mentioned iMessage), but you could easily remove that.

struct ContentView: View {
    @State private var textEditorHeight : CGFloat = 100
    @State private var text = "Testing text. Hit a few returns to see what happens"
    
    private var maxHeight : CGFloat = 250
    
    var body: some View {
        VStack {
            VStack {
                Text("Messages")
                Spacer()
            }
            Divider()
            HStack {
                ZStack(alignment: .leading) {
                    Text(text)
                        .font(.system(.body))
                        .foregroundColor(.clear)
                        .padding(14)
                        .background(GeometryReader {
                            Color.clear.preference(key: ViewHeightKey.self,
                                                   value: $0.frame(in: .local).size.height)
                        })
                    
                    TextEditor(text: $text)
                        .font(.system(.body))
                        .padding(6)
                        .frame(height: min(textEditorHeight, maxHeight))
                        .background(Color.black)
                }
                .padding(20)
                Button(action: {}) {
                    Image(systemName: "plus.circle")
                        .imageScale(.large)
                        .foregroundColor(.primary)
                        .font(.title)
                }.padding(15).foregroundColor(.primary)
            }.onPreferenceChange(ViewHeightKey.self) { textEditorHeight = $0 }
        }
    }
}


struct ViewHeightKey: PreferenceKey {
    static var defaultValue: CGFloat { 0 }
    static func reduce(value: inout Value, nextValue: () -> Value) {
        value = value + nextValue()
    }
}

这篇关于使用 TextEditor 模仿 iMessage 的行为进行文本输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆