iOS 多次添加子视图和子层
iOS adding subViews and subLayers multiple times
我有一个构建界面的方法,它向主 UIView(下面代码中的 containerView)添加一个子视图和一些子层:
- (void)gradeAnimation:(NSNumber*)grade withDuration:(double)duration {
scoreLabel = [[UICountingLabel alloc] init];
scoreLabel.frame = CGRectOffset(_gradeLabel.frame, 0, 5);
[_containerView addSubview:scoreLabel];
// Other code
UIBezierPath *circlePathMin = [UIBezierPath bezierPathWithArcCenter:CGPointMake(_gradientView.center.x, _gradientView.center.y) radius:_gradientView.frame.size.height * 0.5 - 5 startAngle:-M_PI_4*1.2 endAngle:angle1 clockwise:YES];
circleMin = [CAShapeLayer layer];
circleMin.path = circlePathMin.CGPath;
circleMin.lineCap = kCALineCapButt;
circleMin.fillColor = [UIColor clearColor].CGColor;
circleMin.lineWidth = 14;
circleMin.strokeColor = [UIColor colorWithRed:246.0/255.0f green:246.0f/255.0f blue:246.0f/255.0f alpha:0.7f].CGColor;
circleMin.zPosition = 3;
[_containerView.layer addSublayer:circleMin];
UIBezierPath *circlePathMax = [UIBezierPath bezierPathWithArcCenter:CGPointMake(_gradientView.center.x, _gradientView.center.y) radius:_gradientView.frame.size.height * 0.5 - 5 startAngle:angle2 endAngle:5*M_PI_4*1.2 clockwise:YES];
circleMax = [CAShapeLayer layer];
circleMax.path = circlePathMax.CGPath;
circleMax.lineCap = kCALineCapButt;
circleMax.fillColor = [UIColor clearColor].CGColor;
circleMax.lineWidth = 14;
circleMax.strokeColor = [UIColor colorWithRed:246.0/255.0f green:246.0f/255.0f blue:246.0f/255.0f alpha:0.7f].CGColor;
circleMax.zPosition = 3;
[_containerView.layer addSublayer:circleMax];
UIBezierPath *circlePathMiddle = [UIBezierPath bezierPathWithArcCenter:CGPointMake(_gradientView.center.x, _gradientView.center.y) radius:_gradientView.frame.size.height * 0.5 - 5 startAngle:angle1+offsetRight endAngle:angle2+offsetLeft clockwise:YES];
circleMiddle = [CAShapeLayer layer];
circleMiddle.path = circlePathMiddle.CGPath;
circleMiddle.lineCap = kCALineCapButt;
circleMiddle.fillColor = [UIColor clearColor].CGColor;
circleMiddle.lineWidth = 14;
circleMiddle.strokeColor = [UIColor colorWithRed:246.0/255.0f green:246.0f/255.0f blue:246.0f/255.0f alpha:0.7f].CGColor;
circleMiddle.zPosition = 3;
[_containerView.layer addSublayer:circleMiddle];
}
我的问题是,如果我多次调用此方法,每次都会添加子视图和子层,但不会像我希望的那样重新绘制。为什么会这样?
如果您使用 addSublayer
或 addSubview
,那么肯定会向 containerView
添加新图层或新视图。如果你不想每次都添加它并且想要重绘(我的意思是新实例 - 正如我从你的重绘词中理解的那样)然后添加下面的行,
_containerView = [[UIView alloc]initWithFrame:self.view.bounds]; // you can set your desired frame
在 gradeAnimation
方法中作为第一行。所以它每次都会创建新的实例。或者您可以先删除 sublayers
和 subviews
然后添加新的!!!或者您可以在方法中创建新的 containerView
并可以向其添加子视图和图层并将其分配给 _containerView
.
这里只说一个对象,scoreLabel是UICountingLabel的一个对象。每次调用 gradeAnimation: withDuration: 方法时,您都在创建一个新对象并将其添加到您的视图中。
您可以取一个属性,然后启动并添加您的视图一次,在该方法中您可以更改对象的位置或其他内容。
如果您不想更改当前方法,那么在调用该方法之前,您必须从视图中删除以前的对象。这样在您的视图中一次我们将只有一个对象。
首先从containerView中移除所有子层。在方法的开头添加以下代码。
for (CALayer *layer in _containerView) {
[layer removeFromSuperlayer];
}
我有一个构建界面的方法,它向主 UIView(下面代码中的 containerView)添加一个子视图和一些子层:
- (void)gradeAnimation:(NSNumber*)grade withDuration:(double)duration {
scoreLabel = [[UICountingLabel alloc] init];
scoreLabel.frame = CGRectOffset(_gradeLabel.frame, 0, 5);
[_containerView addSubview:scoreLabel];
// Other code
UIBezierPath *circlePathMin = [UIBezierPath bezierPathWithArcCenter:CGPointMake(_gradientView.center.x, _gradientView.center.y) radius:_gradientView.frame.size.height * 0.5 - 5 startAngle:-M_PI_4*1.2 endAngle:angle1 clockwise:YES];
circleMin = [CAShapeLayer layer];
circleMin.path = circlePathMin.CGPath;
circleMin.lineCap = kCALineCapButt;
circleMin.fillColor = [UIColor clearColor].CGColor;
circleMin.lineWidth = 14;
circleMin.strokeColor = [UIColor colorWithRed:246.0/255.0f green:246.0f/255.0f blue:246.0f/255.0f alpha:0.7f].CGColor;
circleMin.zPosition = 3;
[_containerView.layer addSublayer:circleMin];
UIBezierPath *circlePathMax = [UIBezierPath bezierPathWithArcCenter:CGPointMake(_gradientView.center.x, _gradientView.center.y) radius:_gradientView.frame.size.height * 0.5 - 5 startAngle:angle2 endAngle:5*M_PI_4*1.2 clockwise:YES];
circleMax = [CAShapeLayer layer];
circleMax.path = circlePathMax.CGPath;
circleMax.lineCap = kCALineCapButt;
circleMax.fillColor = [UIColor clearColor].CGColor;
circleMax.lineWidth = 14;
circleMax.strokeColor = [UIColor colorWithRed:246.0/255.0f green:246.0f/255.0f blue:246.0f/255.0f alpha:0.7f].CGColor;
circleMax.zPosition = 3;
[_containerView.layer addSublayer:circleMax];
UIBezierPath *circlePathMiddle = [UIBezierPath bezierPathWithArcCenter:CGPointMake(_gradientView.center.x, _gradientView.center.y) radius:_gradientView.frame.size.height * 0.5 - 5 startAngle:angle1+offsetRight endAngle:angle2+offsetLeft clockwise:YES];
circleMiddle = [CAShapeLayer layer];
circleMiddle.path = circlePathMiddle.CGPath;
circleMiddle.lineCap = kCALineCapButt;
circleMiddle.fillColor = [UIColor clearColor].CGColor;
circleMiddle.lineWidth = 14;
circleMiddle.strokeColor = [UIColor colorWithRed:246.0/255.0f green:246.0f/255.0f blue:246.0f/255.0f alpha:0.7f].CGColor;
circleMiddle.zPosition = 3;
[_containerView.layer addSublayer:circleMiddle];
}
我的问题是,如果我多次调用此方法,每次都会添加子视图和子层,但不会像我希望的那样重新绘制。为什么会这样?
如果您使用 addSublayer
或 addSubview
,那么肯定会向 containerView
添加新图层或新视图。如果你不想每次都添加它并且想要重绘(我的意思是新实例 - 正如我从你的重绘词中理解的那样)然后添加下面的行,
_containerView = [[UIView alloc]initWithFrame:self.view.bounds]; // you can set your desired frame
在 gradeAnimation
方法中作为第一行。所以它每次都会创建新的实例。或者您可以先删除 sublayers
和 subviews
然后添加新的!!!或者您可以在方法中创建新的 containerView
并可以向其添加子视图和图层并将其分配给 _containerView
.
这里只说一个对象,scoreLabel是UICountingLabel的一个对象。每次调用 gradeAnimation: withDuration: 方法时,您都在创建一个新对象并将其添加到您的视图中。
您可以取一个属性,然后启动并添加您的视图一次,在该方法中您可以更改对象的位置或其他内容。
如果您不想更改当前方法,那么在调用该方法之前,您必须从视图中删除以前的对象。这样在您的视图中一次我们将只有一个对象。
首先从containerView中移除所有子层。在方法的开头添加以下代码。
for (CALayer *layer in _containerView) {
[layer removeFromSuperlayer];
}