SwiftUI案例:尺寸自适应文本框
效果
目标
- 实现文本框可以单行、多行输入的功能并可以自使用文本内容的高度
思路突破
SwiftUI
并未提供可自适应高度的文本框组件,为实现自适应高度则需要继承 UITextField
进而自定义封装一个弹性的文本框组件。
通过更新函数,从该弹性文本框中获得文本内容的高度并将其赋值给组件的高度,即可实现“弹性”伸缩的效果。
视图实现
代码语言:javascript复制import SwiftUI
struct ContentView: View {
var body: some View {
Home()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct Home: View {
@State var text = ""
//自动更新的文本框高度
@State var containHeight: CGFloat = 0
var body: some View {
//导航区视图控制
NavigationView {
//使用垂直布局
VStack {
//调用自定义组件AutoSizingTF
AutoSizingTF(
hint: "请输入内容...",
text: $text,
containerHeight: $containHeight,
onEnd: {
//当键盘被关闭时调用该方法
UIApplication
.shared
.sendAction(
#selector(
UIResponder.resignFirstResponder
),
to: nil,
from: nil,
for: nil
)
}
)
.padding(.horizontal)
.frame(height: containHeight < 120 ? containHeight : 120)
.background(Color.white)
.cornerRadius(10)
.padding()
}
//导航区域的头部文本信息
.navigationTitle("在输入框中输入文本")
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.primary.opacity(0.04).ignoresSafeArea())
}
}
}
//封装自适应文本框组件AutoSizingTF
struct AutoSizingTF: UIViewRepresentable {
//参数列表
var hint: String //Placeholder占位
@Binding var text: String //文本
@Binding var containerHeight: CGFloat //文本框高度
var onEnd : () -> () //尾随闭包函数
func makeCoordinator() -> Coordinator {
return AutoSizingTF.Coordinator(parent: self)
}
func makeUIView(context: Context) -> UITextView {
let textView = UITextView() //实例化文本框组件
//原生组件样式控制
textView.text = hint
textView.textColor = .gray
textView.backgroundColor = .clear
textView.font = .systemFont(ofSize: 20)
textView.delegate = context.coordinator
//定义输入框附件toolbar(工具栏)并使用默认样式
let toolBar = UIToolbar(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50))
toolBar.barStyle = .default
//使用另一个spacer作为间隔来使得done完成按钮布局在右侧
let spacer = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
//定义done完成按钮
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: context.coordinator, action: #selector(context.coordinator.closeKeyBoard))
toolBar.items = [spacer, doneButton]
toolBar.sizeToFit()
textView.inputAccessoryView = toolBar
//返回这个UIViewRepresentable组件
return textView
}
func updateUIView(_ uiView: UITextView, context: Context) {
//自适应文本高度函数
DispatchQueue.main.async {
if containerHeight == 0 {
//将内容文本的高度赋值给弹性文本框的高度变量
containerHeight = uiView.contentSize.height
}
}
}
class Coordinator: NSObject, UITextViewDelegate {
//读取所有的父属性
var parent: AutoSizingTF
init(parent: AutoSizingTF) {
self.parent = parent
}
//键盘关闭时
@objc func closeKeyBoard() {
parent.onEnd()
}
func textViewDidBeginEditing(_ textView: UITextView) {
if textView.text == parent.hint {
textView.text = ""
textView.textColor = UIColor(Color.primary)
}
}
func textViewDidChange(_ textView: UITextView) {
parent.text = textView.text
parent.containerHeight = textView.contentSize.height
}
//检查文本框是否内容为空,如果为空则用hint的值覆盖
func textViewDidEndEditing(_ textView: UITextView) {
if textView.text == "" {
//覆盖组件
textView.text = parent.hint
textView.textColor = .gray
}
}
}
}
源码
Auto-Sizing-TextField.zip
来源:百度网盘 | 提取码:eh5c
Auto-Sizing-TextField.zip
来源:蓝奏云网盘 | 提取码:dvqr