Mac開發基礎05-NSView(一)
NSView 概述
NSView 是 macOS 應用中所有用戶界面元素的基類。它提供了一系列功能用于視圖的繪制、事件處理、動畫、自動布局等。
1. 基本屬性
bounds 和 frame
bounds 描述了視圖自身坐標系中的矩形區域,而 frame 描述了視圖在其父視圖坐標系中的矩形區域。
Objective-C
NSView *view = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 200, 200)];
NSLog(@"Bounds: %@", NSStringFromRect(view.bounds)); // Bounds: (0.0, 0.0, 200.0, 200.0)
NSLog(@"Frame: %@", NSStringFromRect(view.frame)); // Frame: (0.0, 0.0, 200.0, 200.0)
Swift
let view = NSView(frame: NSRect(x: 0, y: 0, width: 200, height: 200))
print("Bounds: \(view.bounds)") // Bounds: (0.0, 0.0, 200.0, 200.0)
print("Frame: \(view.frame)") // Frame: (0.0, 0.0, 200.0, 200.0)
alphaValue
用于設置視圖的透明度。
Objective-C
view.alphaValue = 0.5; // 設置透明度為50%
Swift
view.alphaValue = 0.5 // 設置透明度為50%
hidden
用于控制視圖的可見性。
Objective-C
view.hidden = YES; // 隱藏視圖
Swift
view.isHidden = true // 隱藏視圖
backgroundColor
NSView 本身沒有 backgroundColor 屬性,但可以通過 wantsLayer 屬性和 CALayer 支持來實現背景顏色。
Objective-C
[view setWantsLayer:YES];
view.layer.backgroundColor = [[NSColor blueColor] CGColor];
Swift
view.wantsLayer = true
view.layer?.backgroundColor = NSColor.blue.cgColor
2. 圖層和動畫
wantsLayer
啟用 Core Animation 支持,通過設置 wantsLayer 為 true 或 YES 為視圖創建一個 CALayer。
Objective-C
view.wantsLayer = YES;
Swift
view.wantsLayer = true
隱式動畫
可以通過 Core Animation 隱式動畫來實現屬性變化的平滑過渡。
Objective-C
[CATransaction begin];
[CATransaction setAnimationDuration:1.0];
view.layer.backgroundColor = [[NSColor greenColor] CGColor];
[CATransaction commit];
Swift
CATransaction.begin()
CATransaction.setAnimationDuration(1.0)
view.layer?.backgroundColor = NSColor.green.cgColor
CATransaction.commit()
3. 事件處理
鼠標事件
重寫相關方法來處理鼠標交互。
Objective-C
- (void)mouseDown:(NSEvent *)event {
NSLog(@"Mouse down at location: %@", NSStringFromPoint(event.locationInWindow));
}
- (void)mouseDragged:(NSEvent *)event {
NSLog(@"Mouse dragged");
}
- (void)mouseUp:(NSEvent *)event {
NSLog(@"Mouse up");
}
Swift
override func mouseDown(with event: NSEvent) {
print("Mouse down at location: \(event.locationInWindow)")
}
override func mouseDragged(with event: NSEvent) {
print("Mouse dragged")
}
override func mouseUp(with event: NSEvent) {
print("Mouse up")
}
鍵盤事件
視圖需要先成為 "First Responder",才能處理鍵盤事件。
Objective-C
- (BOOL)acceptsFirstResponder {
return YES;
}
- (void)keyDown:(NSEvent *)event {
NSLog(@"Key down: %hu", event.keyCode);
}
- (void)keyUp:(NSEvent *)event {
NSLog(@"Key up: %hu", event.keyCode);
}
Swift
override var acceptsFirstResponder: Bool {
return true
}
override func keyDown(with event: NSEvent) {
print("Key down: \(event.keyCode)")
}
override func keyUp(with event: NSEvent) {
print("Key up: \(event.keyCode)")
}
4. 自動布局和約束
自動布局
通過 NSLayoutConstraint 來管理視圖之間的布局關系。
Objective-C
NSView *subview = [[NSView alloc] init];
[subview setTranslatesAutoresizingMaskIntoConstraints:NO];
[view addSubview:subview];
[NSLayoutConstraint activateConstraints:@[
[subview.topAnchor constraintEqualToAnchor:view.topAnchor constant:10],
[subview.leadingAnchor constraintEqualToAnchor:view.leadingAnchor constant:10],
[subview.widthAnchor constraintEqualToConstant:100],
[subview.heightAnchor constraintEqualToConstant:100]
]];
Swift
let subview = NSView()
subview.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(subview)
NSLayoutConstraint.activate([
subview.topAnchor.constraint(equalTo: view.topAnchor, constant: 10),
subview.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10),
subview.widthAnchor.constraint(equalToConstant: 100),
subview.heightAnchor.constraint(equalToConstant: 100)
])
5. 繪制內容
重寫 draw(_:)
通過重寫 draw(_:) 來自定義視圖的繪制內容。
Objective-C
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
// 自定義繪制代碼
CGContextRef context = [[NSGraphicsContext currentContext] CGContext];
CGContextSetFillColorWithColor(context, [[NSColor redColor] CGColor]);
CGContextFillRect(context, dirtyRect);
}
Swift
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
// 自定義繪制代碼
if let context = NSGraphicsContext.current?.cgContext {
context.setFillColor(NSColor.red.cgColor)
context.fill(dirtyRect)
}
}
6. 子視圖管理
添加、移除和替換子視圖
Objective-C
// 添加子視圖
NSView *subview = [[NSView alloc] initWithFrame:NSMakeRect(50, 50, 100, 100)];
[subview setWantsLayer:YES];
subview.layer.backgroundColor = [[NSColor greenColor] CGColor];
[view addSubview:subview positioned:NSWindowAbove relativeTo:nil];
// 移除子視圖
[subview removeFromSuperview];
// 替換子視圖
NSView *newSubview = [[NSView alloc] initWithFrame:NSMakeRect(50, 50, 100, 100)];
[view replaceSubview:subview with:newSubview];
Swift
// 添加子視圖
let subview = NSView(frame: NSRect(x: 50, y: 50, width: 100, height: 100))
subview.wantsLayer = true
subview.layer?.backgroundColor = NSColor.green.cgColor
view.addSubview(subview, positioned: .above, relativeTo: nil)
// 移除子視圖
subview.removeFromSuperview()
// 替換子視圖
let newSubview = NSView(frame: NSRect(x: 50, y: 50, width: 100, height: 100))
view.replaceSubview(subview, with: newSubview)
7. 坐標轉換
轉換坐標系中的點
Objective-C
NSPoint pointInWindow = NSMakePoint(10, 10);
NSPoint pointInSubview = [view convertPoint:pointInWindow toView:subview];
NSLog(@"Point in subview: %@", NSStringFromPoint(pointInSubview));
Swift
let pointInWindow = NSMakePoint(10, 10)
let pointInSubview = view.convert(pointInWindow, to: subview)
print("Point in subview: \(pointInSubview)")
將來的你會感謝今天如此努力的你!
版權聲明:本文為博主原創文章,未經博主允許不得轉載。

浙公網安備 33010602011771號