SwiftUI 轻量级自定义截图组件(使用篇)

SwiftUI 轻量级自定义截图组件(使用篇)

快速说明

案例演示

本篇讲讲实战使用,下篇再讲一下实现原理

在 app 开发过程中,我们经常需要用到截图的功能,比如一个典型场景就是做【分享/保存图片】功能。

如下图所示,我们想要依赖已有的 UI,快速生成一个分享图,用 RickeyBoy/ScreenshotableView 就能快速实现了。

实现步骤

1. 引入组件

使用 Swift Package Manager 引入工程即可,非常方便

通过 Xcode File > Swift Packages > Add Pacage Dependency...,再输入 https://github.com/RickeyBoy/ScreenshotableView 搜索添加

2. 添加截图按钮

首先,我们假设我们已经实现了一个页面的样式(基于 SwiftUI 是非常容易画 UI 的)。我们将中间的部分看做一个整体,命名为 CustomView:

那么这里的页面布局就非常简单了:

Swift 复制代码
var body: some View {
     VStack {
       ... // Headers
       
       CustomView()
       
       ... // Tab buttons
     }
}

不同于 Objective C 和 Swift 中手动添加 Action 的方式,SwiftUI 需要通过 @State 关键字的变量,来绑定截图状态。所以我们在引入 ScreenshotableView 后,需要添加标记位,来实现截图的功能。

在想要截图时,直接调用 shotting.toggle() 就行了。

Swift 复制代码
var body: some View {
     @State var shotting = false

     VStack {
       ... // Headers

       ScreenshotableView(shotting: $shotting) { screenshot in
           // 返回 screenshot 截图
       } content: {
           // 原有的 CustomView 内容
           CustomView()
       }

       ... // Tab buttons
     }

     func screenshot() {
       // 触发截图
       shotting.toggle()
     }
}

此时,如果直接输出截图的图片结果 screenshot,就会直接得到一张和 CustomView 一模一样的图片:

3. 实现自定义样式

如何实现展示效果 vs 截图效果的不同?ScreenshotView 其实提供了非常便捷的实现方式,在 block 中可以直接捕获到 style,包含 inViewinScreenshot 两个枚举类型,分别代表展示效果、截图效果。我们将参数透传给 Custom 即可:

Swift 复制代码
var body: some View {
     @viewBuilder
     func CustomView(style: ScreenshotableViewStyle) -> some View {
        if style == .inView {
             // 展示时使用白色背景
            content
               .background(.white)
        } else {
             // 截图时使用自定义的渐变色背景
             content
               .background {LinearGradient(...)}
        }
    }
}

4. 给截图添加底部额外信息

通过截图组件,我们能够拿到截图后回调的图片。那么就可以直接做一个简单的拼接,就可以得到最终的结果图了:

Swift 复制代码
extension UIImage {
 /// 拼接分享底部 banner
 func addShareBanner() -> UIImage {
   // 资源图片
   let qrCodeImage = UIImage(named: "AppQRCode")!
   let logoImage = UIImage(named: "Logo")!
   // 参数
   let bannerHeight: CGFloat = 92 /// 新增 banner 的高度
   let newImageSize = CGSize(width: self.size.width, height: self.size.height + bannerHeight)
   // 新增画布
   UIGraphicsBeginImageContextWithOptions(newImageSize, false, UIScreen.main.scale)
   // 绘制原本的 Image
   self.draw(at: CGPoint.zero)
   // 绘制二维码
   let qrCodeRect = CGRect(origin: CGPoint(x: 24, y: self.size.height + 10), size: CGSize(width: 72, height: 72))
   qrCodeImage.draw(in: qrCodeRect)
   // 绘制 Logo
   let logoSize = CGSize(width: 74, height: 30)
   let logoRect = CGRect(origin: CGPoint(x: newImageSize.width - 12 - logoSize.width, y: newImageSize.height - 12 -logoSize.height), size: logoSize)
   logoImage.draw(in: logoRect)
   // 生成
   let image = UIGraphicsGetImageFromCurrentImageContext()
   UIGraphicsEndImageContext()
   return image ?? self
 }
}

我们只需要在回调中进行处理,就能得到我们最终的分享图了:

swift 复制代码
var body: some View {
 @State var shotting = false

 VStack {
   ... // Headers

   ScreenshotableView(shotting: $shotting) { screenshot in
     // 返回 screenshot 截图
     sharedImage = screenshot.addShareComponent()
   } content: { style in
     // 原有的 CustomView 内容
     CustomView(style: style)
   }

   ... // Tab buttons
 }

 func screenshot() {
   // 触发截图
   shotting.toggle()
 }
}
相关推荐
逛逛GitHub11 小时前
刚刚!Open AI 宣布开源?
github
不是伍壹14 小时前
【R语言】GitHub Copilot安装-待解决
github·copilot
虾饺爱下棋14 小时前
pycharm上传github问题:rejected
人工智能·深度学习·github
鸠摩智首席音效师15 小时前
如何在 GitHub 中创建一个空目录 ?
github
struggle202516 小时前
Ollmao (OH-luh-毛程序包及源码) 是一款原生 SwiftUI 应用程序,它与 Ollama 集成,可在 Mac 上本地运行强大的 AI 模型
ios·swiftui·swift
Mr.W.T18 小时前
Spring Boot “约定大于配置”
github
不cong明的亚子1 天前
github用户名密码登陆失效了
git·github
QC七哥1 天前
git开发流程以及github社区企业版
git·github
邂逅you1 天前
GitHub基本操作及Git简单命令
git·github
misty youth2 天前
github与git bash绑定问题
git·github·bash