可能是全网第一个适配iOS灵动岛的Toast库-JFPopup
前言
我去年的一篇文章详细的介绍了我编写的一套Swift弹窗组件库一个优雅的Swift弹窗组件-JFPopup。里面适配了一套ToastView,恰逢今年苹果iPhone14 Pro以上系列新出了一套灵动岛的交互风格,所以就意外想到能否把ToastView也适配进去灵动岛,所以此文就应运而生。我上篇文章已经很详细的介绍了JFPopup具体用法,这篇文章主要讲解适配灵动岛的心路历程。
具体效果:
用法
虽然我上篇文章已经介绍了一遍,这里我还是再写一下。另外灵动岛Toast默认适配iPhone14 Pro以上机型,无需另外操作,若不是灵动岛机型,则是默认居中,还支持top及bottom。更多详细参数请看一个优雅的Swift弹窗组件-JFPopup
Toast:
//默认仅文案
JFPopupView.popup.toast(hit: "默认toast,支持灵动岛")
//带logo ,内置success or fail
JFPopupView.popup.toast(hit: "支付成功", icon: .success)
JFPopupView.popup.toast(hit: "支付失败", icon: .fail)
//自定义logo
JFPopupView.popup.toast(hit: "自定义", icon: .imageName(name: "face"))
Loading:
DispatchQueue.main.async {
JFPopupView.popup.loading()
}
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
JFPopupView.popup.hideLoading()
JFPopupView.popup.toast(hit: "刷新成功")
}
适配灵动岛具体过程
由于苹果官方已经说了要在下半年推出的ActivityKit才会加入适配灵动岛的Api。所以目前并没有官方的api可以给我们适配。所以只能硬着头皮自己去思考适配方案了。
- 首先要知道灵动岛的区域大小
我们用最笨的方法,直接给模拟器截个图自己去算大小。至少能还原99%的效果了。如图得知,灵动岛的区域大概是宽120dt,高34dp,那半圆圆角自然为17dt。居顶部大约10dp,以及在屏幕居中。有了这些信息,我们自然就能模拟灵动岛的放大缩小转场效果了。
- ToastView新增灵动岛动画
我们在原先基础上新增灵动岛动画枚举
public enum JFToastPosition {
case center
case top
case bottom
case dynamicIsland //新增灵动岛位置动画
}
重新实现下present 及 dismiss协议的转场动画代码如下
展开:
let originSize = contianerView.jf.size
if config.toastPosition == .dynamicIsland {
contianerView.jf_size = CGSize(width: 120, height: 34)
contianerView.center = CGPoint(x: CGSize.jf.screenSize().width / 2, y: 27)
}
let updateV = {
contianerView.center = CGPoint(x: CGSize.jf.screenSize().width / 2, y: CGSize.jf.screenSize().height / 2)
if config.toastPosition == .top {
contianerView.jf_top = CGFloat.jf.navigationBarHeight() + 15
} else if config.toastPosition == .bottom {
contianerView.jf_bottom = CGSize.jf.screenHeight() - CGFloat.jf.safeAreaBottomHeight() - 15
} else if config.toastPosition == .dynamicIsland {
contianerView.jf_size = originSize
contianerView.center = CGPoint(x: CGSize.jf.screenSize().width / 2, y: originSize.height / 2 + 10)
}
contianerView.layoutIfNeeded()
}
guard config.withoutAnimation == false else {
updateV()
transitonContext?.completeTransition(true)
completion?(true)
return
}
if config.toastPosition == .dynamicIsland {
UIView.animate(withDuration: 0.25) {
updateV()
} completion: { finished in
transitonContext?.completeTransition(true)
completion?(finished)
}
return
}
消失:
UIView.animate(withDuration: 0.25, animations: {
if config.toastPosition == .dynamicIsland {
contianerView?.layer.cornerRadius = 17
contianerView?.jf_size = CGSize(width: 120, height: 34)
contianerView?.center = CGPoint(x: CGSize.jf.screenSize().width / 2, y: 27)
}
contianerView?.subviews.forEach({ v in
if config.toastPosition == .dynamicIsland {
v.isHidden = true
} else {
v.alpha = 0
}
})
contianerView?.alpha = 0
}) { (finished) in
transitonContext?.completeTransition(true)
completion?(finished)
}
末尾
以上即是我JFPopup内置组件JFToastView适配灵动岛动画的全过程,假如下半年苹果更新了Api我也会第一时间重新适配。
作者:jerryfans
链接:https://juejin.cn/post/7145630021372084232
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
链接:https://juejin.cn/post/7145630021372084232
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。