Потяните округленный UIView с градиентом и падающей тенью

Править:

Я наконец нашел реальное простое решение этой проблемы, с помощью класса CAGradientLayer и CALayer рисование технических возможностей.
Ole Begemann выпустил большую обертку UIView для класса CAGradientLayer под названием OBGradientView.
Этот класс позволяет Вам легко создавать градиент UIView в Вашем приложении.
Вы затем используете CALayer рисование технических возможностей для добавления значений падающей тени и скругленных углов:

// Create the gradient view
OBGradientView *gradient = [[OBGradientView alloc] initWithFrame:someRect];
NSArray *colors = [NSArray arrayWithObjects:[UIColor redColor], [UIColor yellowColor], nil];
gradient.colors = colors;

// Set rounded corners and drop shadow
gradient.layer.cornerRadius = 5.0;
gradient.layer.shadowColor = [UIColor grayColor].CGColor;
gradient.layer.shadowOpacity = 1.0;
gradient.layer.shadowOffset = CGSizeMake(2.0, 2.0);
gradient.layer.shadowRadius = 3.0;

[self.view addSubview:gradient];
[gradient release];

Не забывайте добавлять платформу QuartzCore к своему проекту.



ИСХОДНЫЙ ВОПРОС:

Я работал над пользовательским элементом управления, который является кнопкой скругленного прямоугольника, заполненной линейным градиентом и наличием падающей тени. Я заполнил эти два первых шага с помощью этого ответа: текст ссылки

Моя проблема состоит в том, чтобы теперь добавить падающую тень под получающейся формой. На самом деле контекст был отсечен к округленному, реагируют путь, поэтому когда я использую функцию CGContextSetShadow, это не тянет его.

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

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

http://img269.imageshack.us/img269/6489/capturedcran20100701192.png

Это почти хорошо, но не прекрасно все же...

Вот мой-drawRect: реализация:

static void addRoundedRectToPath(CGContextRef context, CGRect rect, float ovalWidth, float ovalHeight)
{
 float fw, fh;

 if (ovalWidth == 0 || ovalHeight == 0) {
  CGContextAddRect(context, rect);
  return;
 }
 CGContextSaveGState(context);
 CGContextTranslateCTM (context, CGRectGetMinX(rect), CGRectGetMinY(rect));
 CGContextScaleCTM (context, ovalWidth, ovalHeight);
 fw = CGRectGetWidth (rect) / ovalWidth;
 fh = CGRectGetHeight (rect) / ovalHeight;
 CGContextMoveToPoint(context, fw, fh/2);
 CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1);
 CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1);
 CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1);
 CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1);
 CGContextClosePath(context);
 CGContextRestoreGState(context);
}


- (void)drawRect:(CGRect)rect
{ 
 CGContextRef context = UIGraphicsGetCurrentContext();

 CGSize shadowOffset = CGSizeMake(10.0, 10.0);
 CGFloat blur = 5.0;

 rect.size.width -= shadowOffset.width + blur;
 rect.size.height -= shadowOffset.height + blur;

 CGContextSaveGState(context);
 addRoundedRectToPath(context, rect, _radius, _radius);
 CGContextSetShadow (context, shadowOffset, blur);
 CGContextDrawPath(context, kCGPathFill);
 CGContextRestoreGState(context);

 addRoundedRectToPath(context, rect, _radius, _radius);
    CGContextClip(context);

 CGFloat colors[] =
 {
  _gradientStartColor.red, _gradientStartColor.green, _gradientStartColor.blue, _gradientStartColor.alpha,
  _gradientEndColor.red, _gradientEndColor.green, _gradientEndColor.blue, _gradientEndColor.alpha
 };
 size_t num_locations = 2;
    CGFloat locations[2] = { 0.0, 1.0 };

 CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
 CGGradientRef gradient = CGGradientCreateWithColorComponents(rgb, colors, locations, num_locations);

 CGRect currentBounds = self.bounds;
 CGPoint gStartPoint = CGPointMake(CGRectGetMidX(currentBounds), 0.0f);
 CGPoint gEndPoint = CGPointMake(CGRectGetMidX(currentBounds), CGRectGetMaxY(currentBounds));
 CGContextDrawLinearGradient(context, gradient, gStartPoint, gEndPoint, 0);

 CGColorSpaceRelease(rgb);
 CGGradientRelease(gradient);
}

Какие-либо идеи о том, как сделать это в другом отношении?

Спасибо!

14
задан Community 23 May 2017 в 12:17
поделиться

1 ответ

Для теней вы можете использовать CGContextSetShadow ()

Этот код будет рисовать что-то с тенью:

- (void)drawTheRealThingInContext:(CGContextRef)ctx 
{   
        // calculate x, y, w, h and inset here...

    CGContextMoveToPoint(ctx, x+inset, y);
    CGContextAddLineToPoint(ctx, x+w-inset, y);
    CGContextAddArcToPoint(ctx, x+w, y, x+w, y+inset, inset);
    CGContextAddLineToPoint(ctx, x+w, y+w-inset);
    CGContextAddArcToPoint(ctx,x+w, y+w, x+w-inset, y+w, inset);
    CGContextAddLineToPoint(ctx, x+inset, y+w);
    CGContextAddArcToPoint(ctx,x, y+w, x, y+w-inset, inset);
    CGContextAddLineToPoint(ctx, x, y+inset);
    CGContextAddArcToPoint(ctx,x, y, x+inset, y, inset);    
}
- (void)drawRect:(CGRect)rect {

    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGFloat color[4];color[0] = 1.0;color[1] = 1.0;color[2] = 1.0;color[3] = 1.0;
    CGFloat scolor[4];scolor[0] = 0.4;scolor[1] = 0.4;scolor[2] = 0.4;scolor[3] = 0.8;

    CGContextSetFillColor(ctx, color);

    CGContextSaveGState(ctx);
    CGSize  myShadowOffset = CGSizeMake (3,  -3);
    CGContextSetShadow (ctx, myShadowOffset, 1);

    CGContextBeginPath(ctx);

    [self drawTheRealThingInContext:ctx];

    CGContextFillPath(ctx);
    CGContextRestoreGState(ctx);
}
1
ответ дан 1 December 2019 в 09:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: