首页 > 其他分享 >Mac开发基础21-NSSplitView

Mac开发基础21-NSSplitView

时间:2024-08-06 17:54:30浏览次数:7  
标签:rightView splitView 21 leftView NSView 视图 NSSplitView Mac

NSSplitView 是 macOS 应用中的一个重要控件,允许用户调整窗口中的各个子视图大小。它通常用于创建可调整大小的面板布局,例如侧边栏和主内容区域。在本指南中,我们将详细介绍 NSSplitView 的常见 API 和基础技巧,并深入探讨相关知识。

基本使用

创建和初始化

Objective-C

#import <Cocoa/Cocoa.h>

// 创建一个 NSSplitView 实例
NSSplitView *splitView = [[NSSplitView alloc] initWithFrame:NSMakeRect(0, 0, 600, 400)];

// 设置 SplitView 为垂直分隔
[splitView setVertical:YES];

// 添加分配两边的子视图
NSView *leftView = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 300, 400)];
[leftView setWantsLayer:YES]; // 启用 layer 支持(用于视图的主要特性设置)
[leftView.layer setBackgroundColor:[NSColor lightGrayColor].CGColor]; // 设置背景颜色

NSView *rightView = [[NSView alloc] initWithFrame:NSMakeRect(300, 0, 300, 400)];
[rightView setWantsLayer:YES]; // 启用 layer 支持
[rightView.layer setBackgroundColor:[NSColor blueColor].CGColor]; // 设置背景颜色

// 将子视图添加到 SplitView
[splitView addSubview:leftView];
[splitView addSubview:rightView];

Swift

import Cocoa

// 创建一个 NSSplitView 实例
let splitView = NSSplitView(frame: NSRect(x: 0, y: 0, width: 600, height: 400))

// 设置 SplitView 为垂直分隔
splitView.isVertical = true

// 添加分配两边的子视图
let leftView = NSView(frame: NSRect(x: 0, y: 0, width: 300, height: 400))
leftView.wantsLayer = true // 启用 layer 支持(用于视图的主要特性设置)
leftView.layer?.backgroundColor = NSColor.lightGray.cgColor // 设置背景颜色

let rightView = NSView(frame: NSRect(x: 300, y: 0, width: 300, height: 400))
rightView.wantsLayer = true // 启用 layer 支持
rightView.layer?.backgroundColor = NSColor.blue.cgColor // 设置背景颜色

// 将子视图添加到 SplitView
splitView.addSubview(leftView)
splitView.addSubview(rightView)

数据源和委托

使用 NSSplitView 时通常需要设置代理以处理各种事件。

Objective-C

// 设置代理
[splitView setDelegate:self];
// 实现代理方法,控制分隔条的位置和行为
- (CGFloat)splitView:(NSSplitView *)splitView constrainMinCoordinate:(CGFloat)proposedMinimumPosition ofSubviewAt:(NSInteger)dividerIndex {
    return proposedMinimumPosition + 50; // 最小分隔条位置
}

- (CGFloat)splitView:(NSSplitView *)splitView constrainMaxCoordinate:(CGFloat)proposedMaximumPosition ofSubviewAt:(NSInteger)dividerIndex {
    return proposedMaximumPosition - 50; // 最大分隔条位置
}

- (BOOL)splitView:(NSSplitView *)splitView shouldAdjustSizeOfSubview:(NSView *)view {
    return YES; // 控制是否允许调整子视图大小
}

Swift

// 设置代理
splitView.delegate = self
// 实现代理方法,控制分隔条的位置和行为
func splitView(_ splitView: NSSplitView, constrainMinCoordinate proposedMinimumPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat {
    return proposedMinimumPosition + 50  // 最小分隔条位置
}

func splitView(_ splitView: NSSplitView, constrainMaxCoordinate proposedMaximumPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat {
    return proposedMaximumPosition - 50  // 最大分隔条位置
}

func splitView(_ splitView: NSSplitView, shouldAdjustSizeOfSubview view: NSView) -> Bool {
    return true  // 控制是否允许调整子视图大小
}

使用自动布局

NSSplitView 支持自动布局,这使得调整窗口大小时能更好地适应变化。

Objective-C

// 使用自动布局进行初始化
NSView *leftView = [[NSView alloc] init];
NSView *rightView = [[NSView alloc] init];

[leftView setTranslatesAutoresizingMaskIntoConstraints:NO]; // 禁用自动转换约束
[rightView setTranslatesAutoresizingMaskIntoConstraints:NO];

[splitView addSubview:leftView];
[splitView addSubview:rightView];

// 添加约束
[NSLayoutConstraint activateConstraints:@[
    [leftView.leadingAnchor constraintEqualToAnchor:splitView.leadingAnchor],
    [leftView.topAnchor constraintEqualToAnchor:splitView.topAnchor],
    [leftView.bottomAnchor constraintEqualToAnchor:splitView.bottomAnchor],
    [leftView.widthAnchor constraintEqualToAnchor:splitView.widthAnchor multiplier:0.5],
    
    [rightView.trailingAnchor constraintEqualToAnchor:splitView.trailingAnchor],
    [rightView.topAnchor constraintEqualToAnchor:splitView.topAnchor],
    [rightView.bottomAnchor constraintEqualToAnchor:splitView.bottomAnchor],
    [rightView.widthAnchor constraintEqualToAnchor:splitView.widthAnchor multiplier:0.5],
]];

Swift

// 使用自动布局进行初始化
let leftView = NSView()
let rightView = NSView()

leftView.translatesAutoresizingMaskIntoConstraints = false // 禁用自动转换约束
rightView.translatesAutoresizingMaskIntoConstraints = false

splitView.addSubview(leftView)
splitView.addSubview(rightView)

// 添加约束
NSLayoutConstraint.activate([
    leftView.leadingAnchor.constraint(equalTo: splitView.leadingAnchor),
    leftView.topAnchor.constraint(equalTo: splitView.topAnchor),
    leftView.bottomAnchor.constraint(equalTo: splitView.bottomAnchor),
    leftView.widthAnchor.constraint(equalTo: splitView.widthAnchor, multiplier: 0.5),
    
    rightView.trailingAnchor.constraint(equalTo: splitView.trailingAnchor),
    rightView.topAnchor.constraint(equalTo: splitView.topAnchor),
    rightView.bottomAnchor.constraint(equalTo: splitView.bottomAnchor),
    rightView.widthAnchor.constraint(equalTo: splitView.widthAnchor, multiplier: 0.5),
])

高级用法

动态增减子视图

Objective-C

添加子视图

NSView *newView = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 300, 400)];
[newView setWantsLayer:YES];
[newView.layer setBackgroundColor:[NSColor greenColor].CGColor];

// 动态添加到 SplitView
[splitView addSubview:newView positioned:NSWindowAbove relativeTo:nil];
[splitView adjustSubviews]; // 调整子视图

移除子视图

NSView *viewToRemove = [splitView.subviews lastObject];
[splitView removeArrangedSubview:viewToRemove];
[viewToRemove removeFromSuperview];
[splitView adjustSubviews]; // 调整子视图

Swift

添加子视图

let newView = NSView(frame: NSRect(x: 0, y: 0, width: 300, height: 400))
newView.wantsLayer = true
newView.layer?.backgroundColor = NSColor.green.cgColor

// 动态添加到 SplitView
splitView.addSubview(newView, positioned: .above, relativeTo: nil)
splitView.adjustSubviews() // 调整子视图

移除子视图

if let viewToRemove = splitView.subviews.last {
    splitView.removeArrangedSubview(viewToRemove)
    viewToRemove.removeFromSuperview()
    splitView.adjustSubviews() // 调整子视图
}

自定义分隔条

Objective-C

创建自定义分隔条视图:

@interface CustomDividerView : NSView
@end

@implementation CustomDividerView
- (instancetype)initWithFrame:(NSRect)frameRect {
    self = [super initWithFrame:frameRect];
    if (self) {
        self.wantsLayer = YES;
        self.layer.backgroundColor = [NSColor darkGrayColor].CGColor;
    }
    return self;
}
@end

NSSplitView 代理方法中使用自定义分隔条:

- (NSView *)splitView:(NSSplitView *)splitView additionalEffectiveRectOfDividerAtIndex:(NSInteger)dividerIndex {
    NSView *dividerView = [[CustomDividerView alloc] initWithFrame:NSMakeRect(0, 0, splitView.dividerThickness, 100)];
    [splitView addSubview:dividerView];
    return dividerView;
}

Swift

创建自定义分隔条视图:

class CustomDividerView: NSView {
    override init(frame frameRect: NSRect) {
        super.init(frame: frameRect)
        self.wantsLayer = true
        self.layer?.backgroundColor = NSColor.darkGray.cgColor
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

NSSplitView 代理方法中使用自定义分隔条:

func splitView(_ splitView: NSSplitView, additionalEffectiveRectOfDividerAt dividerIndex: Int) -> NSRect {
    let dividerView = CustomDividerView(frame: NSRect(x: 0, y: 0, width: splitView.dividerThickness, height: 100))
    splitView.addSubview(dividerView)
    return dividerView.frame
}

用于实际应用

示例代码

Objective-C

#import <Cocoa/Cocoa.h>
#import "CustomDividerView.h"

@interface AppDelegate : NSObject <NSApplicationDelegate, NSSplitViewDelegate>

@property (strong) NSWindow *window;
@property (strong) NSSplitView *splitView;

@end

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    _window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 800, 600)
                                            styleMask:(NSWindowStyleMaskTitled |
                                                      NSWindowStyleMaskClosable |
                                                      NSWindowStyleMaskResizable)
                                              backing:NSBackingStoreBuffered
                                                defer:NO];
    [_window setTitle:@"NSSplitView Example"];
    
    _splitView = [[NSSplitView alloc] initWithFrame:_window.contentView.bounds];
    [_splitView setVertical:YES];
    [_splitView setDelegate:self];
    
    NSView *leftView = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 300, 600)];
    [leftView setWantsLayer:YES];
    [leftView.layer setBackgroundColor:[NSColor lightGrayColor].CGColor];
    
    NSView *rightView = [[NSView alloc] initWithFrame:NSMakeRect(300, 0, 500, 600)];
    [rightView setWantsLayer:YES];
    [rightView.layer setBackgroundColor:[NSColor blueColor].CGColor];
    
    [_splitView addSubview:leftView];
    [_splitView addSubview:rightView];
    
    [_window.contentView addSubview:_splitView];
    [_window makeKeyAndOrderFront:nil];
}

// NSSplitViewDelegate 方法实现
- (CGFloat)splitView:(NSSplitView *)splitView constrainMinCoordinate:(CGFloat)proposedMinimumPosition ofSubviewAt:(NSInteger)dividerIndex {
    return proposedMinimumPosition + 100;
}

- (CGFloat)splitView:(NSSplitView *)splitView constrainMaxCoordinate:(CGFloat)proposedMaximumPosition ofSubviewAt:(NSInteger)dividerIndex {
    return proposedMaximumPosition - 100;
}

- (BOOL)splitView:(NSSplitView *)splitView shouldAdjustSizeOfSubview:(NSView *)view {
    return YES;
}

- (NSView *)splitView:(NSSplitView *)splitView additionalEffectiveRectOfDividerAtIndex:(NSInteger)dividerIndex {
    NSView *dividerView = [[CustomDividerView alloc] initWithFrame:NSMakeRect(0, 0, splitView.dividerThickness, 600)];
    [splitView addSubview:dividerView];
    return dividerView;
}

@end

int main(int argc, const char * argv[]) {
    return NSApplicationMain(argc, argv);
}

Swift

import Cocoa

@main
class AppDelegate: NSObject, NSApplicationDelegate, NSSplitViewDelegate {

    var window: NSWindow!
    var splitView: NSSplitView!

    func applicationDidFinishLaunching(_ aNotification: Notification) {
        window = NSWindow(contentRect: NSMakeRect(0, 0, 800, 600),
                          styleMask: [.titled, .closable, .resizable],
                          backing: .buffered,
                          defer: false)
        window.title = "NSSplitView Example"
        
        splitView = NSSplitView(frame: window.contentView!.bounds)
        splitView.isVertical = true
        splitView.delegate = self
        
        let leftView = NSView(frame: NSMakeRect(0, 0, 300, 600))
        leftView.wantsLayer = true
        leftView.layer?.backgroundColor = NSColor.lightGray.cgColor
        
        let rightView = NSView(frame: NSMakeRect(300, 0, 500, 600))
        rightView.wantsLayer = true
        rightView.layer?.backgroundColor = NSColor.blue.cgColor
        
        splitView.addSubview(leftView)
        splitView.addSubview(rightView)
        
        window.contentView?.addSubview(splitView)
        window.makeKeyAndOrderFront(nil)
    }

    // NSSplitViewDelegate 方法实现
    func splitView(_ splitView: NSSplitView, constrainMinCoordinate proposedMinimumPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat {
        return proposedMinimumPosition + 100
    }

    func splitView(_ splitView: NSSplitView, constrainMaxCoordinate proposedMaximumPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat {
        return proposedMaximumPosition - 100
    }

    func splitView(_ splitView: NSSplitView, shouldAdjustSizeOfSubview view: NSView) -> Bool {
        return true
    }

    func splitView(_ splitView: NSSplitView, additionalEffectiveRectOfDividerAt dividerIndex: Int) -> NSRect {
        let dividerView = CustomDividerView(frame: NSRect(x: 0, y: 0, width: splitView.dividerThickness, height: 600))
        splitView.addSubview(dividerView)
        return dividerView.frame
    }

}

class CustomDividerView: NSView {
    override init(frame frameRect: NSRect) {
        super.init(frame: frameRect)
        wantsLayer = true
        layer?.backgroundColor = NSColor.darkGray.cgColor
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

总结

通过了解 NSSplitView 的基本使用、委托方法、动态增减子视图、自定义分隔条等高级用法,你将能够更有效地使用 NSSplitView 创建可调整大小的复杂布局。在实际应用中,合理使用这些技巧可以显著提升用户界面的灵活性和用户体验。

标签:rightView,splitView,21,leftView,NSView,视图,NSSplitView,Mac
From: https://www.cnblogs.com/chglog/p/18345737

相关文章

  • Mac开发基础20-NSCollectionView
    NSCollectionView是macOS开发中的一种强大控件,类似于iOS上的UICollectionView,用于展示和管理网格、列表等多种布局的数据展示视图。1.基本使用创建和初始化Objective-C#import<Cocoa/Cocoa.h>//创建并初始化一个NSCollectionView实例NSCollectionView*collecti......
  • Mac开发基础19-NSTableView(二)
    进阶使用和技巧1.单击和双击行事件处理Objective-C//单击行时的处理-(void)tableView:(NSTableView*)tableViewdidClickTableColumn:(NSTableColumn*)tableColumn{NSIntegerclickedRow=[tableViewclickedRow];if(clickedRow>=0){NSLog(@"Si......
  • Mac开发基础18-NSTableView(一)
    NSTableView是macOS应用程序中用于显示和管理数据表格的控件。它提供了丰富的API和高度自定义的能力,使得开发者可以精细地控制表格的显示和行为。本文将详细介绍NSTableView的常见API和一些基础技巧,并深入探讨其相关知识。1.基本使用创建和初始化Objective-C#import......
  • LlamaCoder:一款开源的平替 Claude Artifacts 项目
    LlamaCoder是一个开源项目,旨在提供一种替代ClaudeArtifacts的解决方案。ClaudeArtifacts是一个商业软件,可能包含一些专有技术或特定的功能集,而LlamaCoder则致力于提供类似的功能,但以开源的形式,允许更广泛的社区参与和贡献。由于LlamaCoder是一个假想的开源项目,我将......
  • Mac开发基础16-NSButton(一)
    NSButton是macOS应用中常用的控件之一,用于处理各种按钮操作。它不仅提供了丰富的API来定制按钮的外观和行为,还可以通过不同的配置实现多种类型的按钮,如push按钮、toggle按钮、radio按钮等。1.基本用法创建和初始化Objective-C//创建和初始化一个NSButton实例NSB......
  • Mac开发基础17-NSButton(二)
    NSButton是一个功能强大且灵活多样的控件,除了基本使用和常见API外,还有一些进阶用法和技巧可以提高按钮的可用性和实现细节。在以下内容中,我会详细介绍一些进阶使用技巧,并封装一个常用的工具类来实现自定义的多种按钮类型。进阶使用和技巧1.自定义按钮的外观和行为Objective-C......
  • Mac开发基础13-NSTextView(一)
    NSTextView是macOS应用开发中相当强大的多行文本输入控件。它不仅支持文本输入和显示,还支持富文本、文本编辑、布局管理等功能。常见API和基础技巧初始化NSTextView程序化创建Objective-C//创建一个NSScrollView作为NSTextView的容器,因为NSTextView通常需要带滚动条的......
  • Mac开发基础14-NSTextView(二)
    进阶使用和技巧1.扩展查找和替换功能可以自定义查找和替换功能,包括高亮查找结果、批量替换等。查找并高亮Objective-C-(void)highlightOccurrencesOfString:(NSString*)searchString{//清除之前的高亮效果[textView.layoutManagerremoveTemporaryAttribute:N......
  • Xmind2024支持多平台使用,包括Windows、Mac、iOS、等操作系统
    “Xmind2024”是Xmind公司推出的一款全新的思维导图软件,它集成了多种功能,包括智能导图、AI生成、语音输入等。这款产品旨在帮助用户更高效地整理思路,提高思维能力。让我们来了解一下Xmind2024的特点。它采用了全新的设计风格,界面简洁明了,操作便捷。同时,它还提供了丰富的模板......
  • XMind2024思维导图软件特别版+便携版Mac+win+平板
    大家好!今天我们要聊的是一款神奇的思维工具——Xmind2024。你是否常常感到思维混乱,无法集中注意力,或者在处理复杂问题时感到无从下手?如果你有以上的困扰,那么恭喜你,Xmind2024将为你打开一扇全新的大门。让我们先来看看Xmind2024的特点吧。这款产品最大的亮点在于其强大的思维导......