我没有使用常规按钮,而是将其归类,UIControl因为我需要为其添加渐变。我也有一种方法来添加阴影和活动指示器(在下图中不可见)作为有状态的按钮,以防止用户在(例如)进行API调用时重击该按钮。
尝试UIControl旋转该控件确实很棘手,为了做到这一点,我将阴影作为一个单独的视图添加到了包含的容器视图中,UIControl因此可以添加阴影。
现在的问题是控件的行为不像旋转视图-让我为您展示上下文的屏幕抓取:

这是中间旋转,但几乎是肉眼可见的- 图像显示渐变是UIView图像中蓝色长度的75%。
https://github.com/stevencurtis/statefulbutton
为了执行此旋转,我先移除shadowview,然后将渐变框架的框架更改为其边界,这就是问题所在。
func viewRotated() {
CATransaction.setDisableActions(true)
shadowView!.removeFromSuperview()
shadowView!.frame = self.frame
shadowView!.layer.masksToBounds = false
shadowView!.layer.shadowOffset = CGSize(width: 0, height: 3)
shadowView!.layer.shadowRadius = 3
shadowView!.layer.shadowOpacity = 0.3
shadowView!.layer.shadowPath = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: .allCorners, cornerRadii: CGSize(width: 20, height: 20)).cgPath
shadowView!.layer.shouldRasterize = true
shadowView!.layer.rasterizationScale = UIScreen.main.scale
self.gradientViewLayer.frame = self.bounds
self.selectedViewLayer.frame = self.bounds
CATransaction.commit()
self.insertSubview(shadowView!, at: 0)
}
Run Code Online (Sandbox Code Playgroud)
因此,通过父视图控制器调用此旋转方法:
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(alongsideTransition: { context in
context.viewController(forKey: UITransitionContextViewControllerKey.from)
//inform the loginButton that it is being rotated
self.loginButton.viewRotated()
}, completion: { context in
// can call here when completed the transition
})
}
Run Code Online (Sandbox Code Playgroud)
我知道这是问题所在,我想这不是在正确的时间以与相同的方式发生的UIView。现在的问题是,我已经尝试了很多方法来使其正常工作,而我最好的解决方案(上述)还不存在。
建议使用UIButton,将图像用于渐变(建议不要将渐变图像用作UIButton的背景,我已经尝试过)或第三方库,这对建议没有帮助。这是我的工作,可以正常工作,但对我来说不可接受,我想让它和通常的视图一样工作(或者至少知道为什么不这样)。我也尝试了上面的其他解决方案,并且自己解决了UIControl。我知道如果有API调用,我可以锁定视图,或者使用其他方式来阻止用户多次按下按钮。我正在尝试解决我的问题,而不是发明解决方法CAGradientLayer。
问题:我需要使a UIControlView与CAGradientLayer背景一样以a旋转UIView,并且不出现上图所示的问题。
小智 6
这是工作代码:
https://gist.github.com/alldne/22d340b36613ae5870b3472fa1c64654
这些是我对您的代码的建议:
视图的大小(即您的按钮)是在布局完成后确定的。您应该做的只是在布局后设置适当的子层大小。因此,我建议您在中设置渐变子层的大小和位置layoutSubviews。
override func layoutSubviews() {
super.layoutSubviews()
let center = CGPoint(x: self.bounds.width / 2, y: self.bounds.height / 2)
selectedViewLayer.bounds = self.bounds
selectedViewLayer.position = center
gradientViewLayer.bounds = self.bounds
gradientViewLayer.position = center
}
Run Code Online (Sandbox Code Playgroud)
删除shadowView并设置图层属性:
layer.shadowOffset = CGSize(width: 0, height: 3)
layer.shadowRadius = 3
layer.shadowOpacity = 0.3
layer.shadowColor = UIColor.black.cgColor
clipsToBounds = false
Run Code Online (Sandbox Code Playgroud)
如果必须使用额外的视图来绘制阴影,则可以一次添加视图并在init()其中设置适当的大小和位置,layoutSubviews也可以通过编程方式为超级视图设置自动布局约束。
设置适当的大小后,渐变图层和容器视图的动画无法很好地同步。
看起来:
UIViewControllerTransitionCoordinator)具有其自己的过渡持续时间和缓动功能。UIView)。CALayer没有关联的,这些值将不会应用于UIView。因此,它使用CoreAnimation的默认计时功能和持续时间。要同步动画,请显式设置动画持续时间和计时功能,如下所示:
class ViewController: UIViewController {
...
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
CATransaction.setAnimationDuration(coordinator.transitionDuration)
CATransaction.setAnimationTimingFunction(coordinator.completionCurve.timingFunction)
}
...
}
// Swift 4
extension UIView.AnimationCurve {
var timingFunction: CAMediaTimingFunction {
let functionName: CAMediaTimingFunctionName
switch self {
case .easeIn:
functionName = kCAMediaTimingFunctionEaseIn as CAMediaTimingFunctionName
case .easeInOut:
functionName = kCAMediaTimingFunctionEaseInEaseOut as CAMediaTimingFunctionName
case .easeOut:
functionName = kCAMediaTimingFunctionEaseOut as CAMediaTimingFunctionName
case .linear:
functionName = kCAMediaTimingFunctionLinear as CAMediaTimingFunctionName
}
return CAMediaTimingFunction(name: functionName as String)
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
133 次 |
| 最近记录: |