有时候我们要求一个 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 中的使用相关推荐

  1. 安卓自定义view中 绘画基本图形点线面,矩形,方形,圆,扇形,文字及沿着特定方向布局,自定义圆角ImageView图片等等相关api使用方法及举例

    安卓自定义view中 绘画基本图形点线面,矩形,方形,圆,扇形,文字及沿着特定方向布局,自定义圆角ImageView图片等等相关api使用方法及举例,图片压缩处理逻辑 本文旨在介绍自定义View的实现 ...

  2. Android 自定义View中坐标点的理解学习(一)

    本文主要是记录学习自定义view中看到的资料,为了方便记忆做了保存整理便于自己学习也方便其他Android开发爱好者学习,参考资料看底部链接. 一.getLocationInWindow和getLoc ...

  3. Android中实现Bitmap在自定义View中的放大与拖动

    一基本实现思路: 基于View类实现自定义View –MyImageView类.在使用View的Activity类中完成OnTouchListener接口,实现对MotionEvent事件的监听与处理 ...

  4. 《Android开发艺术探索》自定义View中关于“HorizontalScrollViewEx”的改进

    在<Android开发艺术探索>一书中自定义View一节中提到了关于一个类似横向滑动List的自定义ViewGroup:HorizontalScrollViewEx.如果你使用过的话就会发 ...

  5. Android弹性滑动在自定义View中的高级应用

    本文出自门心叼龙的博客,属于原创类容,转载请注明出处. 好久没有更新博客了,特意的看了博客最后的更新时间为2019年7月21日,今天是10月24日掐指一算已经有三个月时间了,自从上篇<开发杂谈: ...

  6. 自定义View中,四个参数的构造函数,其最后两个参数的含义

    先看两个参数的构造函数: public View(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);} p ...

  7. 关于自定义View中wrap_content属性失效的问题

    我们在使用自定义控件的时候,有时候会发现当我们设置子View的属性为wrap_content时,发现它最终展现的效果跟我们说预想的不一样,它展现的是match_parent的效果,这是为什么呢?先把问 ...

  8. Android 自定义View中invalidate()的自动清屏含义以及屏幕刷新

    invalidate()含义 invalidate()是用来刷新View的,必须是在UI线程中进行工作.比如在修改某个view的显示时,调用invalidate()才能看到重新绘制的界面.invali ...

  9. 自定义view中onMeasure、onLayout、onDraw、onFinishInflate、onSizeChanged方法调用时机

    一般自定义view或viewGroup基本上都会去实现onMeasure.onLayout.onDraw方法,还有另外两个方法是onFinishInflate和onSizeChanged. onFin ...

最新文章

  1. 来客推商城V3多用户uni-app商城源码如何搭建?盈利模式怎么样的?
  2. 通俗的说下浏览器的渲染过程
  3. 氩焊机器人编程_焊接机器人编程及调试方法
  4. bootstraptable 怎么在特定行添加数据_手把手教你做一个“渣”数据师,用Python代替老情人Excel...
  5. .NET Core控制台程序发布后没有exe解决方案
  6. 63.Linux/Unix 系统编程手册(下) -- 其他备选的IO模型
  7. 阿坝县人民医院管理系统软件硬件配置参数
  8. android revre view,MK802 4.0.4 CWM Recovery
  9. [渝粤教育] 武汉大学 唐诗艺术 参考 资料
  10. Typora标题增加序号
  11. python 实现excel单元格合并和导出
  12. python 使用 turtle库 画“皮卡丘”
  13. 云计算 第四章 微软云计算 Windows Azure
  14. 全能在线APP一款开源的多功能在线学习考试智慧软件系统
  15. 厉害!猛提升70马力150牛米!帕拉梅拉2.9T南京刷ECU升级一阶程序方案分享
  16. 【EtherCAT理论篇】二、EtherCAT工作原理
  17. Android8.1 audio之compressed offload流程(四十一)
  18. VMware下载及安装(附带下载地址)
  19. node.js毕业设计微信签到小程序(源码+程序+LW+部署)
  20. ftp工具下载,推荐5个流行的ftp工具下载软件

热门文章

  1. Python操作字符串-截取IP地址
  2. 重塑价值:新一代ITSM平台的建设、咨询与实施
  3. YOLOV5训练自己的数据集(踩坑经验之谈)
  4. 01: tornado基础篇
  5. 参与影片《大城小事》的记者会
  6. 免费OA系统平台在企业发展中的优势(转载)
  7. 关于Latex中生僻字显示问题
  8. 点云 3D 目标跟踪 - SimTrack: Exploring Simple 3D Multi-Object Tracking for Autonomous Driving(ICCV 2021)
  9. 计算机网络 华东理工大学 第1章测试
  10. ubuntu12.04安装puppet foreman