Bagaimana cara memusatkan subview dari UIView


128

Saya memiliki bagian UIViewdalam UIViewm dan saya ingin bagian dalam UIViewselalu berpusat di bagian luar, tanpa harus mengubah ukuran lebar dan tinggi.

Saya telah mengatur struts dan pegas sehingga berada di atas / kiri / kanan / bawah tanpa mengatur ukurannya. Tapi itu masih tidak terpusat. Ada ide?


2
Jawaban yang diterima salah dan akan macet. Jawaban Hejazi sangat bagus.
Fattie

Jawaban:


209

Objektif-C

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

Cepat

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

51
Anda harus menggunakan boundsdan bukan frame, karena frametidak terdefinisi jika tampilan memiliki transform.
omz

1
Ini sebenarnya tidak akan membuat perbedaan dalam hal ini, karena hanya sizedigunakan.
Peter DeWeese

1
Itu tidak masalah, seluruh frameproperti tidak terdefinisi jika pandangan memiliki transformyang bukan transformasi identitas; baca dokumentasi pada properti bingkai UIView .
omz

6
Sayangnya jawaban ini sebenarnya salah . Cukup gunakan jawaban Heja yang benar.
Fattie

@ Fat apa yang salah di sini? Saya menggunakannya untuk memusatkan ImageView dalam tampilan dan berfungsi.
jreft56

284

Anda dapat melakukan ini dan itu akan selalu berhasil:

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

Dan untuk Swift:

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

1
dan jangan lupa setelah itu, child.frame = CGRectIntegral (child.frame);
Fattie

8
Satu: Ini hanya berfungsi jika Anda belum mengubah pusat / lokasi tampilan orang tua Anda. Kedua: Jika Anda menggunakan metode ini, tidak perlu mengubah titik (sudah dalam format yang benar) cukup gunakan child.center = parent.center. Saya akan menggunakan `child.center = CGPointMake (parent.bounds.height / 2, parent.bounds.width / 2) '. Ini akan selalu membuat subview Anda terpusat terlepas dari apa yang diatur oleh pusat tampilan orang tua Anda.
Nama Lama

1
Ini juga tidak berguna jika tampilan belum ditambahkan ke hierarki tampilan (seperti ketika initting objek)
Victor Jalencas

1
@Hejazi Akan lebih baik untuk menambahkan jawaban cepat juga;)
Milad Faridnia

1
@ Soal Tidak, ada perbedaan. UIView.boundsrelatif terhadap tampilan itu sendiri (dan karena bounds.originitu awalnya nol), sementara UIView.centerditentukan dalam sistem koordinat superview .
Hejazi

41

Sebelum kita mulai, mari kita ingatkan bahwa titik asal adalah sudut kiri CGPointatas tampilan. Suatu hal penting untuk dipahami tentang pandangan dan orang tua.

Mari kita lihat kode sederhana ini, pengontrol tampilan yang menambah tampilan kotak hitam:

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()
    }

}

Ini akan membuat tampilan ini: asal dan pusat persegi panjang hitam tidak cocok dengan koordinat yang sama seperti orang tuanya

masukkan deskripsi gambar di sini

Sekarang mari kita coba menambahkan subView SubSubView lain, dan memberikan subSubview asal yang sama dengan subView, tetapi buat subSubView tampilan anak dari subView

Kami akan menambahkan kode ini:

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

Dan inilah hasilnya:

masukkan deskripsi gambar di sini

Karena baris ini:

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

Anda mengharapkan asal persegi ungu untuk sama dengan orang tuanya (persegi panjang hitam) tetapi berada di bawahnya, dan mengapa begitu? Karena ketika Anda menambahkan tampilan ke tampilan lain, frame subView "dunia" sekarang adalah parent BOUND RECTANGLE, jika Anda memiliki pandangan bahwa itu asalnya pada layar utama adalah pada coords (15,15) untuk semua sub tampilan itu, sudut kiri atas adalah (0,0)

Inilah sebabnya mengapa Anda harus selalu merujuk ke induk dengan persegi panjang terikat itu, yang merupakan "dunia" dari subViews itu, mari perbaiki baris ini ke:

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

Dan lihat keajaibannya, subSubview sekarang terletak persis di asal orangtuanya:

masukkan deskripsi gambar di sini

Jadi, Anda suka, "Saya hanya ingin memusatkan pandangan saya dengan pandangan orang tua saya, apa masalahnya?" baik, itu bukan masalah besar, Anda hanya perlu "menerjemahkan" titik pusat induk yang diambil dari bingkai itu ke pusat batas induk dengan melakukan ini:

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

Anda sebenarnya mengatakan kepadanya "bawa pusat tampilan orang tua, dan ubah menjadi dunia subSubView".

Dan Anda akan mendapatkan hasil ini:

masukkan deskripsi gambar di sini


Ke tempat baris 'subSubView.center = subView.convertPoint (subView.center, fromView: subSubView)' ditempatkan?
Thamarai T

26

Saya akan menggunakan:

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

Saya suka menggunakan CGRectopsi ...

SWIFT 3:

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

19

1. Jika Anda mengaktifkan pembayaran otomatis:

  • Petunjuk: Untuk memusatkan tampilan pada tampilan lain dengan autolayout, Anda dapat menggunakan kode yang sama untuk dua tampilan yang berbagi setidaknya satu tampilan induk.

Pertama-tama nonaktifkan pandangan anak autoresizing

UIView *view1, *view2;
[childview setTranslatesAutoresizingMaskIntoConstraints:NO];
  1. Jika Anda UIView + Autolayout atau Purelayout :

    [view1 autoAlignAxis:ALAxisHorizontal toSameAxisOfView:view2];
    [view1 autoAlignAxis:ALAxisVertical toSameAxisOfView:view2];
  2. Jika Anda hanya menggunakan metode pembayaran otomatis tingkat 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. Tanpa pembayaran otomatis:

Saya lebih memilih:

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
Perlu dicatat bahwa, tidak seperti jawaban yang diterima, solusi ini akan menyelaraskan dengan bersih pada batas piksel dan mencegah kekaburan tampilan untuk lebar tertentu.
Brad Larson

1
Jika saya tidak salah, child.frame = CGRectIntegral (child.frame); adalah solusi catch-all / use dimanapun yang elegan untuk masalah yang dijelaskan BL.
Fattie

1
@ JoBlow: Terima kasih atas kepala. Saya dulu suka pembulatan tetapi dengan gaya balok itu lebih elegan untuk digunakanCGRectIntegral
Cemal Eker

Bisakah Anda menjelaskan sintaks yang Anda gunakan untuk mengatur frame, saya belum pernah melihatnya sebelumnya. Apakah selalu pernyataan terakhir dalam "penutupan" yang ditugaskan ke properti? Dan di mana saya bisa menemukannya di dokumen Apple?
Johannes

"Jika Anda hanya menggunakan metode pembayaran otomatis tingkat UIKit:" menghasilkan kesalahan.
Jonny

13

Cara termudah:

child.center = parent.center

Yang saya maksud adalah Anda harus menambahkan lebih banyak penjelasan / deskripsi tentang cara kerjanya.
Tushar

Mencari banyak jawaban dari tipe ini, yang sederhana ini sangat membantu saya. Terima kasih.
gbossa

9

masukkan deskripsi gambar di sini

Atur topeng autoresizing ini ke tampilan dalam Anda.


1
Dengan autolayout, tidak ada jendela autosizing.
Allen

@ Allen Anda harus menonaktifkan autolayout jika Anda ingin menggunakan autoresizing.
Mayank Jain

8

Dengan iOS9 Anda dapat menggunakan layout anchor API.

Kode akan terlihat seperti ini:

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

Keuntungan dari ini lebih CGPointMakeatau CGRectadalah bahwa dengan metode-metode itu Anda menetapkan pusat pandangan ke konstan tetapi dengan teknik ini Anda menetapkan hubungan antara dua pandangan yang akan bertahan selamanya, tidak peduli bagaimana parentviewperubahannya.

Pastikan sebelum Anda melakukan ini untuk melakukan:

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

dan untuk mengatur translatesAutoresizingMaskIntoConstraintsagar setiap tampilan menjadi false.

Ini akan mencegah gangguan dan AutoLayout mengganggu.


8

Kamu bisa memakai

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

Dan In Swift 3.0

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

1
Contoh kode kedua bekerja dengan sempurna di swift 4. GREAT 👍🏻!
iGhost

IYA! Akhirnya terima kasih Tidak tahu tentang hal midX / midY. Perfecto.
Dave Y

5

Menggunakan pusat yang sama dalam tampilan dan subview adalah cara paling sederhana untuk melakukannya. Anda dapat melakukan sesuatu seperti ini,

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

Ini akan memusatkan sub tampilan sehubungan dengan tampilan super view. Dalam kasus di atas, ini berfungsi karena asal pada (0, 0).
Abdurrahman Mubeen Ali

3

Solusi lain dengan menggunakan PureLayoutautoCenterInSuperview .

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

[outerview addSubview:innerView];

[innerView autoCenterInSuperview];

Begini tampilannya:

Pusatkan dengan PureLayout


2

Di c # atau Xamarin.ios, kita bisa menggunakan seperti ini

imageView.Center = CGPoint baru (tempView.Frame.Size.Width / 2, tempView.Frame.Size.Height / 2);


1

Saya akan menggunakan:

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

Ini sederhana, pendek, dan manis. Jika Anda menggunakan jawaban @ Hejazi di atas dan parent.centerdiatur ke hal lain selain (0,0)subview Anda tidak akan terpusat!


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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.