Say Hello to MegaX
有的时候会有很多想法和点子,开了很多的项目,发现很多代码都是重复的,比如每个项目中我都会创建一个 if-else
的 View Modifier、BlurView 这些,最近我对于 CameraView 的使用也更加频繁了。
So, why not create a framework that gathers everything we will need in our development proccess?
Sure. We can.
于是,我和自己一拍即合,就开始找寻自己曾经开发过的一些可以复用的组件,对其改造甚至是重写,使其可以适用于不同的场景。
321,上链接:https://github.com/LiYanan2004/MegaX
So, what should we call it?
Well, that brings us to our legendary crack marketing team.
Sorry,串台了。
CameraView
在过年期间,我花了一个礼拜时间写了一个 System-like CameraView,用于拍摄静态图片,相信也是一个很常见的需求。
支持快速快门优先的响应式拍摄。
这里是一个简单的例子。
1 | import SwiftUI |
这里需要额外在 App 入口增加一个 AppOrientationDelegate
是因为在 iPhone 上需要限制在 CameraView
内只能以 portait
显示,从而保证 UI 能够始终保持在原地。
当完成拍摄、完成处理后会调用闭包,你可以在这里处理后续的保存、处理的任务。
AsyncButton
有时候,我们会在 Button
中使用异步操作来执行耗时任务,同时伴随需要展示 ProgressView
使用 MegaX 后,一切都变得简单起来。
1 | AsyncButton("Download", systemName: "arrow.down.circle") { |
你可以像使用 Button
一样创建一个 AsyncButton
也可以额外创建自定义的 ProgressView Placeholder,默认就是:ProgressView()
Backdrop Blur Layer
这应该是一个重磅功能了。
SwiftUI 提供了原生的 Material
材质,但是除了模糊层之外还包含了CubedLuminanceMappingLayer
(一种可以自适应深浅色模式的光照映射层)
在 MegaX 中,我通过大量实验(thanks to SwiftUI Preview)找到了一种很强大的调节方案,极大程度上的抵消掉了 CubedLuminanceMappingLayer
,同时可以适应不同的背景
这样,我们就获得了”纯粹的“ Backdrop-Blur Layer
我知道 CAFilter 里有一个高斯模糊的滤镜,但是 CAFilter 是 Private API,无法完全确定是否可以通过审核。
MagaX 提供了纯粹的 SwiftUI 的解决方案,100% 过审核
这样会在视图下方增加一层模糊,模糊的内容是 YourView
下方的内容,而不是 YourView
本身
这是和 blur(radius:opaque:)
的本质区别
如果你正在构建一个 NavigationBar,你可以还需要处理 bar 和 content 之间的过度,这时候你可以使用 smoothEdges
这样就会在模糊层底部增加一个从 opaque 到 transparent 的蒙板
LongPressGesture with Location
我们很熟悉 SpatialTapGesture
和 onTapGesture(action: (CGPoint) -> Void)
API.
可惜的是,在我做 CameraView
时需要实现长按锁定对焦,也需要获取到点按的位置,于是就有了 SpatialLongPressGesture
[!Tip] 但是这里有一点需要特别注意:你需要使用 onChanged 来获取到争取的状态,而不是 onEnded
1 | YourView() |
也可以使用 View Modifier 的版本:onLongPressGesture(minimumDuration:maximumDistance:coordinateSpace:perform:)
More
if-else
modifier请谨慎地使用这个修改器,因为它会导致性能问题以及奇怪的动画。
当且仅当
condition
值在整个 View LifeCycle 内不会变化时使用该修改器。举个栗子:在 iPad 环境中额外需要添加一个 padding
1
2
3
4
5
6
7
8import MegaX
@Environment(\.deviceType) var deviceType
YourView()
.if(deviceType == .pad) { content in
content.padding()
}在这个例子中,在整个 View LifeCycle 中,deviceType 不会变化,可以放心使用这个修改器。
DeviceType
environment value.mac
、tv
、vision
、watch
基本都是在编译期(Native)就确定了iPad、iPhone、CarPlay、Mac Catalyst 会在运行时获取(
UIDevice.current.userInterfaceIdiom
)需要注意的是,
mac
和Mac Catalyst
是两种DeviceType
Ending
这个库目前还是 WIP 状态,会不断迭代更新,希望它可以帮助到正在使用 SwiftUI 开发的开发者们。
Say Hello to MegaX
预览: