SwiftUI中Menu和ControlGroup的使用

news2024/12/24 4:28:40

本篇文章主要介绍一下Menu组件和ControlGroup组件的使用。Menu组件是在iOS 14(tvOS 17)推出的一个组件,点击后提供一个可选择的操作列表。ControlGroup组件是一个容器视图,以视觉上适当的方式为给定的上下文显示语义相关的控件,这意味着ControlGroup的外观将取决于视图的上下文。

Menu的使用

Menu组件提供了一个可选择的操作列表。比较常用的初始化方法如下:

init(
    @ViewBuilder content: () -> Content,
    @ViewBuilder label: () -> Label
)

label:该闭包提供一个Menu自身显示的视图内容。
content:该闭包提供点击Menu组件后要显示的视图内容。

下面先看一个使用示例:
在这里插入图片描述

var body: some View {
  Menu("Tap me") {
    // Menu 1
    Text("Menu 1")
      .onTapGesture {
        print("Menu 1 clicked")
      }

    // Menu 2
    Button("Menu 2") {
      print("Menu 2 clicked")
    }

    // Menu 3
    Button(action: {
      print("Menu 3 clicked")
    }, label: {
      Label("Menu 3", systemImage: "heart.fill")
    })

    // Menu 4
    Button(action: {
      print("Menu 4 clicked")
    }, label: {
      Text("Menu 4")
        .font(.largeTitle)
        .foregroundColor(.red)
      Image(systemName: "trash")
      Image(systemName: "magnifyingglass")
    })

    // Menu 5
    Menu("Copy") {
      Button("Copy", action: {})
      Button("Copy Formatted", action: {})
      Button("Copy Library Path", action: {})
    }
  }
}

上面代码中,我们创建了一个menu,传入了一个title,并在content闭包内添加了一些组件。Menu的初始化方法很多,这里不过多的介绍了,我们主要看一下content闭包的内容。

content闭包内:

  • menu1是一个Text组件,并且添加了tap手势,不过事实证明,它只会显示出来,并且文字暗灰色,无法点击,应该是被系统disabled了,所以menu1这种无效。
  • menu2是一个Button组件,仅仅设置了一个title和点击事件。title显示正常,点击事件正常。
  • menu3是一个Button组件,不过其显示内容通过Label组件设置了,并带了一个图片。titleimage显示都正常,点击事件也正常。
  • menu4是一个Button组件,显示内容没有采用Label组件,而是Text加上Image组合,事实证明,TextImage都显示正常,多余的Image无法显示,点击事件正常。
  • menu5是一个Menu组件,这属于嵌套了,一切显示都正常。

之前有一篇文章里面也提及到了MenuPicker的配合使用,感兴趣的朋友可以去看看。SwiftUI中普通Picker的用法

Menu也可以放到导航栏上面,弹出的内容不会超出屏幕。

  var body: some View {
    NavigationStack {
      VStack {
        Color.orange.ignoresSafeArea()
      }
      .toolbar(content: {
        ToolbarItem(placement: .topBarTrailing) {
          Menu("Copy") {
      		Button("Copy", action: {})
      		Button("Copy Formatted", action: {})
      		Button("Copy Library Path", action: {})
      	  }
        }
      })
    }
  }

ControlGroup的使用

ControlGroup视图是一个简单的容器视图,它接受ViewBuilder闭包,并根据当前环境显示它。ControlGroup视图是iOS 14(tvOS 17)推出的一个组件。
让我们看看如何使用它。

ControlGroup {
  Button(action: {}) {
    Label("Decrease", systemImage: "minus")
  }

  Button(action: {}) {
    Label("Increase", systemImage: "plus")
  }
}

在这里插入图片描述
正如在上面的例子中看到的,我们只是在ControlGroup视图中放了两个按钮,就像我们在VStackHStack中做的那样。但是ControlGroup不是使用垂直或水平轴来布局视图,而是根据视图的上下文添加合适的样式。

样式设置

通过controlGroupStyle修饰符可以添加一些样式,一些主要的样式有:

  • AutomaticControlGroupStyle:可简写为.automatic
  • NavigationControlGroupStyle:可简写为.navigation

具体显示成什么样还得看用在哪里了,比如下面的Demo:
可简写为
上面的代码中,先在界面中间显示了两个,然后在导航栏上加了两个,具体见代码。

自定义样式

我们可以创建一个符合ControlGroupStyle协议的类型,并实现一个名为makeBody的必需函数。

下面代码创建了一个竖向排列的样式:

struct VerticalControlGroupStyle: ControlGroupStyle {
  func makeBody(configuration: Configuration) -> some View {
    VStack {
        configuration.content
    }
    .foregroundColor(.red)
  }
}

在这里插入图片描述

下面这个在ControlGroup组件中添加了一个Title:

struct ControlGroupWithTitle: ControlGroupStyle {
    let title: LocalizedStringKey

    func makeBody(configuration: Configuration) -> some View {
        VStack {
            Text(title)
                .font(.title)
            HStack {
                configuration.content
            }
        }
    }
}

在这里插入图片描述

Menu和ControlGroup的混合使用

MenuControlGroup也是可以放在一起使用的。

下面代码中将ControlGroup放在Menu中使用,具体看看效果吧。

struct MenuAndControlGroupDemo: View {
  var body: some View {
    VStack {
      Menu("Action 1") {
        Button("Menu 1", action: {})
        Button("Menu 2", action: {})
        ControlGroup {
          Button(action: {}) {
            Label("Decrease", systemImage: "minus")
          }

          Button(action: {}) {
            Label("Increase", systemImage: "plus")
          }
        }
      }

      Spacer()
        .frame(height: 60)

      Menu("Action 2") {
        Button("Menu 1", action: {})
        Button("Menu 2", action: {})
        ControlGroup {
          Button(action: {}) {
            Text("Decrease")
          }

          Button(action: {}) {
            Text("Increase")
          }
        }
      }
    }
    .padding()
  }
}

在这里插入图片描述
下面将Menu放到ControlGroup中试试:

  var body: some View {
    VStack {
      ControlGroup {
        Button(action: {}) {
          Text("Decrease")
        }

        Button(action: {}) {
          Text("Increase")
        }

        Menu("Action 1") {
          Button("Menu 1", action: {})
          Button("Menu 2", action: {})
        }
      }
      .controlGroupStyle(.navigation)
    }
    .padding()
  }

在这里插入图片描述
这里需要设置.controlGroupStyle(.navigation)才能点击。

如果将整个组合组件放到导航栏里面,那么不设置.controlGroupStyle(.navigation),也是可以点击的。

  var body: some View {
    NavigationStack {
      VStack {
        Color.orange.ignoresSafeArea()
      }
      .toolbar(content: {
        ToolbarItem(placement: .topBarTrailing) {
          ControlGroup {
            Button(action: {}) {
              Text("Decrease")
            }

            Button(action: {}) {
              Text("Increase")
            }

            Menu("Action 1") {
              Button("Menu 1", action: {})
              Button("Menu 2", action: {})
            }
          }
        }
      })
    }
  }

在这里插入图片描述

写在最后

本文主要介绍了MenuControlGroup的基本使用,都是一些小组件,而且在显示的时候系统也会根据不同平台的上下文语义来决定怎么显示,非常好用,如果用在自己的App中,是不是会增加用户体验呢?

最后,希望能够帮助到有需要的朋友,如果觉得有帮助,还望点个赞,添加个关注,笔者也会不断地努力,写出更多更好用的文章。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1792713.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【设计模式深度剖析】【3】【行为型】【职责链模式】| 以购物中心客户服务流程为例加深理解

👈️上一篇:命令模式 设计模式-专栏👈️ 文章目录 职责链模式定义英文原话直译如何理解呢? 职责链模式的角色1. Handler(抽象处理者)2. ConcreteHandler(具体处理者)3. Client(客户…

Go微服务: 基于rocketmq:server和rocketmq:broker搭建RocketMQ环境,以及生产消息和延迟消费消息的实现

RocketMQ 的搭建 1 ) 配置 docker-compose.yaml 文件 version: 3.5 services:rmqnamesrv:image: foxiswho/rocketmq:servercontainer_name: rmqnamesrvports:- 9876:9876volumes:- ./logs:/opt/logs- ./store:/opt/storenetworks:rmq:aliases:- rmqnamesrvrmqbroker:image: fo…

使用System-Verilog实现FPGA基于DE2-115开发板驱动HC_SR04超声波测距模块|集成蜂鸣器,led和vga提示功能

文章目录 前言一、SystemVerilog——下一代硬件设计语言1.1 语言基础2.2 面向对象编程1.3 接口(Interfaces)1.4 程序包(Packages)1.5 数据结构1.6 随机化(Randomization)1.7 并发性和时序控制1.8 功能增强1…

小程序丨最大填表限制如何开启?

老师在新建填表时,希望设置最大数量限制,若填表达到限制,后续的学生将不能继续提交填表。 通过开启【表格最大限制】功能即可实现,下面就来教大家如何制作吧。 🔎如何开启表格最大限制功能? 按照常规流程…

Mac OS 用户开启 8080 端口

开启端口 sudo vim /etc/pf.conf # 开放对应端口 pass out proto tcp from any to any port 8080 # 刷新配置文件 sudo pfctl -f /etc/pf.conf sudo pfctl -e获取本机ip地址 ifconfig en0 | grep inet | grep -v inet6 | awk {print $2}访问指定端口

【UML用户指南】-03-UML的14种图

目录 1、结构图 1、类图(class diagram) 2、对象图(object diagram) 3、构件图 (component diagram) 4、组合结构图 5、包图(package diagram) 6、部署图(deploym…

【LeetCode算法】第100题:相同的树

目录 一、题目描述 二、初次解答 三、官方解法 四、总结 一、题目描述 二、初次解答 1. 思路:二叉树的先序遍历。采用递归的先序遍历方法,首先访问根节点若不同则返回false,其次访问左子树和右子树。在访问左右子树时,需要注意…

gkuubibiih

c语言中的小小白-CSDN博客c语言中的小小白关注算法,c,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 给大家分享一句我很喜欢我话: 知不足而奋进,望远山而前行&am…

Kubernetes集群安装部署(Anolis OS 8)

本次 Kubernetes 集群是基于 kubeadm 进行部署的,操作系统采用的 Anolis OS 8.9。 主机IP配置k8s192.168.211.112核,4G,20G硬盘k8s2192.168.211.122核,2G,20G硬盘k8s3192.168.211.132核,2G,20G…

【Vue】异步更新 $nextTick

文章目录 一、引出问题二、解决方案三、代码实现 一、引出问题 需求 编辑标题, 编辑框自动聚焦 点击编辑,显示编辑框让编辑框,立刻获取焦点 即下图上面结构隐藏,下面结构显示,并且显示的时候让它自动聚焦。 代码如下 问题 “…

带Tkinter界面的小验证加密程序——Python课程作业案例分析

Python课程作业案例分析 作业题目要求实现结果动图题目分析主要库介绍和说明实现源码及注释作业题目要求 某个公司采用公用电话传递数据,数据是四位的整数,在传递过程中是加密的。加密规则如下:每位数字都加上5,然后用和除以10的余数代替该数字,再将第一位和第四位交换,…

持续监控和优化的简单介绍

DevOps 监控提供了有关生产环境状况的全面且最新的信息,以及有关其服务、基础设施和应用程序的详细信息。通过从日志和指标中收集数据,您可以在软件开发生命周期的每个步骤中监控合规性和性能。 监控不仅仅针对生产问题,它涵盖了规划、开发、…

python --对象属性、类属性、类方法和静态方法

对象属性和类属性 --掌握--对象属性 目标掌握对象属性的使用 对象属性,有时也称实例属性、普通属性、公有属性 、或者直接叫属性 在类内部,访问对象属性语法: self.对象属性名 在类外部,访问对象属性语法: 对象名.对…

关系代数与规范化

本文是根据自己的理解,结合实践整理所得,有兴趣的可以参考学习。

掌握Django文件处理:一步步构建上传功能

创建模型 首先先进入我们的testsite项目下,打开members/models.py文件,先添加我们保存文件的数据模型: class Document(models.Model):name models.CharField(max_length255)file models.FileField(upload_touploads/) # uploads/ 是文件…

大模型基架:Transformer如何做优化?

大模型的基础模式是transformer,所以很多芯片都实现先专门的transformer引擎来加速模型训练或者推理。本文将拆解Transformer的算子组成,展开具体的数据流分析,结合不同的芯片架构实现,分析如何做性能优化。 Transformer结构 tr…

CTF本地靶场搭建——GZ:CTF安装

GZ:CTF 项目地址:https://gitcode.com/GZTimeWalker/GZCTF GZCTF 是一款开源的网络安全竞技平台,由开发者GZTimeWalker维护。该项目旨在提供一个环境,让网络安全爱好者和专业人士能够实践他们的技能,通过解决各种安全问题(即“…

流量分析——一、蚁剑流量特征

君衍. 一、Webshell特征流量分析二、环境介绍三、使用Wireshark进行流量分析1、环境说明2、HTTP追踪流分析3、蚁剑请求体中代码块解读 四、使用BurpSurite进行流量分析1、环境配置2、抓包分析 六、总结 一、Webshell特征流量分析 对于重保、护网等攻防演练的防守方来说&#x…

Python03:python代码初体验2

1、变量命名规范 1)字母(Unicode字符)、数字、下划线,不能使用特殊字符,数字不能开头 2)变量名是区分大小写的(大小写敏感,x和X是两个不同的变量名) 3)不能使…

D-Day 上海站回顾丨以科技赋能量化机构业务

5月31日下午,DolphinDB 携手光大证券,在上海成功举办 D-Day 行业交流会。三十余位来自私募机构的核心策略研发、量化交易员、数据分析专家们齐聚现场,深入交流量化投研交易过程中的经验、挑战及解决方案。 DolphinDB 赋能机构业务平台 来自光…