SwiftUI实现iPad多任务分屏

news2024/12/27 1:27:03

1. 概述

iPadOS引入了多任务分屏功能,使用户能够同时在一个屏幕上使用多个应用程序。这为用户提供了更高效的工作环境,可以在同一时间处理多个任务。

iPad多任务分屏有两种常见的模式:1/2分屏和Slide Over(滑动覆盖)。1/2分屏将屏幕均分为两个应用程序,而Slide Over模式则允许一个应用程序以较窄的宽度覆盖在另一个应用程序上方。

2. 配置App项目以支持多任务

要使你的App项目支持多任务分屏,需要进行以下配置,在app info文件中:

  1. 不能配置`Requires Full Screen`,或者配置为NO。

  2. 配置`Supported interface orientations (iPad)`支持4个方向。

  3. 配置`Application Scene Manifest`项,并将其下的`Enable Multiple Windows`设置为`yes`。

这样,你的App就会被配置为支持多任务分屏。

3. 屏幕区分和获取屏幕size


在SwiftUI中,你可以使用@Environment属性包装器来获取屏幕的大小。以下是一个示例代码:

import SwiftUI

struct ContentView: View {
    @Environment(\.horizontalSizeClass) var horizontalSizeClass
    
    var body: some View {
        if horizontalSizeClass == .compact {
            // ...
        } else {
            // ...
        }
    }
}

在上面的代码中,我们使用`@Environment(\.horizontalSizeClass) varhorizontalSizeClass`来获取水平尺寸类别,具体如下:

  • 当iPad横屏时:
  1. app全屏或者占屏幕宽度2/3时,为regular。
  2. app占屏幕宽度1/3或者1/2时,为compact。
  • 当iPad竖屏时:
  1. app全屏幕宽度时,为regular。
  2. app非全屏幕宽度时,为compact。

那么如何获取到分屏后的App屏幕宽度呢?就需要用到下面这个组件了。

GeometryReader

将GeometryReader包裹在组件的外部,在屏幕变化是即可得到分屏后的宽度。如下面示例代码:

var body: some View {
    GeometryReader { geometry in
      VStack {
        Spacer()
        if horizontalSizeClass == .compact {
          VStack(alignment: .center, spacing: 20) {
            Image(systemName: "globe")
              .imageScale(.large)
              .foregroundColor(.accentColor)
            Text("horizontalSizeClass == compact")
            Text("当前App屏幕宽度为:\(geometry.size.width)")
          }
          .padding()
          .frame(width: geometry.size.width)
        } else {
          HStack(alignment: .center, spacing: 20) {
            Image(systemName: "globe")
              .imageScale(.large)
              .foregroundColor(.accentColor)
            Text("horizontalSizeClass == regular")
            Text("当前App屏幕宽度为:\(geometry.size.width)")
          }
          .padding()
          .frame(width: geometry.size.width)
        }
        Spacer()
      }
    }
  }

运行结果如下:

  

  

       

这种判断类型还是不够严谨,比如横屏是的1/3或者1/2分屏,都是compact,1/3时我们可以使用iPhone的布局,但是1/2时也使用iPhone的布局的话,界面元素的尺寸会很大,显示内容比较少。为了解决这个问题,下面提供了一个新的方法,来将分屏后的类型进行细分:

calculateSplitRatio方法

enum SplitRatio {
  case fullScreen
  case half
  case oneThird
  case twoThirds
}

func calculateSplitRatio(width: CGFloat) -> SplitRatio {

    let screenWidth = UIScreen.main.bounds.width
    let screenHeight = UIScreen.main.bounds.height

    if abs(width - screenWidth) <= 10 {
      return .fullScreen
    }

    if screenWidth > screenHeight {
      let halfWidth = screenWidth / 2
      let oneThirdWidth = screenWidth / 3
      let twoThirdsWidth = oneThirdWidth * 2

      let diffToHalf = abs(width - halfWidth)
      let diffToOneThird = abs(width - oneThirdWidth)
      let diffToTwoThirds = abs(width - twoThirdsWidth)

      if diffToHalf <= diffToOneThird && diffToHalf <= diffToTwoThirds {
          return .half
      } else if diffToOneThird <= diffToHalf && diffToOneThird <= diffToTwoThirds {
          return .oneThird
      } else {
          return .twoThirds
      }
    } else {
      let halfWidth = screenWidth / 2
      if width > halfWidth {
         return .half
      } else {
         return .oneThird
      }
    }
  }

上面的代码中定义了`SplitRatio`枚举 ,包含了4中类型。在calculateSplitRatio方法中,我们只需要传入分屏后的宽度即可。

这里需要重点说一下的是在iPad竖屏分屏时,如果分屏线在左侧,则认为左侧宽度为1/3,右侧为1/2,如果分屏线在右侧,则左侧宽度为1/2,右侧1/3.这样做,我们能在代码上更好的布局。示例代码如下:

var body: some View {
    GeometryReader { geometry in
      let splitRatio = calculateSplitRatio(width: geometry.size.width)
      VStack {
        if splitRatio == .oneThird {

        } else if splitRatio == .half {

        } else if splitRatio == .twoThirds {

        } else {

        }
      }
      .background(Color.cyan)
    }
  }

4. SwiftUI代码注意事项

在编写SwiftUI代码时,有一些注意事项需要考虑:

  1. 使用适当的布局容器:SwiftUI提供了多种布局容器,如VStack、HStack和ZStack等。根据你的布局需求,选择适当的容器来组织和排列你的视图元素,尽量不使用固定的尺寸布局。
  2. 使用合适的布局修饰符:SwiftUI提供了许多布局修饰符,如padding、spacing和alignment等。使用这些修饰符可以调整视图元素之间的间距、对齐方式等,以获得所需的布局效果。
  3. 考虑不同屏幕尺寸和方向:SwiftUI可以自动适应不同的屏幕尺寸和方向。使用自适应布局和动态尺寸来确保你的界面在不同设备上都能正确显示,并且能够适应横竖屏切换。
     

如果觉得文章对你有用,不妨给个赞,关注一下,更多好用文章还在继续更新中。

本篇文章出自https://blog.csdn.net/guoyongming925的博客,如需转载,还请标明出处。

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

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

相关文章

sentinel blockHandler不生效

sentinel blockHandler不生效: package org.bc.sentinel.controller;import com.alibaba.csp.sentinel.annotation.SentinelResource; import com.alibaba.csp.sentinel.slots.block.BlockException; import org.apache.commons.lang3.RandomUtils; import org.springfram…

blender 场景灯光基础设置

在 blender 中&#xff0c;打光分为两个部分&#xff0c;一个是世界光&#xff0c;一个是场景光&#xff1b; 世界光&#xff1a; 世界光&#xff1a;在 Blender 中&#xff0c;世界光指的是用于设置场景整体照明的环境光。它可以通过调整颜色、强度、阴影等参数来影响场景的…

JAVA:错误: 找不到或无法加载主类 xx.xx.xx类

报错图片&#xff1a; 报错原因&#xff1a; 加载是没有定义项目的根目录或主要代码的位置。这个根目录是整个项目的起点&#xff0c;包含了所有的源代码文件和其他必要的资源文件 解决方法&#xff1a;定义根目录

449. 序列化和反序列化二叉搜索树

诸神缄默不语-个人CSDN博文目录 力扣刷题笔记 Python3版代码提示&#xff1a; # Definition for a binary tree node. # class TreeNode: # def __init__(self, x): # self.val x # self.left None # self.right None# Your Codec object will…

Promise 解决 Vue 中父子组件的加载问题!

前言 关于Promie我这里就不多解释了&#xff0c;不懂得可以看看官方文档。下面文章重点介绍项目中遇到的问题解决方法。 需求 组件b初始化某个用到的库&#xff0c;只有在初始化完成后才能调用其API&#xff0c;不然会报错。a页面负责调用。 // a.vue <template><d…

微服务架构基础--第4章Spring Boot核心功能2

第4章Spring Boot核心功能2 一.预习笔记 1.静态资源访问 1-1&#xff1a;resource下的static文件夹会被视为默认的根目录&#xff08;默认静态资源文件夹&#xff09; 1-2&#xff1a;index.html是SpringBoot的默认首页(默认配置了的) 1-3&#xff1a;修改网页logo&#xf…

文件上传漏洞全面渗透姿势

0x00 文件上传场景 (本文档只做技术交流) 文件上传的场景真的随处可见&#xff0c;不加防范小心&#xff0c;容易造成漏洞&#xff0c;造成信息泄露&#xff0c;甚至更为严重的灾难。 比如某博客网站评论编辑模块&#xff0c;右上角就有支持上传图片的功能&#xff0c;提交带…

飞行动力学 - 第17节-part2-机翼对航向静稳定性的影响 之 基础点摘要

飞行动力学 - 第17节-part2-机翼对航向静稳定性的影响 之 基础点摘要 1. 上反角贡献2. 后掠角贡献3. 机身贡献4. 参考资料 1. 上反角贡献 总体来说&#xff0c;略微降低稳定性。 2. 后掠角贡献 总体来说&#xff0c;略微增加稳定性。 3. 机身贡献 机身也是降低航向静稳定性&…

潜艇来袭(Qt官方案例-2维动画游戏)

一、游戏介绍 1 开始界面 启动程序&#xff0c;进入开始界面。 2 开始新游戏 点击菜单&#xff1a;File》New Game &#xff08;或者CtrlN&#xff09;进入新游戏。 开始新游戏之后&#xff0c;会有一个海底的潜艇&#xff0c;和水面舰艇对战。 计算机&#xff1a;自动控制…

尖端AR技术如何在美国革新外科手术实践?

AR智能眼镜已成为一种革新性的工具&#xff0c;在外科领域具有无穷的优势和无限的机遇。Vuzix与众多医疗创新企业建立了长期合作关系&#xff0c;如Pixee Medical、Medacta、Ohana One、Rods & Cones、Proximie等。这些公司一致认为Vuzix智能眼镜可有效提升手术实践&#x…

java+ssm+mysql水费管理系统

项目介绍&#xff1a; 使用javassmmysql开发的用户水费管理系统&#xff0c;系统包含超级管理员&#xff0c;系统管理员、用户角色&#xff0c;功能如下&#xff1a; 超级管理员&#xff1a;管理员管理、用户管理、用水管理&#xff08;用水记录、缴费提醒&#xff09;、水费…

通讯编程006——NodeJS OPC UA Client开发简单教程

本文介绍如何在NodeJS环境下开发OPC UA Client&#xff0c;通过本文可以对OPC UA的基本概念有所了解&#xff0c;掌握OPC UA的本质。相关软件请登录网信智汇(wangxinzhihui.com)。 开发步骤如下&#xff1a; 1&#xff09;首先需要安装nodejs&#xff0c;要求版本至少是12。 …

实战系列(二)| MybatisPlus详细介绍,包含代码详解

目录 1. MybatisPlus 的基本功能2. 基本用法3. MybatisPlus 的配置4. MybatisPlus 的实体类、Mapper 接口、Service 类和 Controller 类 MybatisPlus 是一个功能强大的 MyBatis 增强工具&#xff0c;它提供了丰富的特性来简化操作数据库的代码。它主要用于简化 JDBC 操作&#…

《Generative Agents: Interactive Simulacra of Human Behavior》全文翻译

《Generative Agents: Interactive Simulacra of Human Behavior》- 生成式代理:人类行为的交互式拟真 论文信息摘要1. 引言2. 相关工作2.1 人机交互2.2 可信的人类行为代理2.3 大型语言模型与人类行为 3. 生成式代理行为和交互3.1 代理形象和交流3.1.1 代理间交流 3.2 环境交互…

PDU是什么?

PDU&#xff0c;即功率分配单元(Power Distribution Unit)&#xff0c;它是一种能够对电源进行管理、监控来保障电力质量与供电可靠性的电源扩展设备。它广泛应用于数据中心、IT机房、机房领域等&#xff0c;可以实现对电源进行远程监控、电源管理和电源分配&#xff0c;为IT设…

阿里 通义千问LLM Qwen-7B-Chat与Qwen-VL-Chat 使用

参考&#xff1a; https://github.com/QwenLM/Qwen-7B https://github.com/QwenLM/Qwen-VL 下载模型&#xff1a; https://huggingface.co/Qwen 1、Qwen-7B-Chat 下载好代码与模型后运行&#xff1a; python ./Qwen-7B-main/web_demo.py -c ./qwen-6b-4bit/ --server-name…

01|PS(容器的三种使用)

系列文章目录 00|PS 01|PS&#xff08;容器的三种使用&#xff09; 文章目录 系列文章目录前言一、容器二、使用步骤0.反向选中删除1.位图&#xff08;图像&#xff09;2.文字3.矢量图&#xff08;图形&#xff09; 前言 一、容器 主要实现于图像之间的组合、覆盖。效果很不错…

分布式系统一致性模式揭秘

分布式系统将数据复制到多个服务器上&#xff0c;以获得更好的容错性、可扩展性和可靠性。一致性模式&#xff08;一致性模型&#xff09;是一组用于在分布式系统中进行数据存储和数据管理的技术。一致性模式决定了数据在分布式系统中的传播。因此&#xff0c;一致性模式将影响…

SpringMvc框架入门使用(详细教程)

目录 ​编辑 1.SpringMVC框架是什么&#xff1f; 2.SpringMVC工作流程 3.SpringMVC的入门 3.1 pom.xml 3.2spring-mvc.xml 3.3web.xml 3.4 建立一个web的方法 4.5 建立一个首页 4.6效果展示 4.图片处理 1.SpringMVC框架是什么&#xff1f; Spring MVC是一个基…

POI基于Excel模板导出数据

1、基于模板导出列表数据 1.1、需求 注意&#xff1a;使用附件的形式下载&#xff0c;前端访问必须通过window.open(),否则附件可能无法下载。 按照以下样式导出excel 1.2、思路 首先准备一个excel模板&#xff0c;这个模板把复杂的样式和固定的内容先准备好并且放入到项…