14
votes

I'm developing a program in which I am programmatically adding an NSImageView to a custom NSView class. While creating the image-view, I am passing the frame of the parent container.

-(NSImageView *)loadNSImage:(NSString *)imageName frame:(NSRect)frame{
    imageName = [[NSBundle mainBundle] pathForResource:imageName ofType:@"png"];
    NSImage *image = [[NSImage alloc] initWithContentsOfFile:imageName]; 
    NSImageView *imageView = [[NSImageView alloc]initWithFrame:frame];
    [imageView setImage:image];
    [imageView setImageScaling:NSImageScaleProportionallyUpOrDown];
    [imageView setAutoresizingMask:NSViewHeightSizable | NSViewWidthSizable | NSViewMaxXMargin | NSViewMaxYMargin | NSViewMinXMargin | NSViewMinYMargin];
    [imageView setImageAlignment:NSImageAlignCenter];
    [image release];
    return imageView;
}

Then I am using the addSubView method to add this into the Custom View. The problem is that the image sticks to the bottom-left of the parent view. How can I place this image in the center of the parent view?

I have tried adding an offset to the frame origin, but that doesn't really work when the window is resized, or if an image with a different size is loaded.

Any help would be appreciated.

4

4 Answers

41
votes

I'm not sure if this is the best way to do it, but I just do simple math when I want to center a subview inside its parent.

You need to set all the margins to be auto-resizable if you want it to stay centered.

[subview setFrameOrigin:NSMakePoint(
  round((NSWidth([parentView bounds]) - NSWidth([subview frame])) / 2),
  round((NSHeight([parentView bounds]) - NSHeight([subview frame])) / 2)
)];
[subview setAutoresizingMask:NSViewMinXMargin | NSViewMaxXMargin | NSViewMinYMargin | NSViewMaxYMargin];

This is just calculating the margins required to get a centered origin.

If you need the centered frame before you invoke initWithFrame: then just use the above logic to compute the frame origin values.

2
votes

Swift 5 @d11wtq's answer

    let x = (parentView.bounds.width - subviewWidth) * 0.5
    let y = (parentView.bounds.height - subviewHeight) * 0.5
    let f = CGRect(x: x, y: y, width: subviewWidth, height: subviewHeight)
    let subview = NSView(frame: f)
    subview.autoresizingMask = [.minXMargin, .maxXMargin, .minYMargin, .maxYMargin ]
0
votes

Objective - C in macOS Catalina , Version 10.15.3

more readable @d11wtq's answer

    CGFloat x = (NSWidth(parentView.bounds) - subviewWidth) * 0.5;
    CGFloat y = (NSHeight(parentView.bounds) - subviewHeight) * 0.5;
    CGRect f = CGRectMake(x, y, subviewWidth, subviewHeight);
    subview = [[NSView alloc] initWithFrame: f];

    subview.autoresizingMask = NSViewMinXMargin | NSViewMaxXMargin | NSViewMinYMargin | NSViewMaxYMargin;
-4
votes

Try This. in .h

@property (strong, nonatomic) IBOutlet UIView *CoinsPurchaseView;

in .m

self.CoinsPurchaseView.center = self.view.center;
    [self.view addSubview:self.CoinsPurchaseView];