Bry*_*yan 9 macos cocoa objective-c
背景:
下面的镜头是OS X Lion中的Mail.app.当源列表变得太长时,在源列表底部的按钮上方会出现一条漂亮的阴影线.滚动时,源列表会在该阴影线下移动.当您展开窗口以使源列表中的所有内容都适合而不滚动时,阴影线将消失.
问题:
如何使用Cocoa绘制这条阴影线?我知道NSShadow等等,但在我看来,这里发生的事情不仅仅是阴影.有一条线巧妙地淡化到点(就好像你在Photoshop中的每一端应用了渐变蒙版.)同样,阴影是椭圆形的,当你接近线的末端时逐渐变细.所以它不只是常规的NSShadow,是吗?(它绝对不是图像,因为当您扩展源视图的宽度时,它可以很好地缩放.)
关于如何绘制这种形状的任何提示都将非常感激.

对于坚持不懈的人来说,不,这并不违反NDA,因为Mail.app已被Apple公开展示.
Reg*_*ent 16
.
150px × 10px的图层"图层A",#535e71 不透明度: 33%#535e71 不透明度: 0%150px × 1px的图层"图层B",#535e71 : 50%#ffffff到#000000到"层C".
MyView.h:
#import <Cocoa/Cocoa.h>
@interface MyView : NSView {
@private
}
@end
Run Code Online (Sandbox Code Playgroud)
MyView.m:
#import "MyView.h"
@implementation MyView
- (CGImageRef)maskForRect:(NSRect)dirtyRect {
NSSize size = [self bounds].size;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, size.width, size.height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast);
CGContextClipToRect(context, *(CGRect*)&dirtyRect);
CGRect rect = CGRectMake(0.0, 0.0, size.width, size.height);
size_t num_locations = 3;
CGFloat locations[3] = { 0.0, 0.5, 1.0 };
CGFloat components[12] = {
1.0, 1.0, 1.0, 1.0, // Start color
0.0, 0.0, 0.0, 1.0, // Middle color
1.0, 1.0, 1.0, 1.0, // End color
};
CGGradientRef myGradient = CGGradientCreateWithColorComponents(colorSpace, components, locations, num_locations);
CGPoint myStartPoint = CGPointMake(CGRectGetMinX(rect), CGRectGetMinY(rect));
CGPoint myEndPoint = CGPointMake(CGRectGetMaxX(rect), CGRectGetMinY(rect));
CGContextDrawLinearGradient(context, myGradient, myStartPoint, myEndPoint, 0);
CGImageRef theImage = CGBitmapContextCreateImage(context);
CGImageRef theMask = CGImageMaskCreate(CGImageGetWidth(theImage), CGImageGetHeight(theImage), CGImageGetBitsPerComponent(theImage), CGImageGetBitsPerPixel(theImage), CGImageGetBytesPerRow(theImage), CGImageGetDataProvider(theImage), NULL, YES);
[(id)theMask autorelease];
CGColorSpaceRelease(colorSpace);
CGContextRelease(context);
return theMask;
}
- (void)drawRect:(NSRect)dirtyRect {
NSRect nsRect = [self bounds];
CGRect rect = *(CGRect*)&nsRect;
CGRect lineRect = CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, (CGFloat)1.0);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort];
CGContextClipToRect(context, *(CGRect*)&dirtyRect);
CGContextClipToMask(context, rect, [self maskForRect:dirtyRect]);
size_t num_locations = 2;
CGFloat locations[2] = { 0.0, 1.0 };
CGFloat components[8] = {
0.315, 0.371, 0.450, 0.3, // Bottom color
0.315, 0.371, 0.450, 0.0 // Top color
};
CGGradientRef myGradient = CGGradientCreateWithColorComponents(colorSpace, components, locations, num_locations);
CGPoint myStartPoint = CGPointMake(CGRectGetMinX(rect), CGRectGetMinY(rect));
CGPoint myEndPoint = CGPointMake(CGRectGetMinX(rect), CGRectGetMaxY(rect));
CGContextDrawLinearGradient(context, myGradient, myStartPoint, myEndPoint, 0);
CGContextSetRGBFillColor(context, 0.315, 0.371, 0.450, 0.5 );
CGContextFillRect(context, lineRect);
CGColorSpaceRelease(colorSpace);
}
@end
Run Code Online (Sandbox Code Playgroud)
(我第一次使用纯粹的低级CoreGraphics,因此可能低于最佳值,可以进行改进.)
这是上面代码产生的实际屏幕截图:

图纸延伸到视图的尺寸.
(我以前有两种技术显示在这里:"技术A"和"技术B".
"技术B"提供了优异的结果,并且实现起来也更简单,所以我放弃了"技术A".
有些评论可能仍然提到"技术A"虽然.只是忽略它们并享受功能完整的代码片段."
| 归档时间: |
|
| 查看次数: |
1681 次 |
| 最近记录: |