@ViewBuilder 在自定义 View 中的使用
有时候我们要求一个 View 要有比较高的灵活性,它的一部分视图的内容需要灵活指定。比如这样的视图,它仅仅提供了一个“灰色背景”,中间的部分则可以由 View 的使用者自己定义:
那么我们可以考虑用 @ViewBuilder。
首先定义一个 SwiftUI View:
struct DialogView<T>: View where T: View{private let content: Tvar body: some View {ZStack {Rectangle().fill(Color.black.opacity(0.6)).edgesIgnoringSafeArea(.all)VStack{content}.frame(width: 270).background(Color(red: 0xd6/255.0, green: 0xd6/255.0, blue: 0xd6/255.0)).cornerRadius(14)}}init(@ViewBuilder content: () -> T) {self.content = content()}
}
在类名后面有一个范型 T ,用来代表 content 属性的类型。这个 content 属性就是代表了用户需要灵活定义的那部分视图 UI。我们无法在此时知道它的确切类型,因为它完全由调用者制定,可能是任意类型的 View,我们只知道它是一种 View,但无法具体知道是什么View,是一个 Text 还是 Image 还是多个 Text+Image 的组合。所以范型约束是: where T: View。
你可能想说,不可以直接使用 View 来定义 content 吗?不可以,因为 View 是一个协议,而非具体类型。
这样,我们就可以把 content 的类型定义为 T 了。
在 body 块中(其实 body 块也是一种 ViewBuilder),我们使用 content 替代了部分 UI 内容。然后在 init 方法中,通过 @ViewBuilder content 参数让调用者指定这部分 UI 的内容。你可以看到,这个参数实际上是一个 block,它没有参数,但返回的类型为 T。也就是说 Swift 通过 content 入参来推断出 T 的真正类型。
比如用户在 content 参数中传入一个 Text, 那么 T 就是 Text 类型。当然 ViewBuilder 有一个特别的地方,就是它的返回值可以有多个,因此你可以在其中构建 10 个以内(数量有限制)的不同类型 View,但 T 的类型仍然能被正确推断出来:
DialogView(content: {Spacer().frame(height: 16)Image(systemName: "exclamationmark.circle").foregroundColor(.red)Spacer().frame(height: 2)Text("Hint").font(.system(size: 17, weight: .semibold, design: .default)).foregroundColor(.red)Spacer().frame(height: 16)Divider()Button {debugPrint("close")} label: {Text("OK").font(.system(size: 17)).foregroundColor(Color(red: 0, green: 0x7a/255.0, blue: 0xff/255.0))}.padding(.vertical,11)})
这样,你看到的效果就如本文一开头的截图所示。如你所见,content 的内容完全就如同你构建一个 SwiftUI View 的 body ,这给我们提供了相当大的灵活性。
@ViewBuilder 在自定义 View 中的使用相关推荐
- 安卓自定义view中 绘画基本图形点线面,矩形,方形,圆,扇形,文字及沿着特定方向布局,自定义圆角ImageView图片等等相关api使用方法及举例
安卓自定义view中 绘画基本图形点线面,矩形,方形,圆,扇形,文字及沿着特定方向布局,自定义圆角ImageView图片等等相关api使用方法及举例,图片压缩处理逻辑 本文旨在介绍自定义View的实现 ...
- Android 自定义View中坐标点的理解学习(一)
本文主要是记录学习自定义view中看到的资料,为了方便记忆做了保存整理便于自己学习也方便其他Android开发爱好者学习,参考资料看底部链接. 一.getLocationInWindow和getLoc ...
- Android中实现Bitmap在自定义View中的放大与拖动
一基本实现思路: 基于View类实现自定义View –MyImageView类.在使用View的Activity类中完成OnTouchListener接口,实现对MotionEvent事件的监听与处理 ...
- 《Android开发艺术探索》自定义View中关于“HorizontalScrollViewEx”的改进
在<Android开发艺术探索>一书中自定义View一节中提到了关于一个类似横向滑动List的自定义ViewGroup:HorizontalScrollViewEx.如果你使用过的话就会发 ...
- Android弹性滑动在自定义View中的高级应用
本文出自门心叼龙的博客,属于原创类容,转载请注明出处. 好久没有更新博客了,特意的看了博客最后的更新时间为2019年7月21日,今天是10月24日掐指一算已经有三个月时间了,自从上篇<开发杂谈: ...
- 自定义View中,四个参数的构造函数,其最后两个参数的含义
先看两个参数的构造函数: public View(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);} p ...
- 关于自定义View中wrap_content属性失效的问题
我们在使用自定义控件的时候,有时候会发现当我们设置子View的属性为wrap_content时,发现它最终展现的效果跟我们说预想的不一样,它展现的是match_parent的效果,这是为什么呢?先把问 ...
- Android 自定义View中invalidate()的自动清屏含义以及屏幕刷新
invalidate()含义 invalidate()是用来刷新View的,必须是在UI线程中进行工作.比如在修改某个view的显示时,调用invalidate()才能看到重新绘制的界面.invali ...
- 自定义view中onMeasure、onLayout、onDraw、onFinishInflate、onSizeChanged方法调用时机
一般自定义view或viewGroup基本上都会去实现onMeasure.onLayout.onDraw方法,还有另外两个方法是onFinishInflate和onSizeChanged. onFin ...
最新文章
- 来客推商城V3多用户uni-app商城源码如何搭建?盈利模式怎么样的?
- 通俗的说下浏览器的渲染过程
- 氩焊机器人编程_焊接机器人编程及调试方法
- bootstraptable 怎么在特定行添加数据_手把手教你做一个“渣”数据师,用Python代替老情人Excel...
- .NET Core控制台程序发布后没有exe解决方案
- 63.Linux/Unix 系统编程手册(下) -- 其他备选的IO模型
- 阿坝县人民医院管理系统软件硬件配置参数
- android revre view,MK802 4.0.4 CWM Recovery
- [渝粤教育] 武汉大学 唐诗艺术 参考 资料
- Typora标题增加序号
- python 实现excel单元格合并和导出
- python 使用 turtle库 画“皮卡丘”
- 云计算 第四章 微软云计算 Windows Azure
- 全能在线APP一款开源的多功能在线学习考试智慧软件系统
- 厉害!猛提升70马力150牛米!帕拉梅拉2.9T南京刷ECU升级一阶程序方案分享
- 【EtherCAT理论篇】二、EtherCAT工作原理
- Android8.1 audio之compressed offload流程(四十一)
- VMware下载及安装(附带下载地址)
- node.js毕业设计微信签到小程序(源码+程序+LW+部署)
- ftp工具下载,推荐5个流行的ftp工具下载软件