วิธีจัดกึ่งกลางย่อยของ UIView


128

ฉันมีUIViewด้านในUIViewและฉันต้องการให้ด้านในUIViewอยู่กึ่งกลางด้านในเสมอโดยไม่ต้องปรับขนาดความกว้างและความสูง

ฉันได้ตั้งเสาและสปริงเพื่อให้อยู่ด้านบน / ซ้าย / ขวา / ล่างโดยไม่ต้องปรับขนาด แต่มันก็ยังไม่ได้อยู่ตรงกลาง ความคิดใด ๆ


2
คำตอบที่ยอมรับนั้นผิดและจะผิดพลาด คำตอบของ Hejazi นั้นยอดเยี่ยม
Fattie

คำตอบ:


209

Objective-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เป็นจะไม่ได้กำหนดถ้ามุมมองที่มีframe transform
omz

1
จริงๆแล้วมันจะไม่สร้างความแตกต่างในกรณีนี้เนื่องจากsizeมีการใช้งานเพียงอย่างเดียว
Peter DeWeese

1
ไม่สำคัญว่าframeคุณสมบัติทั้งหมดจะไม่ถูกกำหนดถ้ามุมมองมีการtransformแปลงข้อมูลที่ไม่ใช่ตัวตน อ่านเอกสารเกี่ยวกับกรอบทรัพย์สินของ UIView
omz

6
แต่น่าเสียดายที่คำตอบนี้คือผิดจริง เพียงใช้คำตอบที่ถูกต้องของ Heja
Fattie

@Fattie มีอะไรผิดปกติที่นี่? ฉันใช้สำหรับการจัดศูนย์กลางของ ImageView ภายในมุมมองและใช้งานได้
jreft56

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) ' สิ่งนี้จะทำให้ subview ของคุณอยู่กึ่งกลางไม่ว่าคุณจะตั้งค่าศูนย์มุมมองหลักไว้ที่ใด
ชื่อเก่า

1
นอกจากนี้ยังไม่เป็นประโยชน์หากมุมมองยังไม่ถูกเพิ่มไปยังลำดับชั้นของมุมมอง (เช่นเมื่อใส่วัตถุ)
Victor Jalencas

1
@Hejazi มันจะดีถ้าเพิ่มคำตอบอย่างรวดเร็วด้วย)
Milad Faridnia

1
@Soumen ไม่มีความแตกต่าง UIView.boundsจะสัมพันธ์กับมุมมองของตัวเอง (และดังนั้นจึงbounds.originเป็นครั้งแรกที่ศูนย์) ในขณะที่UIView.centerระบุไว้ในระบบพิกัดของSuperView
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()
    }

}

สิ่งนี้จะสร้างมุมมองนี้: จุดกำเนิดสี่เหลี่ยมผืนผ้าสีดำและกึ่งกลางไม่พอดีกับพิกัดเดียวกันกับพาเรนต์ของมัน

ป้อนคำอธิบายรูปภาพที่นี่

ทีนี้ลองเพิ่ม subView อีก SubSubView และให้ 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;

คุณคาดหวังให้ที่มาของสี่เหลี่ยมสีม่วงเหมือนกันกับมันเป็นแม่ (สี่เหลี่ยมสีดำ) แต่มันอยู่ใต้มันและทำไมมันถึงเป็นอย่างนั้น? เนื่องจากเมื่อคุณเพิ่มมุมมองไปยังมุมมองอื่นเฟรมมุมมอง "โลก" ตอนนี้เป็นเฟรมย่อยของแม่ถ้าคุณมีมุมมองที่ว่าต้นกำเนิดบนหน้าจอหลักอยู่ที่ coords (15,15) สำหรับมุมมองย่อยทั้งหมด มุมบนซ้ายจะเป็น (0,0)

นี่คือเหตุผลที่คุณต้องอ้างถึงผู้ปกครองเสมอโดยสี่เหลี่ยมผืนผ้าที่ถูกผูกไว้ซึ่งเป็น "โลก" ของการดูย่อยช่วยให้แก้ไขบรรทัดนี้ไปที่:

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

และดูเวทย์มนตร์ subSubview ตอนนี้ตั้งอยู่ในแหล่งกำเนิดของมัน:

ป้อนคำอธิบายรูปภาพที่นี่

ดังนั้นคุณชอบ "ตกลงฉันแค่ต้องการให้มุมมองของฉันอยู่ตรงกลางโดยมุมมองพ่อแม่ของฉันเรื่องใหญ่คืออะไร" ดีมันไม่ใช่เรื่องใหญ่คุณเพียงแค่ต้อง "แปล" จุดศูนย์กลางของผู้ปกครองซึ่งนำมาจากกรอบไปสู่กึ่งกลางขอบเขตของผู้ปกครองโดยทำสิ่งนี้:

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

คุณกำลังบอกเขาว่า "พาผู้ปกครองไปที่จุดศูนย์กลางและเปลี่ยนเป็น subSubView world"

และคุณจะได้รับผลลัพธ์นี้:

ป้อนคำอธิบายรูปภาพที่นี่


ไปที่ตำแหน่ง 'subSubView.center = subView.convertPoint (subView.center, fromView: subSubView)'
Thamarai T

26

ฉันจะใช้:

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

ฉันชอบที่จะใช้CGRectตัวเลือก ...

สวิฟท์ 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); เป็นวิธีแก้ปัญหาแบบ catch-all / use ที่ใดก็ได้ในการแก้ไขปัญหา BL
Fattie

1
@ JoeBlow: ขอบคุณสำหรับหัวขึ้น ฉันเคยชอบการปัดเศษ แต่ด้วยรูปแบบบล็อกมันก็ดีกว่าที่จะใช้CGRectIntegral
Cemal Eker

คุณช่วยอธิบายซินแทกซ์ที่คุณใช้เพื่อตั้งค่าเฟรมได้หรือไม่ฉันไม่เคยเห็นมาก่อน เป็นคำสั่งสุดท้ายใน "การปิด" ที่กำหนดให้กับทรัพย์สินหรือไม่ และฉันจะหามันได้จากเอกสารของ Apple?
โยฮันเนส

"หากคุณใช้วิธีการชำระอัตโนมัติระดับ UIKit เท่านั้น:" จะทำให้เกิดข้อผิดพลาด
จอนนี่

13

วิธีที่ง่ายที่สุด:

child.center = parent.center

สิ่งที่ฉันหมายถึงคือคุณควรเพิ่มคำอธิบาย / คำอธิบายเพิ่มเติมเกี่ยวกับวิธีการทำงาน
Tushar

ค้นหาคำตอบของประเภทนี้มากมายคำตอบง่ายๆสำหรับฉัน ขอบคุณ
gbossa

9

ป้อนคำอธิบายรูปภาพที่นี่

ตั้งค่าหน้ากากปรับขนาดอัตโนมัตินี้เป็นมุมมองภายในของคุณ


1
ด้วยการเลื่อนอัตโนมัติไม่มีหน้าต่างการปรับขนาดอัตโนมัติ
อัลเลน

@ ทั้งหมดคุณต้องปิดใช้งานการชำระอัตโนมัติหากคุณต้องการใช้การเปลี่ยนขนาดอัตโนมัติ
Mayank Jain

8

ด้วย IOS9 คุณสามารถใช้ layout anchor API

รหัสจะมีลักษณะเช่นนี้:

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

ข้อได้เปรียบของสิ่งนี้CGPointMakeหรือCGRectว่าด้วยวิธีการเหล่านี้คุณกำลังตั้งจุดศูนย์กลางของมุมมองเป็นค่าคงที่ แต่ด้วยเทคนิคนี้คุณกำลังตั้งค่าความสัมพันธ์ระหว่างสองมุมมองที่จะเก็บไว้ตลอดไปไม่ว่าparentviewเปลี่ยนแปลงจะเป็นอย่างไร

ให้แน่ใจก่อนทำสิ่งนี้ให้ทำ:

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

และเพื่อตั้งค่า translatesAutoresizingMaskIntoConstraintsสำหรับแต่ละมุมมองเป็นเท็จ

การทำเช่นนี้จะช่วยป้องกันการหยุดทำงานและเลย์เอาต์อัตโนมัติจากการแทรกแซง


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
ตัวอย่างโค้ดที่สองทำงานได้อย่างสมบูรณ์แบบรวดเร็ว 4 GREAT 👍🏻!
iGhost

ใช่! ขอบคุณในที่สุด ไม่ทราบเกี่ยวกับสิ่ง midX / midY Perfecto
Dave Y

5

การใช้ศูนย์เดียวกันในมุมมองและมุมมองย่อยเป็นวิธีที่ง่ายที่สุดในการดำเนินการ คุณสามารถทำอะไรเช่นนี้

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

สิ่งนี้จะจัดมุมมองย่อยให้ตรงกึ่งกลางตามมุมมองมุมมองระดับสูง ในกรณีข้างต้นมันทำงานได้เพราะแหล่งกำเนิดอยู่ที่ (0, 0)
Abdurrahman Mubeen Ali

3

ทางออกก็มีPureLayoutautoCenterInSuperviewใช้

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

[outerview addSubview:innerView];

[innerView autoCenterInSuperview];

นี่คือลักษณะที่ปรากฏ:

ศูนย์รวม PureLayout


2

ใน c # หรือ Xamarin.ios เราสามารถใช้สิ่งนี้

imageView.Center = CGPoint ใหม่ (tempView.Frame.Size.Width / 2, tempView.Frame.Size.Height / 2);


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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.