如何在SwiftUI视图中将TextField与带有空白下划线的空间结合起来

huangapple go评论55阅读模式
英文:

How to incorporate TextField with blank underlined space in SwiftUI view

问题

以下是翻译好的代码部分:

struct dialogueCaptionBoxWithQuestion: View {
    
    var questionPart1: String
    var questionPart2: String
    var correctChosen: Bool
    var answer: String
    
    @Binding var userInput: String
    @Binding var currentQuestionNumber: Int
    
    var body: some View{
        
        HStack {
            if !correctChosen {
                Text(questionPart1)
                    .font(Font.custom("Chalkboard SE", size: 15)) +
                Text(userInput)
                    .font(Font.custom("Chalkboard SE", size: 15))
                    .foregroundColor(.black)
                    .underline(color: .black.opacity(1.0)) +
                Text(questionPart2)
                    .font(Font.custom("Chalkboard SE", size: 15))
            }else {
                Text(questionPart1)
                    .font(Font.custom("Chalkboard SE", size: 15)) +
                
                Text("  " + answer + "  ")
                    .font(Font.custom("Chalkboard SE", size: 15))
                    .foregroundColor(.black)
                    .underline(color: .black.opacity(1.0)) +
                Text(questionPart2)
                    .font(Font.custom("Chalkboard SE", size: 15))
            }
        }.frame()
            .padding([.top, .bottom], 10)
            .padding([.leading, .trailing], 20)
            .foregroundColor(.black)
            .background(.white)
            .cornerRadius(10)
            .shadow(radius: 5)
        
    }
}
英文:

I'm trying to do a type of fill in the blank question. I have a question that pops up that I want to look like

"This is a question and the answer is __________ that you will type in"

The issue is I have a text field at the bottom of the page for the user to input their answer and then press enter. However, I wanted the blank space in the question to be dynamically filled with the user input in the text field. I know this can be done with a simple binding to the text field but I'm not sure how to make that work with the question's underlined blank space.

This is what I have so far

struct dialogueCaptionBoxWithQuestion: View {

var questionPart1: String
var questionPart2: String
var correctChosen: Bool
var answer: String

@Binding var userInput: String
@Binding var currentQuestionNumber: Int

var body: some View{
    
    HStack {
        if !correctChosen {
            Text(questionPart1)
                .font(Font.custom("Chalkboard SE", size: 15)) +
            Text(userInput)
                .font(Font.custom("Chalkboard SE", size: 15))
                .foregroundColor(.black)
                .underline(color: .black.opacity(1.0)) +
            Text(questionPart2)
                .font(Font.custom("Chalkboard SE", size: 15))
        }else {
            Text(questionPart1)
                .font(Font.custom("Chalkboard SE", size: 15)) +
            
            Text("  " + answer + "  ")
                .font(Font.custom("Chalkboard SE", size: 15))
                .foregroundColor(.black)
                .underline(color: .black.opacity(1.0)) +
            Text(questionPart2)
                .font(Font.custom("Chalkboard SE", size: 15))
        }
    }.frame()
        .padding([.top, .bottom], 10)
        .padding([.leading, .trailing], 20)
        .foregroundColor(.black)
        .background(.white)
        .cornerRadius(10)
        .shadow(radius: 5)
    
}

}

答案1

得分: 1

如果你想通过连接Text字段来实现,那么下划线可能是你最好的选择。实际上,你已经在使用它了,所以你只需要添加填充来增加不完整答案的长度:

Text(userInput.padding(
    toLength: max(userInput.count, 15),
    withPad: " ",
    startingAt: 0
))
.font(Font.custom("Chalkboard SE", size: 15))
.foregroundColor(.black)
.underline(color: .black.opacity(1.0)) +

然而,这不是一个很好的解决方案,因为你正在使用比例字体,所以文本字段的宽度会随着用户输入答案而不断变化。

也许考虑一个不受这些问题影响的不同设计会更好。例如,你可以使用一个包含不完整答案的VStack,位于questionPart1和questionPart2之间。这样,你可以按自己的喜好进行样式化,并应用一个固定的宽度。

顺便说一句,不需要将userInput作为Binding传递,因为它是一个只读视图。只有在需要写入更改时,才需要它作为Binding。另外,将字体应用于容器而不是每个单独的Text字段可能更简单。你的使用.frame()也已经过时了,但也许这是因为你将原始代码精简为提供示例。

英文:

If you want to do it by concatenating Text fields then underline is perhaps your best bet. You're actually using this already, so you just need to add padding to increase the length of the incomplete answer:

    Text(userInput.padding(
        toLength: max(userInput.count, 15),
        withPad: " ",
        startingAt: 0
    ))
    .font(Font.custom("Chalkboard SE", size: 15))
    .foregroundColor(.black)
    .underline(color: .black.opacity(1.0)) +

However, this is not a great solution because you're using a proportional font, so the width of the Text field is always changing as the user enters their answer.

Perhaps it would be better to consider a different design that is not affected by these issues. For example, you could use a VStack with the incomplete answer sandwiched between questionPart1 and questionPart2. That way, you can style it any way you like and also apply a fixed width.

Btw, there is no need to pass the userInput as a Binding because it's a read-only view. It only needs to be a Binding if you want to be able to write changes to it. Also, it would be simpler to apply the font to the container instead of to each individual Text field. Your use of .frame() is deprecated too, but maybe that's because you cut down your original code to provide the example.

huangapple
  • 本文由 发表于 2023年6月19日 00:50:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/76501627.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定