如果不允许约束,如何移动 CAGradientLayer 及其父 UIView 容器?
How to move a CAGradientLayer with its parent UIView container if constraints are not allowed?
目前我有一个 UIView
容器位于 UITableView
上方。使用从 UIScrollView
的继承,我创建了一个 IBOutlet
容器视图的前导约束,并调整类似如下的约束:
func scrollViewDidScroll(_ scrollView: UIScrollView)
{
if scrollView.contentOffset.y < 0
{
...
containerViewLeftConstraint.constant -= abs(scrollView.contentOffset.y) * 2
}
else
{
...
containerViewLeftConstraint.constant += abs(scrollView.contentOffset.y) * 2
}
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool)
{
resetContainerViewSize()
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView)
{
resetContainerViewSize()
}
func resetContainerViewSize()
{
containerViewLeftConstraint.constant = 0.0
UIView.animate(withDuration: 0.4,
delay: 0.0,
usingSpringWithDamping: 0.7,
initialSpringVelocity: 0.5,
options: .curveEaseInOut,
animations: {
self.view.layoutIfNeeded()
}, completion: nil)
}
为了演示,我将容器视图的 backgroundColor
设置为红色以直观地查看发生了什么:
我已经声明了一个 var gradientLayer = CAGradientLayer()
并将其作为子层添加到容器视图中,如下所示:
func createGradientOverlay()
{
gradientLayer.frame = containerView.frame
let colors = [UIColor.black.withAlphaComponent(0.5).cgColor,
UIColor.white.cgColor]
gradientLayer.colors = colors
gradientLayer.startPoint = CGPoint(x:0.0,
y:0.5)
gradientLayer.endPoint = CGPoint(x:1.0, y:0.5);
containerView.layer.addSublayer(gradientLayer)
}
然而,我得到的结果如下所示:
渐变层不粘附在容器视图的边界上,看起来像是浮动的。
我看过几个类似的问题:
- CALayers 没有在其 UIView 的边界变化时调整大小。为什么?
- Auto Layout constraint on CALayer IOS
所有人都建议像这样使用 viewDidLayoutSubviews
:
override func viewDidLayoutSubviews()
{
super.viewDidLayoutSubviews()
gradientLayer.frame = nameContainerView.frame
}
然而,渐变层仍然看起来是浮动的,并且没有遵守容器视图的约束。
我也尝试了以下方法但无济于事:
gradientLayer.frame = nameContainerView.bounds
gradientLayer.bounds = nameContainerView.bounds
gradientLayer.frame = nameContainerView.layer.bounds
gradientLayer.frame = nameContainerView.layer.frame
我该如何解决这个问题?
Pangu - 如果有人想要更多信息来帮助您,那么您应该提供这些信息,以便他们可以帮助您。现在回答你的问题。您可以通过两种方式干净地完成这两种方式,如果我能看到您的函数,可能是 3。
首先是创建一个使用 CAGradientLayer 作为背衬层的视图,然后您可以将自动布局应用于渐变视图。这是一个 class 你可以用我几分钟的时间。
import UIKit
class GradientBackedLayer: UIView {
var colors : [UIColor] = [UIColor.black.withAlphaComponent(0.5),UIColor.white]{
didSet{
setUpGradient()
}
}
var startPoint : CGPoint = CGPoint(x:0.0,y:0.5){
didSet{
setUpGradient()
}
}
var endPoint : CGPoint = CGPoint(x:1.0, y:0.5){
didSet{
setUpGradient()
}
}
override init(frame: CGRect) {
super.init(frame: frame)
setUpGradient()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setUpGradient()
}
func setUpGradient(){
self.backgroundColor = .clear
let cgColors = colors.map({[=10=].cgColor})
if let gradientLayer = self.layer as? CAGradientLayer{
gradientLayer.colors = cgColors
gradientLayer.startPoint = startPoint
gradientLayer.endPoint = endPoint
}
}
override class var layerClass: AnyClass {
return CAGradientLayer.self
}
}
第二种是使用变换而不是更改容器上的约束,所有内容都将按比例缩放。如果这是你想要的方式,我会把这个留给你去解决。
目前我有一个 UIView
容器位于 UITableView
上方。使用从 UIScrollView
的继承,我创建了一个 IBOutlet
容器视图的前导约束,并调整类似如下的约束:
func scrollViewDidScroll(_ scrollView: UIScrollView)
{
if scrollView.contentOffset.y < 0
{
...
containerViewLeftConstraint.constant -= abs(scrollView.contentOffset.y) * 2
}
else
{
...
containerViewLeftConstraint.constant += abs(scrollView.contentOffset.y) * 2
}
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool)
{
resetContainerViewSize()
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView)
{
resetContainerViewSize()
}
func resetContainerViewSize()
{
containerViewLeftConstraint.constant = 0.0
UIView.animate(withDuration: 0.4,
delay: 0.0,
usingSpringWithDamping: 0.7,
initialSpringVelocity: 0.5,
options: .curveEaseInOut,
animations: {
self.view.layoutIfNeeded()
}, completion: nil)
}
为了演示,我将容器视图的 backgroundColor
设置为红色以直观地查看发生了什么:
我已经声明了一个 var gradientLayer = CAGradientLayer()
并将其作为子层添加到容器视图中,如下所示:
func createGradientOverlay()
{
gradientLayer.frame = containerView.frame
let colors = [UIColor.black.withAlphaComponent(0.5).cgColor,
UIColor.white.cgColor]
gradientLayer.colors = colors
gradientLayer.startPoint = CGPoint(x:0.0,
y:0.5)
gradientLayer.endPoint = CGPoint(x:1.0, y:0.5);
containerView.layer.addSublayer(gradientLayer)
}
然而,我得到的结果如下所示:
渐变层不粘附在容器视图的边界上,看起来像是浮动的。
我看过几个类似的问题:
- CALayers 没有在其 UIView 的边界变化时调整大小。为什么?
- Auto Layout constraint on CALayer IOS
所有人都建议像这样使用 viewDidLayoutSubviews
:
override func viewDidLayoutSubviews()
{
super.viewDidLayoutSubviews()
gradientLayer.frame = nameContainerView.frame
}
然而,渐变层仍然看起来是浮动的,并且没有遵守容器视图的约束。
我也尝试了以下方法但无济于事:
gradientLayer.frame = nameContainerView.bounds
gradientLayer.bounds = nameContainerView.bounds
gradientLayer.frame = nameContainerView.layer.bounds
gradientLayer.frame = nameContainerView.layer.frame
我该如何解决这个问题?
Pangu - 如果有人想要更多信息来帮助您,那么您应该提供这些信息,以便他们可以帮助您。现在回答你的问题。您可以通过两种方式干净地完成这两种方式,如果我能看到您的函数,可能是 3。
首先是创建一个使用 CAGradientLayer 作为背衬层的视图,然后您可以将自动布局应用于渐变视图。这是一个 class 你可以用我几分钟的时间。
import UIKit
class GradientBackedLayer: UIView {
var colors : [UIColor] = [UIColor.black.withAlphaComponent(0.5),UIColor.white]{
didSet{
setUpGradient()
}
}
var startPoint : CGPoint = CGPoint(x:0.0,y:0.5){
didSet{
setUpGradient()
}
}
var endPoint : CGPoint = CGPoint(x:1.0, y:0.5){
didSet{
setUpGradient()
}
}
override init(frame: CGRect) {
super.init(frame: frame)
setUpGradient()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setUpGradient()
}
func setUpGradient(){
self.backgroundColor = .clear
let cgColors = colors.map({[=10=].cgColor})
if let gradientLayer = self.layer as? CAGradientLayer{
gradientLayer.colors = cgColors
gradientLayer.startPoint = startPoint
gradientLayer.endPoint = endPoint
}
}
override class var layerClass: AnyClass {
return CAGradientLayer.self
}
}
第二种是使用变换而不是更改容器上的约束,所有内容都将按比例缩放。如果这是你想要的方式,我会把这个留给你去解决。