Неровные пути при перетаскивании закадрового CGLayer в текущий контекст - PullRequest
0 голосов
/ 11 октября 2011

В моем текущем проекте мне нужно нарисовать сложный фон в качестве фона для нескольких ячеек UITableView.Поскольку код для рисования этого фона довольно длинный и сильно загружает процессор при выполнении в drawRect: методе ячейки, я решил отрендерить его только один раз в CGLayer, а затем перетащить его в ячейку, чтобы повысить общую производительность.

Код, который я использую для отрисовки фона на CGLayer:

+ (CGLayerRef)standardCellBackgroundLayer
{
    static CGLayerRef standardCellBackgroundLayer;

    if(standardCellBackgroundLayer == NULL)
    {
        CGContextRef viewContext = UIGraphicsGetCurrentContext();
        CGRect rect = CGRectMake(0, 0, [UIScreen mainScreen].applicationFrame.size.width, PLACES_DEFAULT_CELL_HEIGHT);

        standardCellBackgroundLayer = CGLayerCreateWithContext(viewContext, rect.size, NULL);
        CGContextRef context = CGLayerGetContext(standardCellBackgroundLayer);

        // Setup the paths
        CGRect rectForShadowPadding = CGRectInset(rect, (PLACES_DEFAULT_CELL_SHADOW_SIZE / 2) + PLACES_DEFAULT_CELL_SIDE_PADDING, (PLACES_DEFAULT_CELL_SHADOW_SIZE / 2));
        CGMutablePathRef path = createPathForRoundedRect(rectForShadowPadding, LIST_ITEM_CORNER_RADIUS);

        // Save the graphics context state
        CGContextSaveGState(context);

        // Draw shadow
        CGContextSetShadowWithColor(context, CGSizeMake(0, 0), PLACES_DEFAULT_CELL_SHADOW_SIZE, [Skin shadowColor]);
        CGContextAddPath(context, path);
        CGContextSetFillColorWithColor(context, [Skin whiteColor]);
        CGContextFillPath(context);

        // Clip for gradient
        CGContextAddPath(context, path);
        CGContextClip(context);

        // Draw gradient on clipped path
        CGPoint startPoint = rectForShadowPadding.origin;
        CGPoint endPoint = CGPointMake(rectForShadowPadding.origin.x, CGRectGetMaxY(rectForShadowPadding));
        CGContextDrawLinearGradient(context, [Skin listGradient], startPoint, endPoint, 0);

        // Restore the graphics state and release everything
        CGContextRestoreGState(context);
        CGPathRelease(path);
    }

    return standardCellBackgroundLayer;
}

Код для перетаскивания слоя в текущий контекст:

- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextDrawLayerAtPoint(context, CGPointMake(0.0, 0.0), [Skin standardCellBackgroundLayer]);
}

Это на самом деле довольно неплохо.хорошо, но единственная проблема, которую я имею, состоит в том, что закругленные углы (проверьте статический метод).Очень зазубрины, когда моргнут на экран.Это был не тот случай, когда код рисования был в исходном положении: в методе drawRect.

Как мне вернуть этот сглаживание?

По какой-то причине следующие методы неоказать какое-либо влияние на сглаживание:

CGContextSetShouldAntialias(context, YES);
CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
CGContextSetAllowsAntialiasing(context, YES);

Заранее спасибо!

Ответы [ 2 ]

1 голос
/ 03 марта 2013

Вы можете упростить это, просто используя UIGraphicsBeginImageContextWithOptions и установив масштаб на 0.0.

Извините за пробуждение старого поста, но я натолкнулся на него, чтобы кто-то еще тоже мог. Более подробную информацию можно найти в UIGraphicsBeginImageContextWithOptions документации :

Если указать значение 0.0, коэффициент масштабирования будет установлен на масштаб коэффициент основного экрана устройства.

В основном это означает, что если это отображение сетчатки, то оно создаст контекст сетчатки, так что вы можете указать 0.0 и рассматривать координаты как точки.

0 голосов
/ 06 января 2012

Я собираюсь ответить на свой вопрос, так как я выяснил это некоторое время назад.Вы должны сделать контекст сетчатки осведомленным.Зубчатость появилась только на устройстве с сетчаткой.

Чтобы противостоять этому поведению, вы должны создать контекст сетчатки с помощью этого вспомогательного метода:

// Begin a graphics context for retina or SD
void RetinaAwareUIGraphicsBeginImageContext(CGSize size) 
{
    static CGFloat scale = -1.0;

    if(scale < 0.0) 
    {   
        UIScreen *screen = [UIScreen mainScreen];

        if([[[UIDevice currentDevice] systemVersion] floatValue] >= 4.0)
        {    
            scale = [screen scale]; // Retina
        }
        else 
        {
            scale = 0.0; // SD
        }
    }

    if(scale > 0.0)
    {    
        UIGraphicsBeginImageContextWithOptions(size, NO, scale);   
    }
    else 
    {    
        UIGraphicsBeginImageContext(size);   
    }
}

Затем в своем методе рисования вызовите перечисленный методвыше вот так:

+ (CGLayerRef)standardCellBackgroundLayer
{
    static CGLayerRef standardCellBackgroundLayer;

    if(standardCellBackgroundLayer == NULL)
    {
        RetinaAwareUIGraphicsBeginImageContext(CGSizeMake(320.0, 480.0));
        CGRect rect = CGRectMake(0, 0, [UIScreen mainScreen].applicationFrame.size.width, PLACES_DEFAULT_CELL_HEIGHT);

        ...
...