mac 自定义titlebar

本文介绍如何在Mac应用中自定义Titlebar,使用图片作为背景并实现特定区域保护的拉伸效果。通过创建自定义视图及窗口控制器,调整Storyboard配置,实现透明Titlebar和图片背景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

mac 自定义titlebar,背景为图片,并且图片拉伸做了保护区域
这里写图片描述

首先随便在storyboard中拖到viewController中一个contentview。然后创建一个继承自NSView的CustomView,修改刚拖进去控件测class为CustomView。
这里写图片描述
然后把刚才拖的控件往viewController中拖线
并且做相对设置

#import "ViewController.h"
#import "CustomView.h"
@interface ViewController ()
@property (weak) IBOutlet CustomView *fakeTitlebar;
@end
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // Do any additional setup after loading the view.

    self.fakeTitlebar.translatesAutoresizingMaskIntoConstraints = NO;

    [self.fakeTitlebar.topAnchor constraintEqualToAnchor:self.view.topAnchor].active = YES;

    [self.fakeTitlebar.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor].active = YES;

    [self.fakeTitlebar.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor].active = YES;

    [self.fakeTitlebar.heightAnchor constraintEqualToConstant:60].active = YES;

}

然后再对创建一个NSWindowController(CustomWindowController),让storyboard的window的class集成自CustomWindowController。
在CustomWindowController里面添加修改titlebar代码

#import "CustomWindowController.h"

@interface CustomWindowController ()

@end

@implementation CustomWindowController

- (void)windowDidLoad {
     [super windowDidLoad];
     self.window.titlebarAppearsTransparent  = YES;
     self.window.movableByWindowBackground = YES;
     self.window.titleVisibility = NSWindowTitleHidden;
     [self.window setStyleMask:[self.window styleMask] | NSWindowStyleMaskFullSizeContentView];

}

做到这里就剩下设置customview了

#import "CustomView.h"
#import "NSImage+Extension.h"
@implementation CustomView

- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];

    // Drawing code here.
    self.wantsLayer = YES;
    NSImage *image = [NSImage imageNamed:@"1111"];
    NSImage *image1 = [image stretchableImageWithLeftCapWidth:300 middleWidth:dirtyRect.size.width rightCapWidth:25];
    [ [NSColor colorWithPatternImage:image1] set];
    NSRectFill(dirtyRect);
}

其中做了一个NSIamge的类扩展用来做拉伸图片保护的。
下面是NSImage类扩展内容

#import <Cocoa/Cocoa.h>

@interface NSImage (Extension)

//保持四周一定区域像素不拉伸,将图像扩散到一定的大小
- (NSImage *)stretchableImageWithSize:(NSSize)size edgeInsets:(NSEdgeInsets)insets;
//保持leftWidth,rightWidth这左右一定区域不拉伸,将图片宽度拉伸到(leftWidth+middleWidth+rightWidth)
- (NSImage *)stretchableImageWithLeftCapWidth:(float)leftWidth middleWidth:(float)middleWidth rightCapWidth:(float)rightWidth;

@end
#import "NSImage+Extension.h"

@implementation NSImage (Extension)

- (NSImage *)stretchableImageWithSize:(NSSize)size edgeInsets:(NSEdgeInsets)insets
{
    void (^makeAreas)(NSRect, NSRect *, NSRect *, NSRect *, NSRect *, NSRect *, NSRect *, NSRect *, NSRect *, NSRect *) = ^(NSRect srcRect, NSRect *tl, NSRect *tc, NSRect *tr, NSRect *ml, NSRect *mc, NSRect *mr, NSRect *bl, NSRect *bc, NSRect *br) {
        CGFloat w = NSWidth(srcRect);
        CGFloat h = NSHeight(srcRect);
        CGFloat cw = w - insets.left - insets.right;
        CGFloat ch = h - insets.top - insets.bottom;

        CGFloat x0 = NSMinX(srcRect);
        CGFloat x1 = x0 + insets.left;
        CGFloat x2 = NSMaxX(srcRect) - insets.right;

        CGFloat y0 = NSMinY(srcRect);
        CGFloat y1 = y0 + insets.bottom;
        CGFloat y2 = NSMaxY(srcRect) - insets.top;

        *tl = NSMakeRect(x0, y2, insets.left, insets.top);
        *tc = NSMakeRect(x1, y2, cw, insets.top);
        *tr = NSMakeRect(x2, y2, insets.right, insets.top);

        *ml = NSMakeRect(x0, y1, insets.left, ch);
        *mc = NSMakeRect(x1, y1, cw, ch);
        *mr = NSMakeRect(x2, y1, insets.right, ch);

        *bl = NSMakeRect(x0, y0, insets.left, insets.bottom);
        *bc = NSMakeRect(x1, y0, cw, insets.bottom);
        *br = NSMakeRect(x2, y0, insets.right, insets.bottom);
    };

    NSRect rect = NSMakeRect(0, 0, size.width, size.height);

    // Source rects
    NSRect srcRect = (NSRect){NSZeroPoint, self.size};
    NSRect srcTopL, srcTopC, srcTopR, srcMidL, srcMidC, srcMidR, srcBotL, srcBotC, srcBotR;
    makeAreas(srcRect, &srcTopL, &srcTopC, &srcTopR, &srcMidL, &srcMidC, &srcMidR, &srcBotL, &srcBotC, &srcBotR);

    // Destinations rects
    NSRect dstTopL, dstTopC, dstTopR, dstMidL, dstMidC, dstMidR, dstBotL, dstBotC, dstBotR;
    makeAreas(rect, &dstTopL, &dstTopC, &dstTopR, &dstMidL, &dstMidC, &dstMidR, &dstBotL, &dstBotC, &dstBotR);

    NSRect srcRects[] = {srcTopL, srcTopC, srcTopR, srcMidL, srcMidC, srcMidR, srcBotL, srcBotC, srcBotR};
    NSRect dstRects[] = {dstTopL, dstTopC, dstTopR, dstMidL, dstMidC, dstMidR, dstBotL, dstBotC, dstBotR};
    NSMutableArray *partImgs = [NSMutableArray arrayWithCapacity:9];
    for (int i=0;i<9;i++)
    {
        NSRect aSrcRect = srcRects[i];
        NSRect aDstRect = dstRects[i];

        NSImage *partImg = [[NSImage alloc] initWithSize:aSrcRect.size];
        [partImg lockFocus];
        [self drawAtPoint:NSZeroPoint fromRect:aSrcRect operation:NSCompositeCopy fraction:1.0];
        [partImg setSize:aDstRect.size];
        [partImg unlockFocus];
        [partImgs addObject:partImg];
    }

    // Draw
    NSImage *resultImg = [[NSImage alloc] initWithSize:rect.size];
    [resultImg lockFocus];
    NSDrawNinePartImage(rect,
                        [partImgs objectAtIndex:0],
                        [partImgs objectAtIndex:1],
                        [partImgs objectAtIndex:2],
                        [partImgs objectAtIndex:3],
                        [partImgs objectAtIndex:4],
                        [partImgs objectAtIndex:5],
                        [partImgs objectAtIndex:6],
                        [partImgs objectAtIndex:7],
                        [partImgs objectAtIndex:8],
                        NSCompositeSourceOver, 1, NO);
    [resultImg unlockFocus];
    return resultImg;
}

- (NSImage *)stretchableImageWithLeftCapWidth:(float)leftWidth middleWidth:(float)middleWidth rightCapWidth:(float)rightWidth
{
    // Calculate the new images dimensions
    float imageWidth = leftWidth + middleWidth + rightWidth;
    float imageHeight = self.size.height;

    // Generate the left image
    NSRect rectLeft = NSMakeRect(0, 0, leftWidth, imageHeight);
    NSImage *imageLeft = [[NSImage alloc] initWithSize:rectLeft.size];
    if (imageLeft.size.width > 0) {
        [imageLeft lockFocus];
        [self drawInRect:rectLeft fromRect:rectLeft operation:NSCompositeCopy fraction:1.0];
        [imageLeft unlockFocus];
    }

    // Generate the middle image
    NSRect rectMiddle = NSMakeRect(0, 0, middleWidth, imageHeight);
    NSImage *imageMiddle = [[NSImage alloc] initWithSize:rectMiddle.size];
    if (imageMiddle.size.width > 0) {
        [imageMiddle lockFocus];
        [self drawInRect:rectMiddle fromRect:NSMakeRect(leftWidth, 0, self.size.width-rightWidth-leftWidth,imageHeight) operation:NSCompositeCopy fraction:1.0];
        [imageMiddle unlockFocus];
    }

    // Generate the right image
    NSRect rectRight = NSMakeRect(0, 0, rightWidth, imageHeight);
    NSImage *imageRight = [[NSImage alloc] initWithSize:rectRight.size];
    if (imageRight.size.width > 0) {
        [imageRight lockFocus];
        [self drawInRect:rectRight fromRect:NSMakeRect(self.size.width - rightWidth, 0, rightWidth, imageHeight) operation:NSCompositeCopy fraction:1.0];
        [imageRight unlockFocus];
    }

    // Combine the images
    NSImage *newImage = [[NSImage alloc] initWithSize:NSMakeSize(imageWidth,  imageHeight)];
    if (newImage.size.width > 0) {
        [newImage lockFocus];
        NSDrawThreePartImage(NSMakeRect(0, 0, imageWidth, imageHeight), imageLeft, imageMiddle, imageRight, NO, NSCompositeSourceOver, 1, NO);
        [newImage unlockFocus];
    }

    // Release the images and return the new image
    return newImage;
}

@end

这样添加完成之后应该就可以显示图片上的效果了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值