目录

单行输入和密码输入 TextField SecureField

        示例

        双向绑定 $变量

        预设格式 textFieldStyle

        内容类型 textContentType

        设置键盘类型 keyboardType

        禁止自动纠正 disableAutocorrection

再谈Padding

再谈text

关闭键盘 取消焦点

背景覆盖 overlay

多行编辑 TextEditor

        介绍

        综合示例


单行输入和密码输入 TextField SecureField

        示例

        单行输入使用TextField和SecureField,区别是SecureField会用*代替输入的字符。

        代码:

struct SwiftUIViewTextField: View {
    @State var str: String = ""
    var body: some View {
        VStack(alignment: .leading, spacing: 20) {
            Text("\(str)").frame(minWidth: 120).border(.blue)
            TextField("Hello, World!", text: $str)
                .border(.blue)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .textContentType(.telephoneNumber)
                .keyboardType(.numberPad)
                .disableAutocorrection(true)
                .padding()
            SecureField("请输入密码", text: $str).border(.blue)
        }.padding().border(.red)
    }
}

        效果:

        双向绑定 $变量

        之前我们用过@State变量来自动刷新界面,输入型视图要把输入的内容保存到变量去需要不同的绑定方式,增加符号“$”,实现双向绑定。

TextField("Hello, World!", text: $str)

        因为例子中Text和SecureField也绑定到同一个变量,所以三个框会同步变化。

        预设格式 textFieldStyle

        textFieldStyle的参数指示预设的格式,比如RoundedBorderTextFieldStyle(),圆角带Padding(注意由于设置了border,失去了圆角,这是个冲突)。内置变量.roundedBorder也是一样的。

        其余格式PlainTextFieldStyle(或内置变量.plain)和DefaultTextFieldStyle(或内置变量.automatic)差不多,不用设置。

        内容类型 textContentType

        这是给系统的提示,而不是对内容的约束。系统会根据提示调整键盘的细节,改善用户体验(然而莫名其妙的变化会伤害用户体验)。使用什么键盘是需要自己设置的。

        .telephoneNumber 电话号码。

        设置键盘类型 keyboardType

        一般用到的就是指定数字键盘:

.keyboardType(.numberPad)

        禁止自动纠正 disableAutocorrection

        什么时候他们才会意识到全人类都痛恨自动纠正啊。

.disableAutocorrection(true)

再谈Padding

        padding是填充的意思,在四周增加空白,但具体效果不同对象有所不同。

        上面的示例给VStack和TextField都设置了Padding和Border,但是明显看出对VStack,填充是在边框之内,而对于TextField,填充却在边框之外,似乎缺乏统一的概念设计。

再谈text

        我们注意到text是跟随内容自动变化的,示例代码强制了最小宽度,有内容的时候高度会变大,整个VStack的边框也会变大(红色),这种灵活的效果我不是很习惯。

关闭键盘 取消焦点

        我们会发现很多应用输入完数据后键盘不会消失,导致部分界面被遮盖,无法进行下一步。这是因为输入框不会在点击外部空白区域时失去焦点,从而系统认为仍然处于输入状态。

        解决方法很简单,输入框有个.focused($isFocus),参数是绑定的布尔变量,用来指示或控制输入框的状态,我们只需要在点击输入框外部空白时将绑定变量设置为false即可。

    @FocusState private var isFocus: Bool //绑定变量

    var body: some View 
    {
        VStack
        {
            TextField(。。。。。。)
                .focused($isFocus)//设置绑定变量
        }
        .padding()
        .border(.red)
        .background(.green) //这句挺重要
        .ignoresSafeArea(.all)
        .onTapGesture 
        {
            isFocus = false //取消焦点
        }
    }

        代码不复杂,在外层的onTapGesture设置代码即可,一般应该在最外层的容器上做。

        里面有一句设置了最外层容器的背景色,标注了“这句挺重要”,为什么呢?因为没有这一句时似乎系统认为顶级容器挺小的,取消焦点这个功能不是很灵,加了这一句就很灵了。注意任何情况下点击顶部安全区都无效,不论是否使用了.ignoresSafeArea(.all)。有一点奇怪,对于VStack,忽略安全区将导致边界正确显示在屏幕最外围,与ZStack不同。

        不论是否使用了.ignoresSafeArea(.all),顶级的背景色都是全屏的。

        关闭键盘还有些不同的方法,这个方法是官方推荐的方法(但是仍然不是很理想)。

背景覆盖 overlay

        可以用overlay修饰TextField,overlay的参数是视图。修改一下之前的TextField:

            TextField("Hello, World!", text: $str)
                .font(.system(size: 80))
                .border(.blue)
                .textFieldStyle(.roundedBorder)
                .textContentType(.telephoneNumber)
                .keyboardType(.numberPad)
                .disableAutocorrection(true)
                //.padding()
                .overlay(
                    HStack {
                        Image(systemName: "magnifyingglass")
                            .font(.system(size: 80))
                        Spacer()
                    }
                )

        效果:

        其实也不是啥好主意。

多行编辑 TextEditor

        介绍

        多行编辑有两点很不同:没有placeholder参数,默认大小是尽可能大。

        还有一点也很不同:必须先隐藏默认背景才能设置背景。(.scrollContentBackground(.hidden))

        综合示例

        这个例子包含了本篇全部内容:

import SwiftUI

struct SwiftUIViewTextField: View {
    @State var str: String = ""
    @FocusState private var isFocus: Bool
    var body: some View {
        VStack(alignment: .leading, spacing: 20) {
            Spacer()
            Text("\(str)")
                .frame(minWidth: 120)
                .border(.blue)
                .background(.blue)
                .foregroundStyle(.red)
            TextField("Hello, World!", text: $str)
                .font(.system(size: 80))
                .border(.blue)
                .textFieldStyle(.roundedBorder)
                .textContentType(.telephoneNumber)
                .keyboardType(.numberPad)
                .disableAutocorrection(true)
                //.padding()
                .overlay(
                    HStack {
                        Image(systemName: "magnifyingglass")
                            .font(.system(size: 80))
                        Spacer()
                    }
                )
                .focused($isFocus)
            SecureField("请输入密码", text: $str)
                .border(.blue)
            TextEditor(text:$str) //第一个多行文本,设置了背景色和前景色,默认大小
                .scrollContentBackground(.hidden)
                .background(.gray)
                .foregroundStyle(.red)
            TextEditor(text:$str) //第二个多行文本,指定了最大高度
                .border(.red)
                .frame(maxHeight:80)
            
            Spacer()
        }
        .padding()
        .border(.red)
        .background(.green)
        //.ignoresSafeArea(.all)
        .onTapGesture {
            isFocus = false
        }
    }
}

        效果:

        我们可以看到,Text是能显示多行的,TextField则把多行显示在一行,换行变成了空白。Text很简单地设置了背景色,TextEditor则必须禁用默认背景才能显示自己设置的背景色。TexeEditor的默认大小是尽可能大的。

更多推荐