Градиенты в UIView и UILabels на iPhone

Possible Duplicate:
Manually drawing a gradient in iPhone apps?

Мое приложение должно отображать текст в UIView или UILabel, но фон должен быть градиентным, а не истинным UIColor. Использование графической программы для создания желаемого внешнего вида бесполезно, поскольку текст может отличаться в зависимости от данных, возвращаемых с сервера.

Кто-нибудь знает самый быстрый способ решить эту проблему? Ваши мысли очень ценятся.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
220
0
175 551
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Вы можете использовать Core Graphics, чтобы нарисовать градиент, как указано в ответе Майка. В качестве более подробного примера вы можете создать подкласс UIView для использования в качестве фона для вашего UILabel. В этом подклассе UIView переопределите метод drawRect: и вставьте код, подобный следующему:

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

    CGGradientRef glossGradient;
    CGColorSpaceRef rgbColorspace;
    size_t num_locations = 2;
    CGFloat locations[2] = { 0.0, 1.0 };
    CGFloat components[8] = { 1.0, 1.0, 1.0, 0.35,  // Start color
         1.0, 1.0, 1.0, 0.06 }; // 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));
    CGContextDrawLinearGradient(currentContext, glossGradient, topCenter, midCenter, 0);

    CGGradientRelease(glossGradient);
    CGColorSpaceRelease(rgbColorspace); 
}

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

Вам просто нужно правильно выбрать размер этого UIView и добавить свой UILabel в качестве его части, чтобы получить желаемый эффект.

РЕДАКТИРОВАТЬ (4/23/2009): по предложению St3fan я заменил фрейм представления его границами в коде. Это исправляет случай, когда источник представления не (0,0).

Я пробовал этот код, но он неправильный. Вместо того, чтобы устанавливать для currentFrame значение self.frame, следует установить значение self.bounds.

Stefan Arentz 23.04.2009 00:20

Вы правы, спасибо, что указали на это. С тех пор я исправил свой собственный код, но забыл, что это требует обновления. Ситуация, которая возникает у вас, - это когда исходная точка вида имеет положение Y, отличное от 0. Затем градиент отрисовывается смещением от центра по вертикали.

Brad Larson 23.04.2009 16:33

Можно ли это применить к UIImage или UIImageView, чтобы иметь любое изображение с градиентом?

sashaeve 15.12.2009 13:31

Вы можете разместить это поверх UIImageView, чтобы добавить градиент. Для изменения содержимого изображения вам может потребоваться сначала нарисовать изображение в контексте, нарисовать градиент над ним в этом контексте, а затем сохранить контекст как новое изображение.

Brad Larson 19.12.2009 02:06

Можете ли вы сказать мне, как вы определяете цвета при использовании следующих компонентов: CGFloat components [8] = {1.0, 1.0, 1.0, 0.35, 1.0, 1.0, 1.0, 0.06}; Как узнать, например, что такое 1.0 и 0.35?

fulvio 07.03.2011 06:41

@Fulvio - это два цвета, представленные двумя наборами красного, зеленого, синего и альфа-компонентов. Эти компоненты нормализованы до 1,0, так что непрозрачный черный будет (0,0, 0,0, 0,0, 1,0), а непрозрачный белый будет (1,0, 1,0, 1,0, 1,0).

Brad Larson 07.03.2011 17:11

Как вы вызываете этот метод и / или применяете его к UIImageView?

RyeMAC3 29.09.2012 03:05

Невозможно для UIImageView - он не вызывает drawRect.

Guntis Treulands 30.11.2012 17:38

Не забудьте добавить масштаб устройства: CGRect currentBounds = (CGRect) {0, 0, self.bounds.size.width * [UIScreen mainScreen] .scale, self.bounds.size.height * [UIScreen mainScreen] .scale ,};

myeyesareblind 09.04.2014 16:46
Ответ принят как подходящий

Вы также можете использовать графическое изображение шириной в один пиксель в качестве градиента и установить свойство view, чтобы развернуть графику, чтобы заполнить вид (при условии, что вы думаете о простом линейном градиенте, а не о какой-то радиальной графике).

Привет, Кендалл, спасибо, чувак, ты сработал для меня. Решил это просто, поместив градиент в UIImageView и поместив поверх него динамическую метку. Спасибо всем за помощь. Тони

TonyNeallon 08.01.2009 14:20

При таком подходе убедитесь, что у вас есть два разных градиента: один для обычных дисплеев и один для дисплеев Retina.

Kamchatka 04.10.2011 06:39

Одним из важных преимуществ этого решения по сравнению с кодированными решениями является то, что цветовые градиенты обычно являются свойством украшения и на самом деле не должны выражаться в коде вообще. Вот для чего нужны графические ребята. Написание кода для выражения цветов - плохое разделение логики от представления. Когда маркетинговая команда решает изменить цвета, и специалист по графике спрашивает, как это сделать, ему не понравится, когда ему говорят, что вы просто настраиваете массив цветов на CAGradientLayer в MyLabelView.m ... и он не должен. Не имеет большого значения для магазина одного человека, но для команды имеет значение.

Nate 16.06.2012 14:05

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

Kendall Helmstetter Gelner 17.06.2012 01:05

@Nate - ваш код для вашей логики должен быть отделен от вашего кода для вашей презентации. Это не означает, что ваше единственное возможное решение - иметь графический файл, и, честно говоря, для каждого растрового изображения в вашем приложении вы настраиваете себя на дополнительную работу в будущем. Код градиента всегда будет отлично выглядеть. Растровое изображение будет хорошо выглядеть только до тех пор, пока Apple снова не решит увеличить разрешение экрана.

ArtOfWarfare 30.12.2012 07:48

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

Kendall Helmstetter Gelner 30.12.2012 08:29

То же самое для представлений с динамической высотой, например, для ячейки, высота которой зависит от того, сколько текста она должна содержать.

Adam 24.01.2013 09:04

Зачем вам менять 50 файлов xib, если у вас есть только одно изображение градиента, которое вы меняете? Теоретически это было бы так же просто, как изменить код. Я вижу, что код для градиентов используется, когда вам по какой-то причине нужно динамически создать градиент.

Kendall Helmstetter Gelner 12.10.2013 00:24

Я достигаю этого в представлении с подпредставлением, которое является UIImageView. Изображение, на которое указывает ImageView, является градиентом. Затем я устанавливаю цвет фона в UIView, и у меня есть цветной градиентный вид. Затем я использую вид, как мне нужно, и все, что я рисую, будет находиться под этим видом градиента. Добавив второе представление поверх ImageView, вы можете иметь некоторые параметры, будет ли ваш рисунок ниже или выше градиента ...

Я понимаю, что это более старая ветка, но для справки в будущем:

Начиная с iPhone SDK 3.0, пользовательские градиенты можно очень легко реализовать без создания подклассов или изображений с помощью нового CAGradientLayer:

 UIView *view = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 100)] autorelease];
 CAGradientLayer *gradient = [CAGradientLayer layer];
 gradient.frame = view.bounds;
 gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor blackColor] CGColor], (id)[[UIColor whiteColor] CGColor], nil];
 [view.layer insertSublayer:gradient atIndex:0];

Взгляните на документы CAGradientLayer. При желании вы можете указать начальную и конечную точки (если вам не нужен линейный градиент, идущий прямо сверху вниз) или даже определенные местоположения, которые соответствуют каждому из цветов.

На всякий случай, если мой комментарий попадется кому-нибудь на глаза, когда они рассматривают возможность реализации других решений, указанных выше, СДЕЛАТЬ ЭТО. Это не может быть проще (но помните, что вам нужно добавить фреймворк QuartzCore и импортировать #import <QuartzCore/QuartzCore.h> в свой класс).

Justin Searls 14.02.2010 00:31

Отличная работа: намного проще, чем другие решения.

jkp 03.03.2010 21:17

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

Brad Robinson 12.04.2010 18:14

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

Mirko Froehlich 15.04.2010 01:26

Кто-то может применить дополнительный эффект, например, cornerRadius. Они должны добавить сюда еще код: view.layer.masksToBounds = YES;, чтобы убедиться, что все идет гладко.

iwat 27.05.2010 08:14

Это сработало отлично, большое спасибо!

jakeboxer 17.07.2010 04:28

Какой способ обеспечивает лучшую производительность? Используете CAGradientLayer или UIImageViews?

samvermette 03.10.2010 07:47

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

Mike 18.11.2010 00:33

Хм. Текст моей метки исчезает, когда я использую это решение.

HiveHicks 17.12.2010 20:28

Эй, это потрясающе - спасибо! («Он написал больше года спустя.») Интересно, могу ли я использовать это для ячеек табличного представления на выбранном и невыделенном фоне? Я думаю, я просто вставляю подслои в каждое из этих представлений в ячейке. Может быть. (Я предполагаю, что в выбранном состоянии уже есть градиент - хм ...!)

Joe D'Andrea 20.03.2011 03:02

@Mike: Насколько велика разница в производительности? Есть ли у вас какие-то конкретные тесты / показатели, подтверждающие ваше утверждение?

Rafael Bugajewski 13.07.2011 20:21

@Rafael Довольно большая разница. Я написал приложение, очень похожее на почтовое приложение, и использую синий шарик с градиентной заливкой в ​​каждой ячейке таблицы, чтобы отмечать непрочитанное сообщение. Прокрутка таблицы была значительно медленнее, чем альтернатива с заранее созданным изображением мяча. Попробуйте и убедитесь.

Mike 17.08.2011 03:14

@HiveHicks Я обнаружил, что если я использую CAGradientLayer для UILabel, мне нужно установить backgroundColor на [UIColor clearColor] (или эквивалент)

Thomas Müller 09.09.2011 08:44

Я пытаюсь использовать это для uitableviewcell, и градиент выходит за пределы правой части ячейки. Что я делаю неправильно?

zakdances 22.05.2012 23:32

Совет: чтобы использовать выделение (и показать другой градиент с выделением), создайте подкласс UIButton и используйте метод "- (void) setHighlighted: (BOOL) highlight {if (highlight! = Self.highlighted) {...}}". Затем я вставляю туда переключение слоев (ставим нормальный слой на ноль и выделяю на 1). Работает отлично.

Anna Billstrom 01.06.2012 22:52

У меня он работает, с градиентами, выделением (градиент на выделении тоже), закругленными углами и т. д. Вы также можете скачать код: banane.com/2012/06/01/iphone-gradient-buttons-with-high‌ освещения

Anna Billstrom 03.06.2012 23:16

Я добавил это в свою ячейку таблицы. У меня при загрузке видно 9 строк. Когда я загружаю таблицу с помощью нажатия кнопки в основном представлении, для ее нажатия требуется добрых 10 секунд. Нулевые секунды без градиента. Почему такая задержка?

RyeMAC3 02.10.2012 16:23

То, что нарисовано с помощью drawRect: все еще находится под этим градиентом. Просто забавный факт.

Guntis Treulands 15.10.2012 02:13

@Mike - Интересно, правильно ли вы используете deque? Разве код рисования не должен выполняться только один раз для каждой видимой ячейки и никогда больше, если вы прокручиваете, потому что он просто повторно использует старые ячейки?

ArtOfWarfare 30.12.2012 08:14

Возможно, вам потребуется связать библиотеку QuartzCore: stackoverflow.com/questions/7464399/… Проверьте решение и комментарий ниже =)

Abdo 10.01.2013 03:26

прекрасный код для применения градиента. действительно полезно

Warewolf 27.02.2013 11:31

Не работает для UILabel. Цвет градиента в фоновом режиме не отображается.

Muhammad Aamir Ali 13.03.2013 14:08

Есть идеи, как сделать радиальный градиент?

Bijoy Thangaraj 08.01.2014 18:08

Похоже, это не работает как градиент для фона всего приложения. Слой не изменяется автоматически в зависимости от вида.

MusiGenesis 21.01.2014 20:07

@MusiGenesis см. Мой ответ здесь: stackoverflow.com/a/27236831/202875

tybro0103 01.12.2014 23:40

@MirkoFroehlich, пожалуйста, проверьте этот вопрос: stackoverflow.com/questions/39255885/…

Ehtesham Hasan 01.09.2016 06:11

один голос за простой ответ .. Очень просто и полезно, спасибо ..! Но как я могу достичь этого для текста UILabel, а не для фона ..... любая идея ...?

Abirami Bala 24.10.2016 14:55

Примечание: Приведенные ниже результаты применимы к более старым версиям iOS, но при тестировании на iOS 13 степпинг не происходит. Не знаю, для какой версии iOS убрали степпинг.


При использовании CAGradientLayer, в отличие от CGGradient, градиент не плавный, но имеет заметные ступенчатые переходы. См. this example:

Для получения более привлекательных результатов лучше использовать CGGradient.

Не могли бы вы опубликовать код, эквивалентный примеру Мирко Фрёлиха с CGGradient?

zekel 13.01.2011 20:09

Приведенный выше код Брэда Ларсона с использованием CGGradient достаточно хорош. Я бы сделал свой комментарий как комментарий к одному из этих ответов, но у меня пока недостаточно очков.

ThomasW 14.01.2011 07:52

Как вы можете сказать? Ваши градиенты оканчиваются (внизу) разными цветами.

ma11hew28 16.02.2012 19:42

@MattDiPasquale У меня нет под рукой кода, который я использовал для его создания, но, насколько я помню, в конечных точках использовались те же цвета. В любом случае я сомневаюсь, что это имеет значение, поскольку моя точка зрения связана с качеством градиента. В любом случае вы сможете сами воспроизвести результаты. (В то время я использовал iOS 4.x, поэтому результаты могут отличаться от iOS 5.)

ThomasW 17.02.2012 06:07
ВАЖНЫЙ: Я недавно удалил свой код CGGradient и заменил его на CAGradientLayer. Ты знаешь почему? Я рисовал это примерно на 30 ячейках, и влияние на производительность было БОЛЬШИМ. CAGradient был намного лучше с точки зрения производительности (объясняет крошечную разницу в качестве).
Mazyod 29.05.2012 22:09

Если высота вида, который вы хотите добавить градиент, мала, я думаю, CAGradientLayer - это компромисс, который вы можете себе позволить. Если высота просмотра значительна, лучше использовать CGGradient. Таким образом, маловероятно, что вы поместите изображение большей высоты в режим прокрутки.

Deepak G M 13.02.2013 17:41

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

SaltyNuts 05.06.2013 18:08

Обновил свой ответ. В моих первоначальных тестах этой проблемы не было на iOS 13.

ThomasW 03.05.2020 15:37

Это то, что у меня получилось - установить UIButton в IB xCode на прозрачный / прозрачный и без изображения bg.

UIColor *pinkDarkOp = [UIColor colorWithRed:0.9f green:0.53f blue:0.69f alpha:1.0];
UIColor *pinkLightOp = [UIColor colorWithRed:0.79f green:0.45f blue:0.57f alpha:1.0];

CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = [[shareWordButton layer] bounds];
gradient.cornerRadius = 7;
gradient.colors = [NSArray arrayWithObjects:
                   (id)pinkDarkOp.CGColor,
                   (id)pinkLightOp.CGColor,
                   nil];
gradient.locations = [NSArray arrayWithObjects:
                      [NSNumber numberWithFloat:0.0f],
                      [NSNumber numberWithFloat:0.7],
                      nil];

[[recordButton layer] insertSublayer:gradient atIndex:0];

Хорошо, изменение - теперь я создаю подкласс UIButton и использую метод выделения: "- (void) setHighlighted: (BOOL) highlight {if (highlight! = Self.highlighted) {" внутри этого, сделайте переключение слоя. работает отлично.

Anna Billstrom 01.06.2012 22:50

Причем, подробно об этом писали здесь: banane.com/2012/06/01/iphone-gradient-buttons-with-highlighting

Anna Billstrom 03.06.2012 09:01

Как можно удалить этот CAGradientLayer из представления?

Ajay Sharma 25.09.2012 13:05

Найдите его и удалите из слоя представлений кнопки, если я помню.

Anna Billstrom 26.09.2012 05:12

Ответ Мирко Фрелиха сработал для меня, за исключением случаев, когда я хотел использовать собственные цвета. Хитрость заключается в том, чтобы указать цвет пользовательского интерфейса с помощью оттенка, насыщенности и яркости вместо RGB.

CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = myView.bounds;
UIColor *startColour = [UIColor colorWithHue:.580555 saturation:0.31 brightness:0.90 alpha:1.0];
UIColor *endColour = [UIColor colorWithHue:.58333 saturation:0.50 brightness:0.62 alpha:1.0];
gradient.colors = [NSArray arrayWithObjects:(id)[startColour CGColor], (id)[endColour CGColor], nil];
[myView.layer insertSublayer:gradient atIndex:0];

Чтобы получить оттенок, насыщенность и яркость цвета, используйте встроенное средство выбора цвета xcode и перейдите на вкладку HSB. В этом представлении оттенок измеряется в градусах, поэтому разделите значение на 360, чтобы получить значение, которое вы хотите ввести в код.

Я могу добавить этот CAGradientLayer, но как его удалить из myView? Я хотел бы иметь вид, как раньше, до рисования CAGradientLayer. Есть ли для этого что-нибудь?

Ajay Sharma 25.09.2012 13:05

Я бы перебирал myView.layer.sublayers до тех пор, пока вы не получили CAGradientLayer, а затем вызвал бы removeFromSuperlayer. для (CALayer * currentLayer в [подслоях self.view.layer]) {if ([currentLayer isKindOfClass: [CAGradientLayer class]]) {[currentLayer removeFromSuperlayer]; }}

Robert Wagstaff 13.03.2013 02:14

Wtf, почему бы просто не сохранить слой градиента как свойство экземпляра и удалить его, когда он больше не нужен?

return true 19.11.2017 15:12

Другие вопросы по теме