UIView alt görünümü nasıl ortalanır


128

İçimde UIViewbir UIViewm var ve iç UIViewkısmın genişliği ve yüksekliği yeniden boyutlandırmak zorunda kalmadan her zaman dış olanın içinde ortalanmasını istiyorum .

Destekleri ve yayları, yeniden boyutlandırmayı ayarlamadan üst / sol / sağ / altta olacak şekilde ayarladım. Ama yine de ortalanmıyor. Herhangi bir fikir?


2
Kabul edilen cevap yanlış ve çökecek. Hejazi'nin cevabı harika çalışıyor.
Şişko

Yanıtlar:


209

Objective-C

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

hızlı

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

51
Sen kullanmalıdır boundsdeğil framegibi framegörünümü bir sahipse tanımlanmamış transform.
omz

1
Aslında sadece sizekullanıldığı için bu durumda farklı olmayacak .
Peter DeWeese

1
Bu önemli değil, frameeğer görünümde transformkimlik dönüşümü olmayan bir özellik varsa , tüm özellik tanımsızdır ; UIView'ın çerçeve özelliğiyle ilgili belgeleri okuyun .
omz

6
Maalesef bu cevap aslında yanlış . Basitçe Heja'nın doğru cevabını kullanın.
Şişko

@Fattie burada tam olarak yanlış olan ne? Bunu bir Görünüm içinde bir ImageView'u ortalamak için kullandım ve çalışıyor.
jreft56

284

Bunu yapabilirsiniz ve her zaman işe yarayacaktır:

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

Ve Swift için:

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

1
ve daha sonra unutmayın, child.frame = CGRectIntegral (child.frame);
Şişko

8
Bir: Bu, yalnızca ebeveyn görünümünüzün merkezini / konumunu değiştirmediyseniz çalışır. İkincisi: Bu yöntemi kullanıyorsanız, noktayı dönüştürmeye gerek yoktur (zaten doğru formattadır) sadece kullanın child.center = parent.center. `` Child.center = CGPointMake (parent.bounds.height / 2, parent.bounds.width / 2) 'kullanırım. Bu, ebeveyn görünüm merkezinizin neye ayarlandığına bakılmaksızın her zaman alt görünümünüzün ortalanmasını sağlar.
Eski İsim

1
Görünüm hiyerarşisine henüz eklenmemişse de kullanışlı değildir (nesneyi başlatırken olduğu gibi)
Victor

1
@Hejazi Hızlı cevap eklemek güzel olurdu;)
Milad Faridnia

1
@Soumen Hayır, bir fark var. UIView.boundsgöre olan görünümü kendisi (ve dolayısıyla bounds.originda, başlangıçta sıfır olan) UIView.centerkoordinat sisteminde belirtilen Superview .
Hicazi

41

Başlamadan önce, başlangıç ​​noktasının CGPointbir görünümün Sol Üst köşesi olduğunu hatırlatalım . Görüşler ve ebeveynler hakkında anlaşılması gereken önemli bir şey.

Bu basit koda bir göz atalım, görünümüne siyah bir kare ekleyen bir görünüm denetleyicisi:

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

}

Bu, şu görünümü oluşturacaktır: siyah dikdörtgenin orijini ve merkezi, üst öğe ile aynı koordinatlara uyuyor

görüntü açıklamasını buraya girin

Şimdi, başka bir SubSubView subView eklemeyi ve subSubview ile aynı kaynağı vermeyi deneyelim, ancak subSubView'ı subView'in bir alt görünümü yapalım

Bu kodu ekleyeceğiz:

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

Ve sonuç bu:

görüntü açıklamasını buraya girin

Bu satır nedeniyle:

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

Mor dikdörtgenin orijininin ebeveyn (siyah dikdörtgen) ile aynı olmasını bekliyorsunuz, ancak onun altına giriyor ve bu neden? Çünkü başka bir görünüme bir görünüm eklediğinizde, alt Görünüm çerçevesi "dünya" artık ebeveyn BOUND RECTANGLE'tır, ana ekrandaki orijininin tüm alt görünümleri için koordinatlarda (15,15) olduğu görüşüne sahipseniz, sol üst köşe (0,0) olacaktır

Bu nedenle, bir ebeveyne her zaman alt görünümlerinin "dünyası" olan bağlı dikdörtgeniyle başvurmanız gerekir, bu satırı şu şekilde düzeltelim:

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

Ve sihri görün, alt görünüm artık tam olarak ana kaynağında bulunuyor:

görüntü açıklamasını buraya girin

Öyleyse, "Tamam, sadece ailemin görüşüne göre bakış açımı ortalamak istedim, sorun nedir?" pekala, önemli değil, sadece çerçevesinden alınan üst Merkez noktasını, bunu yaparak ebeveynin sınır merkezine "çevirmeniz" gerekir:

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

Aslında ona "ebeveynlerin merkezini al ve onu subSubView dünyasına dönüştür" diyorsun.

Ve bu sonucu alacaksınız:

görüntü açıklamasını buraya girin


'SubSubView.center = subView.convertPoint (subView.center, fromView: subSubView)' satırının nereye yerleştirileceği?
Thamarai T

26

Kullanmak istiyorum:

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

CGRectSeçenekleri kullanmayı seviyorum ...

SWIFT 3:

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

19

1. Otomatik düzenini etkinleştirdiyseniz:

  • İpucu: Bir görünümü başka bir görünümü otomatik düzen ile ortalamak için, en az bir ana görünümü paylaşan herhangi iki görünüm için aynı kodu kullanabilirsiniz.

Öncelikle çocuk görünümlerinin otomatik yeniden boyutlandırmasını devre dışı bırakın

UIView *view1, *view2;
[childview setTranslatesAutoresizingMaskIntoConstraints:NO];
  1. UIView + Autolayout veya Purelayout iseniz :

    [view1 autoAlignAxis:ALAxisHorizontal toSameAxisOfView:view2];
    [view1 autoAlignAxis:ALAxisVertical toSameAxisOfView:view2];
  2. Yalnızca UIKit düzeyinde otomatik düzen yöntemlerini kullanıyorsanız:

    [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. Otomatik düzen olmadan:

Tercih ederim:

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
Kabul edilen cevabın aksine, bu çözümün piksel sınırlarında temiz bir şekilde hizalanacağı ve belirli genişliklerde görünümün bulanıklığını önleyeceği unutulmamalıdır.
Brad Larson

1
Yanılmıyorsam, child.frame = CGRectIntegral (child.frame); BL'nin tanımladığı soruna şık bir tümünü yakalama / her yerde kullanma çözümüdür.
Şişko

1
@JoeBlow: Uyarılar için teşekkürler. Eskiden yuvarlamayı severdim ama blok stiliyle kullanımı daha şıkCGRectIntegral
Cemal Eker

Çerçeveyi ayarlamak için kullandığınız sözdizimini açıklar mısınız, daha önce görmedim. Her zaman mülke atanan "kapanış" daki son ifade midir? Ve Apple belgelerinde nerede bulabilirim?
Johannes

"Yalnızca UIKit düzeyinde otomatik düzen yöntemlerini kullanıyorsanız:" hatalara neden olur.
Jonny

13

En kolay yol:

child.center = parent.center

Demek istediğim, bunun nasıl çalıştığına dair daha fazla açıklama / açıklama eklemelisiniz.
Tushar

Bu türden birçok cevap aradım, bu basit cevap benim için hile yaptı. Teşekkürler.
gbossa

9

görüntü açıklamasını buraya girin

Bu otomatik yeniden boyutlandırma maskesini iç görünümünüze ayarlayın.


1
Otomatik düzen ile, otomatik boyutlandırma penceresi yoktur.
Allen

@Allen, otomatik yeniden boyutlandırmayı kullanmak istiyorsanız, otomatik düzeni devre dışı bırakmanız gerekir.
Mayank Jain

8

IOS9 ile layout çapa API'sini kullanabilirsiniz.

Kod şöyle görünecektir:

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

Bunun avantajı CGPointMakeya CGRectda bu yöntemlerle, görüşün merkezini sabit bir noktaya ayarlamanızdır, ancak bu teknikle, iki görünüm arasında, nasıl parentviewdeğişirse değişsin sonsuza kadar sürecek bir ilişki kuruyorsunuz.

Bunu yapmadan önce emin olun:

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

ve translatesAutoresizingMaskIntoConstraintsher görünümün değerini yanlış olarak ayarlamak için.

Bu, kilitlenmeyi ve Otomatik Yerleşimin karışmasını önleyecektir.


8

Kullanabilirsiniz

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

Ve Swift 3.0'da

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

1
İkinci kod örneği, hızlı 4. GREAT 👍🏻!
iGhost

EVET! Sonunda teşekkür ederim. MidX / midY olayını bilmiyordum. Mükemmel.
Dave Y

5

Görünüm ve alt görünümde aynı merkezi kullanmak, bunu yapmanın en basit yoludur. Bunun gibi bir şey yapabilirsin,

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

Bu, alt görünümü süper görünüm açısından ortalayacaktır. Yukarıdaki durumda, başlangıç ​​noktası (0, 0) olduğu için çalışıyor.
Abdurrahman Mubeen Ali

3

PureLayout kullanarak başka bir çözüm autoCenterInSuperview.

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

[outerview addSubview:innerView];

[innerView autoCenterInSuperview];

Görünüşü bu:

PureLayout ile Merkez


2

C # veya Xamarin.ios'ta bu şekilde kullanabiliriz

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


1

Kullanmak istiyorum:

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

Bu basit, kısa ve tatlı. @ Hejazi'nin yukarıdaki cevabını kullanırsanız ve alt parent.centergörünümünüz dışında herhangi bir şeye ayarlanmışsa (0,0)ortalanmaz!


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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.