Repeating background image in an NSView

2019-03-09 18:21发布

I am trying to draw a repeating background image in my NSView, I have this till now:

// INIT
- (id)initWithFrame:(NSRect)frame {
  if (self = [super initWithFrame:frame]) {
    self.backgroundImage = [NSImage imageNamed:@"progressBackground.pdf"];
  }

  return self;
}

// DRAW
- (void)drawRect:(NSRect)dirtyRect {
  // Draw the background
  [backgroundImage drawInRect:[self bounds]
                     fromRect:NSMakeRect(0.0f, 0.0f, backgroundImage.size.width, backgroundImage.size.height)
                    operation:NSCompositeSourceAtop
                     fraction:1.0f];
  NSLog(@"%dx%d", backgroundImage.size.width, backgroundImage.size.height);
}

However, the view stretches the image to fill itself. I want the image to repeat instead.

alt text (the black strokes are fixed already)

Also, something strange happens, as the console says the size of the image equals -2109897792x0, but the image really is 32x32! WTF?!

Could someone help me, please? Thanks.

3条回答
叼着烟拽天下
2楼-- · 2019-03-09 18:38

You can create a pattern color with +[NSColor colorWithPatternImage:] and then just fill the background rectangle with that "color". That should do what you want to accomplish.

查看更多
Melony?
3楼-- · 2019-03-09 18:39

Check out RMSkinnedViewon Github!

EDIT: RMSkinnedView is a NSView subclass where you can set up several options, including rounded corners, background color, background image pattern, etc., directly via the User Defined Runtime Attributes in the Interface Builder.

查看更多
姐就是有狂的资本
4楼-- · 2019-03-09 18:57

I found the answer here to prevent patterns from drawing from the bottom and giving that weird effect when windows resize:

http://www.mere-mortal-software.com/blog/details.php?d=2007-01-08

Basically all you need to do in your drawRect is to save your graphics context state, call the method, paint your pattern, then restore your state.

The method is:

- (void)drawRect:(NSRect)dirtyRect {
    NSGraphicsContext* theContext = [NSGraphicsContext currentContext];
    [theContext saveGraphicsState];
    [[NSGraphicsContext currentContext] setPatternPhase:NSMakePoint(0,[self frame].size.height)];
    [self.customBackgroundColour set];
    NSRectFill([self bounds]);
    [theContext restoreGraphicsState]; 
}

I initialized my background color pattern in the init method:

- (id)initWithFrame:(NSRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.customBackgroundColour = [NSColor colorWithPatternImage:[NSImage imageNamed:@"light-linen-texture.png"]];
    }

    return self;
}
查看更多
登录 后发表回答