CALayers没有根据UIView的界限变化调整大小.为什么?

Ger*_*eri 98 iphone objective-c calayer uiview ios

我有一个在其图层中添加了UIView大约8个不同的CALayer子图层.如果我修改视图的边界(动画),那么视图本身会缩小(我用a检查过backgroundColor),但是子图层的大小保持不变.

怎么解决这个?

Cha*_*ood 142

我使用的是Solin使用的相同方法,但该代码中存在拼写错误.方法应该是:

- (void)layoutSubviews {
  [super layoutSubviews];
  // resize your layers based on the view's new bounds
  mylayer.frame = self.bounds;
}
Run Code Online (Sandbox Code Playgroud)

出于我的目的,我一直希望子图层是父视图的完整大小.将该方法放在视图类中.

  • 不要忘记调用[super layoutSubviews],因为这会导致各种UIKit类中的意外行为. (31认同)
  • @fishinear你确定吗?听起来你在描述框架.理论上,边界应始终以0,0为原点. (8认同)
  • @griotspeak--事实并非如此.请参阅此处的bounds属性说明:http://developer.apple.com/library/ios/#documentation/uikit/reference/uiview_class/UIView/UIView.html#//apple_ref/doc/uid/TP40006816-CH3- SW1 - "默认情况下,边界矩形的原点设置为(0,0),但您可以更改此值以显示视图的不同部分." (3认同)
  • 对于我来说,使用自定义的"UITextView"(scrollEnabled = NO)和自动布局,这对我来说效果不佳.我有一个固定在其超级视图的文本视图,而该视图又在其底部(边框)有一个"CALayer",我希望它在文本视图的高度发生变化时更新边框位置.出于某种原因,`layoutSubiews`被称为太晚了(并且图层位置是动画的). (2认同)

Ole*_*ann 25

由于iPhone上的CALayer不支持布局管理器,我认为您必须使视图的主层成为自定义CALayer子类,您可以在其中覆盖layoutSublayers以设置所有子图层的帧.您还必须覆盖视图的+layerClass方法以返回新CALayer子类的类.

  • Mac上的CALayer具有此布局管理器,但它们在iPhone上不可用.所以是的,你必须自己计算帧大小.另一种选择可能是使用子视图而不是子图层.然后,您可以相应地设置子视图的自动调整大小. (3认同)
  • 雅,UIViews是性能太高的课程,为什么我使用CALayers. (2认同)

Run*_*ara 12

我在UIView中使用过这个.

-(void)layoutSublayersOfLayer:(CALayer *)layer
{
    if (layer == self.layer)
    {
        _anySubLayer.frame = layer.bounds;
    }

super.layoutSublayersOfLayer(layer)
}
Run Code Online (Sandbox Code Playgroud)

适合我.


Sol*_*lin 9

我有同样的问题.在自定义视图的图层中,我添加了两个子图层.为了调整子图层的大小(每次自定义视图的边界发生变化),我实现了layoutSubviews自定义视图的方法; 在这个方法中,我只是更新每个子层的帧以匹配我的子视图层的当前边界.

像这样的东西:

-(void)layoutSubviews{
   //keep the same origin, just update the width and height
   if(sublayer1!=nil){
      sublayer1.frame = self.layer.bounds;
   }
}
Run Code Online (Sandbox Code Playgroud)

  • 仅供参考,你不需要if(sublayer1!= nil),因为ObjC将消息定义为nil(在本例中为-setFrame :)作为无操作返回0. (16认同)

Fat*_*tie 6

2017年

这个问题的字面答案:

“ CALayers的UIView边界更改没有调整大小。为什么?”

是好是坏

needsDisplayOnBoundsChange

在中默认为false CALayer

解,

class CircularGradientViewLayer: CALayer {

    override init() {

        super.init()
        needsDisplayOnBoundsChange = true
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override open func draw(in ctx: CGContext) {
        go crazy drawing in .bounds
    }
}
Run Code Online (Sandbox Code Playgroud)

确实,我指导您进行此质量检查

/sf/answers/3343231111/

这说明了关键contentsScale设置到底是做什么的;您通常需要在设置needsDisplayOnBoundsChange时同样地进行设置。


小智 5

斯威夫特 3 版本

在自定义单元格中,添加以下行

先申报

let gradientLayer: CAGradientLayer = CAGradientLayer()
Run Code Online (Sandbox Code Playgroud)

然后添加以下几行

override func layoutSubviews() {
    gradientLayer.frame = self.YourCustomView.bounds
}
Run Code Online (Sandbox Code Playgroud)