Мне нужно, чтобы у подвидов была отрицательная исходная точка, а CGRectUnion
- это честный способ ObjC, как кто-то упоминал в комментариях. Для начала посмотрим, как это работает:
Как вы можете видеть ниже, мы предполагаем, что некоторые подпредставления лежат снаружи, поэтому нам нужно сделать две вещи, чтобы это выглядело хорошо, не затрагивая расположение подпредставлений:
- Переместить рамку вида в крайнее верхнее левое положение
- Переместите подпредставления в противоположном направлении, чтобы свести на нет эффект.
Картинка стоит тысячи слов.
Код стоит миллиард слов. Вот решение:
@interface UIView (UIView_Expanded)
- (void)resizeToFitSubviews;
@end
@implementation UIView (UIView_Expanded)
- (void)resizeToFitSubviews
{
// 1 - calculate size
CGRect r = CGRectZero;
for (UIView *v in [self subviews])
{
r = CGRectUnion(r, v.frame);
}
// 2 - move all subviews inside
CGPoint fix = r.origin;
for (UIView *v in [self subviews])
{
v.frame = CGRectOffset(v.frame, -fix.x, -fix.y);
}
// 3 - move frame to negate the previous movement
CGRect newFrame = CGRectOffset(self.frame, fix.x, fix.y);
newFrame.size = r.size;
[self setFrame:newFrame];
}
@end
Я думал, что было бы интересно написать в Swift 2.0 .. Я был прав!
extension UIView {
func resizeToFitSubviews() {
let subviewsRect = subviews.reduce(CGRect.zero) {
$0.union($1.frame)
}
let fix = subviewsRect.origin
subviews.forEach {
$0.frame.offsetInPlace(dx: -fix.x, dy: -fix.y)
}
frame.offsetInPlace(dx: fix.x, dy: fix.y)
frame.size = subviewsRect.size
}
}
И площадка доказательство:
Обратите внимание, что visualAidView
не двигается и помогает увидеть, как изменяется superview
при сохранении позиций подпредставлений.
let canvas = UIView(frame: CGRect(x: 0, y: 0, width: 80, height: 80))
canvas.backgroundColor = UIColor.whiteColor()
let visualAidView = UIView(frame: CGRect(x: 5, y: 5, width: 70, height: 70))
visualAidView.backgroundColor = UIColor(white: 0.8, alpha: 1)
canvas.addSubview(visualAidView)
let superview = UIView(frame: CGRect(x: 15, y: 5, width: 50, height: 50))
superview.backgroundColor = UIColor.purpleColor()
superview.clipsToBounds = false
canvas.addSubview(superview)
[
{
let view = UIView(frame: CGRect(x: -10, y: 0, width: 15, height: 15))
view.backgroundColor = UIColor.greenColor()
return view
}(),
{
let view = UIView(frame: CGRect(x: -10, y: 40, width: 35, height: 15))
view.backgroundColor = UIColor.cyanColor()
return view
}(),
{
let view = UIView(frame: CGRect(x: 45, y: 40, width: 15, height: 30))
view.backgroundColor = UIColor.redColor()
return view
}(),
].forEach { superview.addSubview($0) }