我有一个NSScrollView,它通过点击IB中滚动视图上的图层复选标记设置为图层备份。在该scrollview中,我有一个NSTableView。在那个NSTableView中,我使用自定义的NSTableRowView在我的列之间的分隔线上绘制一条垂直的红线。我的NSTableView有2列。将我的scrollview设置为图层备份后,每当我拖动列分隔符使列更宽或更窄时,都不会调用drawBackgroundInRect,因此在拖动操作期间我的背景垂直线不会更新。
有解决方法吗?
这是我在drawBackgroundInRect中使用的代码:
- (void)drawBackgroundInRect:(NSRect)dirtyRect {
[super drawBackgroundInRect:dirtyRect];
NSGraphicsContext *nscontext = [NSGraphicsContext currentContext];
[nscontext saveGraphicsState];
CGContextRef context = (CGContextRef)[nscontext graphicsPort];
if (!self.isGroupRowStyle) {
CGRect leftColumnRect = [(NSView *)[self viewAtColumn:0] frame];
leftColumnRect.origin.y -= 1.0;
leftColumnRect.size.height += 2.0;
leftColumnRect.size.width += 1.0;
// grey background
CGContextSetGrayFillColor(context, 0.98, 1.0);
CGContextFillRect(context, leftColumnRect);
// draw nice red vertical line
CGContextBeginPath(context);
CGContextSetRGBStrokeColor(context, 0.6, 0.2, 0.2, 0.3);
CGContextMoveToPoint(context, leftColumnRect.size.width + 1.5, 0);
CGContextSetLineWidth(context, 1.0);
CGContextAddLineToPoint(context, leftColumnRect.size.width + 1.5, leftColumnRect.size.height);
CGContextStrokePath(context);
}
[nscontext restoreGraphicsState];
}
以下是调整列大小时遇到的问题:
当我没有将我的scrollview设置为图层备份时,它应该是这样的:
谢谢!
答案 0 :(得分:0)
经过一年多的努力,我终于找到了对自己问题的正确答案。
诀窍是在调整NSTableColumn的大小时,在可见行列表中的每一行上调用setNeedsDisplay。
这是我在NSViewController子类中使用的代码:
- (void)tableView:(NSTableView *)tableView isResizingTableColumn:(NSTableColumn *)tableColumn {
NSRange range = [tableView rowsInRect:tableView.visibleRect];
for (NSInteger row = range.location; row < (range.location + range.length); row++) {
NSTableRowView *rowView = [tableView rowViewAtRow:row makeIfNecessary:NO];
[rowView setNeedsDisplay:YES];
}
}
我的NSTableView的标题视图是我自己的NSTableHeaderView子类。我将我的NSViewController设置为标题视图的委托,以便我可以跟踪用户何时调整大小。
TFRecordTableHeaderView.h:
#import <Cocoa/Cocoa.h>
@protocol TFRecordTableHeaderViewDelegate <NSObject>
- (void)tableView:(NSTableView *)tableView isResizingTableColumn:(NSTableColumn *)tableColumn;
@end
@interface TFRecordTableHeaderView : NSTableHeaderView
@property (nonatomic, assign) id<TFRecordTableHeaderViewDelegate>delegate;
@end
TFRecordTableHeaderView.m:
#import "TFRecordTableHeaderView.h"
@implementation TFRecordTableHeaderView
- (id)initWithFrame:(NSRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Initialization code here.
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
// do some custom drawing here
}
// track resizing of the column as it happens
// from the docs: If the user is resizing a column in the receiver, returns the index of that column.
- (NSInteger)resizedColumn {
NSInteger columnIndex = [super resizedColumn];
if (columnIndex >= 0) {
NSTableColumn *column = [self.tableView.tableColumns objectAtIndex:columnIndex];
if ([self.delegate respondsToSelector:@selector(tableView:isResizingTableColumn:)]) {
[self.delegate tableView:self.tableView isResizingTableColumn:column];
}
}
return columnIndex;
}
@end
只需将NSTableHeaderView子类设置为NSTableView的标题视图即可。现在,只要在标题中拖动列,就会调用isResizingTableColumn委托方法。您可以在NSViewController子类上实现isResizingTableColumn。
现在,当您调整列的大小时,将调用isResizingTableColumn,它将获取可见rect的NSTableRowViews,并将发送setNeedsDisplay。这将导致刷新行,并在拖动时调用drawBackgroundInRect方法。这反过来将刷新我的自定义垂直网格线。
这一切都是为了避免在NSTableView上的顶部分组行上绘制垂直网格线。我认为这应该内置于NSTableView。如果您的组部分标题中包含文字,并且文本顶部正好有垂直网格线,那么看起来非常糟糕。
现在我考虑一下,你可以在你的NSTableHeaderView子类上做到这一点:
- (NSInteger)resizedColumn {
NSInteger columnIndex = [super resizedColumn];
if (columnIndex >= 0) {
NSRange range = [self.tableView rowsInRect:self.tableView.visibleRect];
for (NSInteger row = range.location; row < (range.location + range.length); row++) {
NSTableRowView *rowView = [self.tableView rowViewAtRow:row makeIfNecessary:NO];
[rowView setNeedsDisplay:YES];
}
}
return columnIndex;
}
在我的情况下,我是在我的NSViewController子类上进行的,因为当我调整一个表列的大小时,我也同样调整了另一个。这是模拟一个页脚行与另一个类似配置的表,其中只有一行,因为NSTableView没有像UITableView那样的页脚概念。