2010-10-03 2 views
2

Я пытаюсь сделать более сложный рисунок UILabels (или UIView, накладывая на него UILabel сверху, если это потребуется). Поскольку я хочу, чтобы это автоматически изменялось, когда пользователь меняет ориентацию iPhone, я пытаюсь реализовать это в функции drawLect подкласса. Я хотел бы иметь возможность настраивать все это в коде, опустив необходимость в образах шаблонов, если это возможно.UIView CGGradient, привязанный к нарисованному «кадру»

Я получил некоторые подсказки от некоторых прежних постов на эту тему:

Gradients on UIView and UILabels On iPhone и Make Background of UIView a Gradient Without Sub Classing

К сожалению, они оба мимо цели, так как я хотел объединить градиент с пользовательской графикой. Я хочу, чтобы CGGradient был обрезан рамкой линии, которую я рисую (видимой в закругленных углах), но я не могу этого сделать.

Альтернативой может быть использование CAGradientLayer, который, кажется, работает неплохо, но для этого потребуется некоторое изменение кадра при повороте, а слой градиента, похоже, нарисован поверх текста, независимо от того, как я пытаюсь ,

Мой вопрос для этого двоякая

  • Как изменить код ниже, чтобы сделать градиент клип нарисованной «кадр»
  • Как сделать CAGradientLayer рисовать за текстом UILabel (или я должен поставить UIView позади UILabel с CAGradientLayer в качестве фона)

Вот моя DrawRect функция:

- (void)drawRect:(CGRect)rect { 
// Drawing code 
CGContextRef c = UIGraphicsGetCurrentContext(); 
CGContextSetFillColorWithColor(c, [[UIColor clearColor] CGColor]); 
CGContextSetStrokeColorWithColor(c, [strokeColor CGColor]); 
CGContextSetLineWidth(c, 1); 

CGFloat minx = CGRectGetMinX(rect), midx = CGRectGetMidX(rect), maxx = CGRectGetMaxX(rect) ; 
CGFloat miny = CGRectGetMinY(rect), midy = CGRectGetMidY(rect), maxy = CGRectGetMaxY(rect) ; 
minx = minx + 1; 
miny = miny + 1; 

maxx = maxx - 1; 
maxy = maxy - 1; 

CGGradientRef glossGradient; 
CGColorSpaceRef rgbColorspace; 
size_t num_locations = 2; 
CGFloat locations[2] = { 0.0, 1.0 }; 
CGFloat components[8] = { 0.6, 0.6, 0.6, 1.0, // Start color 
0.3, 0.3, 0.3, 1.0 }; // End color 

rgbColorspace = CGColorSpaceCreateDeviceRGB(); 
glossGradient = CGGradientCreateWithColorComponents(rgbColorspace, components, locations, num_locations); 

CGRect currentBounds = [self bounds]; 
CGPoint topCenter = CGPointMake(CGRectGetMidX(currentBounds), 0.0f); 
CGPoint midCenter = CGPointMake(CGRectGetMidX(currentBounds),   CGRectGetMidY(currentBounds)); 
CGPoint lowCenter = CGPointMake(CGRectGetMidX(currentBounds), CGRectGetMidY(currentBounds)); 

CGContextDrawLinearGradient(c, glossGradient, topCenter, midCenter, 0); 

CGGradientRelease(glossGradient); 
CGColorSpaceRelease(rgbColorspace); 

CGContextMoveToPoint(c, minx, midy); 
CGContextAddArcToPoint(c, minx, miny, midx, miny, ROUND_SIZE_INFO); 
CGContextAddArcToPoint(c, maxx, miny, maxx, midy, ROUND_SIZE_INFO); 
CGContextAddArcToPoint(c, maxx, maxy, midx, maxy, ROUND_SIZE_INFO); 
CGContextAddArcToPoint(c, minx, maxy, minx, midy, ROUND_SIZE_INFO); 

// Close the path 
CGContextClosePath(c); 
// Fill & stroke the path 
CGContextDrawPath(c, kCGPathFillStroke);     
//  return; 

[super drawRect: rect]; 
+0

В принципе, я хотел бы знать, есть ли способ ограничить Градиент определенной границей, немного похожей на флаг maskToBounds CALayer. – jollyCocoa

+0

Использование CAGradientLayer кажется адекватным для решения простых прямоугольных градиентных фонов, но вопрос остается, если возможно, выполнить ту же задачу с пользовательским рисунком ... (что, если, например, я хотел бы нарисовать собственный граничный фон с не квадратной границей используя CGContextAddLineToPoint() и CGContextAddArcToPoint(). Можно ли заполнить содержимое границы градиентом и как это будет выполнено)? – jollyCocoa

ответ

3

Что вы ищете CGContextClip()

Создать свой путь и градиент, как в вашем коде, а затем

CGContextClip(c); 
CGContextDrawLinearGradient(c, glossGradient, topCenter, midCenter, 0); 
CGGradientRelease(glossGradient); 

(Удалите старый вызов CGContextDrawLinearGradient)

Также не забудьте сохраните и восстановите свой контекст до и после того, как сделаете какую-либо обрезку.

Если ваша обрезка инвертирована от того, что вы хотите, попробуйте CGContextEOClip() (или нарисуйте свой путь в обратном порядке или der)

+0

Спасибо, я рассмотрю его как можно скорее! – jollyCocoa

+0

Я возвращаюсь к этой теме. Прошло некоторое время, и я надеюсь, вы прочтете это. Мне удалось создать градиент с обрезанными границами в соответствии с путём, но у меня все еще есть проблема, которую мне не удалось решить. В коде выше я создаю путь прямоугольника с закругленными углами. В исходном рисунке это привело к фигуре с нарисованной границей и другим цветом заливки. Теперь я хотел бы добавить специальный градиент к этой форме.Проблема в том, что ваше исправление позволяет мне нарисовать исходную фигуру с нераскрытым градиентом выше или только градиент, привязанный к пути. Итак, как я могу выполнить оба? – jollyCocoa

+0

Я решил. Решение состояло в том, чтобы нарисовать новый путь после того, как был пробит первый путь. Большое спасибо! – jollyCocoa

Смежные вопросы