如何居中UIView的子视图


128

我有一个UIView内部UIViewm,我希望内部UIView始终位于外部m的中心,而不必调整宽度和高度的大小。

我已经设置了支柱和弹簧,使其位于顶部/左侧/右侧/底部,而无需设置调整大小。但是它仍然没有居中。任何想法?


2
接受的答案是错误的,将崩溃。Hejazi的答案很棒。
Fattie

Answers:


209

目标C

yourSubView.center = CGPointMake(yourView.frame.size.width  / 2, 
                                 yourView.frame.size.height / 2);

迅速

yourSubView.center = CGPoint(x: yourView.frame.size.width  / 2,
                             y: yourView.frame.size.height / 2)

51
如果视图具有,则应使用bounds而不是frame,因为frameundefined是未定义的transform
omz 2012年

1
在这种情况下,实际上并没有什么不同,仅size在使用中。
彼得·德威斯

1
没关系,frame如果视图具有transform不是标识转换的视图,则整个属性都不确定。阅读有关UIView的frame属性文档
omz 2012年

6
不幸的是,这个答案实际上是错误的。只需使用Heja的正确答案即可。
Fattie

@Fattie这里到底有什么问题?我用它来使ImageView在View中居中,并且可以正常工作。
jreft56 '19

284

您可以执行此操作,它将始终有效:

child.center = [parent convertPoint:parent.center fromView:parent.superview];

对于Swift:

child.center = parent.convert(parent.center, from:parent.superview)

1
并且不要忘了之后,child.frame = CGRectIntegral(child.frame);
Fattie

8
一:仅当您尚未更改父视图的中心/位置时,此方法才有效。第二:如果您使用的是此方法,则无需转换点(它已经采用正确的格式),只需使用即可child.center = parent.center。我会使用child.center = CGPointMake(parent.bounds.height / 2,parent.bounds.width / 2)。无论您的父视图中心设置为什么,这都将始终使子视图居中。
旧名称

1
如果尚未将视图添加到视图层次结构中(例如,插入对象时),这也没有用
Victor Jalencas

1
@Hejazi也可以添加一个快速的答案;)
Milad Faridnia

1
@Soumen不,有区别。UIView.bounds相对于视图本身(因此bounds.origin最初为零),而UIView.centerSuperview的坐标系中指定。
Hejazi

41

在开始之前,我们只需要提醒一下原点是CGPoint视图的左上角。了解观点和父母的重要事项。

让我们看一下这个简单的代码,一个视图控制器,在其视图中添加了一个黑色正方形:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        createDummyView()
        super.view.backgroundColor = UIColor.cyanColor();
    }

    func createDummyView(){
        var subView = UIView(frame: CGRect(x: 15, y: 50, width: 50 , height: 50));
        super.view.addSubview(subView);
        view.backgroundColor = UIColor.blackColor()
    }

}

这将创建此视图:黑色矩形的原点和中心确实适合与父级相同的坐标

在此处输入图片说明

现在让我们尝试添加另一个SubSubView的SubView,并为SubSubview提供与SubView相同的起源,但是让SubSubView成为SubView的子视图

我们将添加以下代码:

var subSubView = UIView();
subSubView.frame.origin = subView.frame.origin;
subSubView.frame.size = CGSizeMake(20, 20);
subSubView.backgroundColor = UIColor.purpleColor()
subView.addSubview(subSubView)

结果如下:

在此处输入图片说明

由于这一行:

subSubView.frame.origin = subView.frame.origin;

您希望紫色矩形的原点与父矩形(黑色矩形)相同,但是在其下方,为什么呢?因为当您将视图添加到另一个视图时,subView框架“ world”现在是其父级BOUND RECTANGLE,如果您有一个视图,认为它在主屏幕上的所有子视图的坐标为(15,15),则左上角将是(0,0)

这就是为什么您需要始终通过其绑定矩形(即其subViews的“世界”)引用父对象的原因,因此请将该行修复为:

subSubView.frame.origin = subView.bounds.origin;

看到魔术,subSubview现在完全位于其父原点中:

在此处输入图片说明

因此,您喜欢“好吧,我只想以父母的观点为中心,这有什么大不了的?” 好吧,这没什么大不了的,您只需要通过执行以下操作即可将从其框架获取的父中心点“转换”为父边界中心:

subSubView.center = subView.convertPoint(subView.center, fromView: subSubView);

您实际上是在告诉他“以父母的视点为中心,并将其转换为subSubView世界”。

您将得到以下结果:

在此处输入图片说明


行'subSubView.center = subView.convertPoint(subView.center,fromView:subSubView)'放置在哪里?
Thamarai T

26

我会用:

self.childView.center = CGPointMake(CGRectGetMidX(self.parentView.bounds),
                                    CGRectGetMidY(self.parentView.bounds));

我喜欢使用这些CGRect选项...

SWIFT 3:

self.childView.center = CGPoint(x: self.parentView.bounds.midX,
                                        y: self.parentView.bounds.midY);

19

1.如果启用了自动版式:

  • 提示:若要使用自动布局将一个视图置于另一个视图的中心,您可以对共享至少一个父视图的任何两个视图使用相同的代码。

首先禁用子视图的自动调整大小

UIView *view1, *view2;
[childview setTranslatesAutoresizingMaskIntoConstraints:NO];
  1. 如果您是UIView + Autolayout或Purelayout

    [view1 autoAlignAxis:ALAxisHorizontal toSameAxisOfView:view2];
    [view1 autoAlignAxis:ALAxisVertical toSameAxisOfView:view2];
  2. 如果仅使用UIKit级别的自动布局方法:

    [view1 addConstraints:({
        @[ [NSLayoutConstraint
           constraintWithItem:view1
           attribute:NSLayoutAttributeCenterX
           relatedBy:NSLayoutRelationEqual
           toItem:view2
           attribute:NSLayoutAttributeCenterX
           multiplier:1.f constant:0.f],
    
           [NSLayoutConstraint
            constraintWithItem:view1
            attribute:NSLayoutAttributeCenterY
            relatedBy:NSLayoutRelationEqual
            toItem:view2
            attribute:NSLayoutAttributeCenterY
            multiplier:1.f constant:0.f] ];
    })];

2.没有自动布局:

我更喜欢:

UIView *parentView, *childView;
[childView setFrame:({
    CGRect frame = childView.frame;

    frame.origin.x = (parentView.frame.size.width - frame.size.width) / 2.0;
    frame.origin.y = (parentView.frame.size.height - frame.size.height) / 2.0;

    CGRectIntegral(frame);
})];

6
应当注意,与公认的答案不同,此解决方案将在像素边界上对齐,并防止某些宽度的视图模糊。
布拉德·拉森

1
如果我没记错的话,child.frame = CGRectIntegral(child.frame); 是BL所描述的问题的一种极好的包罗万象/可在任何地方使用的解决方案。
Fattie

1
@JoeBlow:感谢大家的注意。我曾经喜欢四舍五入,但使用块样式会更优雅CGRectIntegral
Cemal Eker 2014年

您能否解释一下用于设置框架的语法,我之前从未见过。是否始终是分配给属性的“闭包”中的最后一条语句?在Apple文档中我可以在哪里找到它?
约翰内斯,2014年

“如果仅使用UIKit级自动布局方法:”将导致错误。
乔尼2015年

13

最简单的方法:

child.center = parent.center

我的意思是,您应该添加更多有关此工作原理的解释/说明。
Tushar

搜索了很多这种类型的答案,这个简单的答案对我有用。谢谢。
gbossa


8

借助IOS9,您可以使用布局锚点API。

代码如下所示:

childview.centerXAnchor.constraintEqualToAnchor(parentView.centerXAnchor).active = true
childview.centerYAnchor.constraintEqualToAnchor(parentView.centerYAnchor).active = true

over CGPointMake或or 的优点CGRect是,使用这些方法,您可以将视图的中心设置为常数,但是使用此技术,您可以设置将永久保留的两个视图之间的关系,而无论parentview更改如何。

在执行此操作之前,请务必确保:

        self.view.addSubview(parentView)
        self.view.addSubView(chidview)

并将translatesAutoresizingMaskIntoConstraints每个视图的设置为false。

这将防止崩溃和自动布局干扰。


8

您可以使用

yourView.center = CGPointMake(CGRectGetMidX(superview.bounds), CGRectGetMidY(superview.bounds))

在Swift 3.0中

yourView.center = CGPoint(x: superview.bounds.midX, y: superview.bounds.midY)

1
第二个代码示例可在Swift 4中完美运行。
iGhost,

是!最后,谢谢你。不知道那midX / midY的事情。完美
Dave Y

5

在视图和子视图中使用相同的中心是最简单的方法。你可以做这样的事情,

UIView *innerView = ....;
innerView.view.center = self.view.center;
[self.view addSubView:innerView];

这将使子视图相对于超级视图居中。在上述情况下,它起作用是因为原点位于(0,0)。
Abdurrahman Mubeen Ali

3

与另一种溶液PureLayout使用autoCenterInSuperview

// ...
UIView *innerView = [UIView newAutoLayoutView];
innerView.backgroundColor = [UIColor greenColor];
[innerView autoSetDimensionsToSize:CGSizeMake(100, 30)];

[outerview addSubview:innerView];

[innerView autoCenterInSuperview];

它是这样的:

以PureLayout为中心



1

我会用:

child.center = CGPointMake(parent.bounds.height / 2, parent.bounds.width / 2)

这很简单,简短而可爱。如果您使用上述@Hejazi的答案并将parent.center其设置为除(0,0)子视图以外的其他任何内容,将不会居中!


0
func callAlertView() {

    UIView.animate(withDuration: 0, animations: {
        let H = self.view.frame.height * 0.4
        let W = self.view.frame.width * 0.9
        let X = self.view.bounds.midX - (W/2)
        let Y = self.view.bounds.midY - (H/2)
        self.alertView.frame = CGRect(x:X, y: Y, width: W, height: H)
        self.alertView.layer.borderWidth = 1
        self.alertView.layer.borderColor = UIColor.red.cgColor
        self.alertView.layer.cornerRadius = 16
        self.alertView.layer.masksToBounds = true
        self.view.addSubview(self.alertView)

    })


}// calculation works adjust H and W according to your requirement
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.