Возможно ли, чтобы цвет текста представлял собой диапазон цветов? [Дубликат]

попробуйте

mysql --version

, например. Или dpkg -l 'mysql-server*'.

23
задан Brad Larson 12 August 2009 в 18:45
поделиться

7 ответов

(Пропустить вниз для полного исходного кода)

Действительно полезные ответы и Брэда Ларсона, и Баха. Второй работал для меня, но для этого требуется, чтобы изображение присутствовало заранее. Я хотел что-то более динамичное, поэтому я объединил оба решения в один:

  • нарисуйте желаемый градиент на UIImage
  • , используя UIImage, чтобы установить цветовой паттерн

Результат работает, и на скриншоте ниже вы можете увидеть некоторые греческие символы, сделанные отлично. (Я также добавил штрих и тень поверх градиента).

iOS stylized UILabel, the big brown fox [/g2]

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

- (id)initWithFrame:(CGRect)frame text:(NSString *)aText {
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor clearColor];
        self.text = aText;

        self.textColor = [UIColor colorWithPatternImage:[self gradientImage]];

    }
    return self;
}

- (UIImage *)gradientImage
{
    CGSize textSize = [self.text sizeWithFont:self.font];
    CGFloat width = textSize.width;         // max 1024 due to Core Graphics limitations
    CGFloat height = textSize.height;       // max 1024 due to Core Graphics limitations

    // create a new bitmap image context
    UIGraphicsBeginImageContext(CGSizeMake(width, height));

    // get context
    CGContextRef context = UIGraphicsGetCurrentContext();       

    // push context to make it current (need to do this manually because we are not drawing in a UIView)
    UIGraphicsPushContext(context);                             

    //draw gradient    
    CGGradientRef glossGradient;
    CGColorSpaceRef rgbColorspace;
    size_t num_locations = 2;
    CGFloat locations[2] = { 0.0, 1.0 };
    CGFloat components[8] = { 0.0, 1.0, 1.0, 1.0,  // Start color
                            1.0, 1.0, 0.0, 1.0 }; // End color
    rgbColorspace = CGColorSpaceCreateDeviceRGB();
    glossGradient = CGGradientCreateWithColorComponents(rgbColorspace, components, locations, num_locations);
    CGPoint topCenter = CGPointMake(0, 0);
    CGPoint bottomCenter = CGPointMake(0, textSize.height);
    CGContextDrawLinearGradient(context, glossGradient, topCenter, bottomCenter, 0);

    CGGradientRelease(glossGradient);
    CGColorSpaceRelease(rgbColorspace); 

    // pop context 
    UIGraphicsPopContext();                             

    // get a UIImage from the image context
    UIImage *gradientImage = UIGraphicsGetImageFromCurrentImageContext();

    // clean up drawing environment
    UIGraphicsEndImageContext();

    return  gradientImage;
}

Я попытаюсь завершить этот подкласс UILabel и опубликовать его.

EDIT:

Класс выполнен, и он находится в моем хранилище GitHub . Читайте об этом здесь !

38
ответ дан Dimitris 22 August 2018 в 05:30
поделиться
  • 1
    Это единственный ответ, который работает с многострочным текстом, спасибо! – jjxtra 6 April 2014 в 06:43
  • 2
    Любой шанс обновить это до Swift 4? – J. Doe 13 September 2017 в 14:59

Я искал решение, и DotSlashSlash имеет ответ, спрятанный в одном из комментариев!

Для полноты ответа и простейшего решения:

UIImage *myGradient = [UIImage imageNamed:@"textGradient.png"];
myLabel.textColor   = [UIColor colorWithPatternImage:myGradient];
107
ответ дан Bach 22 August 2018 в 05:30
поделиться

Simplest Swift 3 Solution

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

let image = UIImage(named: "myGradient.png")!
label.textColor = UIColor.init(patternImage: image)
-1
ответ дан Ben Sullivan 22 August 2018 в 05:30
поделиться

SWIFT 3 +

Это решение основано на ответе @ Dimitris. Это расширение класса UILabel, которое создаст градиент над текстом метки в каждом переданном startColor и endColor. Расширение UILabel ниже:

extension UILabel {

    func applyGradientWith(startColor: UIColor, endColor: UIColor) -> Bool {

        var startColorRed:CGFloat = 0
        var startColorGreen:CGFloat = 0
        var startColorBlue:CGFloat = 0
        var startAlpha:CGFloat = 0

        if !startColor.getRed(&startColorRed, green: &startColorGreen, blue: &startColorBlue, alpha: &startAlpha) {
            return false
        }

        var endColorRed:CGFloat = 0
        var endColorGreen:CGFloat = 0
        var endColorBlue:CGFloat = 0
        var endAlpha:CGFloat = 0

        if !endColor.getRed(&endColorRed, green: &endColorGreen, blue: &endColorBlue, alpha: &endAlpha) {
            return false
        }

        let gradientText = self.text ?? ""

        let name:String = NSFontAttributeName
        let textSize: CGSize = gradientText.size(attributes: [name:self.font])
        let width:CGFloat = textSize.width
        let height:CGFloat = textSize.height

        UIGraphicsBeginImageContext(CGSize(width: width, height: height))

        guard let context = UIGraphicsGetCurrentContext() else {
            UIGraphicsEndImageContext()
            return false
        }

        UIGraphicsPushContext(context)

        let glossGradient:CGGradient?
        let rgbColorspace:CGColorSpace?
        let num_locations:size_t = 2
        let locations:[CGFloat] = [ 0.0, 1.0 ]
        let components:[CGFloat] = [startColorRed, startColorGreen, startColorBlue, startAlpha, endColorRed, endColorGreen, endColorBlue, endAlpha]
        rgbColorspace = CGColorSpaceCreateDeviceRGB()
        glossGradient = CGGradient(colorSpace: rgbColorspace!, colorComponents: components, locations: locations, count: num_locations)
        let topCenter = CGPoint.zero
        let bottomCenter = CGPoint(x: 0, y: textSize.height)
        context.drawLinearGradient(glossGradient!, start: topCenter, end: bottomCenter, options: CGGradientDrawingOptions.drawsBeforeStartLocation)

        UIGraphicsPopContext()

        guard let gradientImage = UIGraphicsGetImageFromCurrentImageContext() else {
            UIGraphicsEndImageContext()
            return false
        }

        UIGraphicsEndImageContext()

        self.textColor = UIColor(patternImage: gradientImage)

        return true
    }

}

И использование:

let text = "YAAASSSSS!"
label.text = text
if label.applyGradientWith(startColor: .red, endColor: .blue) {
    print("Gradient applied!")
}
else {
    print("Could not apply gradient")
    label.textColor = .black
}


SWIFT 2

class func getGradientForText(text: NSString) -> UIImage {

    let font:UIFont = UIFont(name: "YourFontName", size: 50.0)!
    let name:String = NSFontAttributeName
    let textSize: CGSize = text.sizeWithAttributes([name:font])
    let width:CGFloat = textSize.width         // max 1024 due to Core Graphics limitations
    let height:CGFloat = textSize.height       // max 1024 due to Core Graphics limitations

    //create a new bitmap image context
    UIGraphicsBeginImageContext(CGSizeMake(width, height))

    // get context
    let context = UIGraphicsGetCurrentContext()

    // push context to make it current (need to do this manually because we are not drawing in a UIView)
    UIGraphicsPushContext(context!)

    //draw gradient
    let glossGradient:CGGradientRef?
    let rgbColorspace:CGColorSpaceRef?
    let num_locations:size_t = 2
    let locations:[CGFloat] = [ 0.0, 1.0 ]
    let components:[CGFloat] = [(202 / 255.0), (197 / 255.0), (52 / 255.0), 1.0,  // Start color
                                (253 / 255.0), (248 / 255.0), (101 / 255.0), 1.0] // End color
    rgbColorspace = CGColorSpaceCreateDeviceRGB();
    glossGradient = CGGradientCreateWithColorComponents(rgbColorspace, components, locations, num_locations);
    let topCenter = CGPointMake(0, 0);
    let bottomCenter = CGPointMake(0, textSize.height);
    CGContextDrawLinearGradient(context, glossGradient, topCenter, bottomCenter, CGGradientDrawingOptions.DrawsBeforeStartLocation);

    // pop context
    UIGraphicsPopContext();

    // get a UIImage from the image context
    let gradientImage = UIGraphicsGetImageFromCurrentImageContext();

    // clean up drawing environment
    UIGraphicsEndImageContext();

    return  gradientImage;
}

Опоры @Dimitris

11
ответ дан Brandon A 22 August 2018 в 05:30
поделиться
  • 1
    Не работает, когда я помещаю его в ImageView, весь вид выглядит желтым и в нем нет текста ... – Bogdan Bogdanov 25 July 2016 в 12:48
  • 2
  • 3
    Вы правы @ J.Doe. Я обновил свой ответ с помощью решения для Swift 3+. Также я включил свой собственный поворот с расширением UILabel, который поместит градиент в UIColor и применит его к самой метке. Пожалуйста, дайте мне знать, есть ли другие проблемы. – Brandon A 13 September 2017 в 18:48
  • 4
    @BrandonA Я думаю, что это работает сейчас :) – J. Doe 16 September 2017 в 12:21
  • 5
    Мне это точно нужно :) – Nishu Priya 30 April 2018 в 11:10

Вот что я делаю в Swift 3

override func viewDidLoad() {
    super.viewDidLoad()
    timerLabel.textColor = UIColor(patternImage: gradientImage(size: timerLabel.frame.size, color1: CIColor(color: UIColor.green), color2: CIColor(color: UIColor.red), direction: .Left))
}

func gradientImage(size: CGSize, color1: CIColor, color2: CIColor, direction: GradientDirection = .Up) -> UIImage {

    let context = CIContext(options: nil)
    let filter = CIFilter(name: "CILinearGradient")
    var startVector: CIVector
    var endVector: CIVector

    filter!.setDefaults()

    switch direction {
    case .Up:
        startVector = CIVector(x: size.width * 0.5, y: 0)
        endVector = CIVector(x: size.width * 0.5, y: size.height)
    case .Left:
        startVector = CIVector(x: size.width, y: size.height * 0.5)
        endVector = CIVector(x: 0, y: size.height * 0.5)
    case .UpLeft:
        startVector = CIVector(x: size.width, y: 0)
        endVector = CIVector(x: 0, y: size.height)
    case .UpRight:
        startVector = CIVector(x: 0, y: 0)
        endVector = CIVector(x: size.width, y: size.height)
    }

    filter!.setValue(startVector, forKey: "inputPoint0")
    filter!.setValue(endVector, forKey: "inputPoint1")
    filter!.setValue(color1, forKey: "inputColor0")
    filter!.setValue(color2, forKey: "inputColor1")

    let image = UIImage(cgImage: context.createCGImage(filter!.outputImage!, from: CGRect(x: 0, y: 0, width: size.width, height: size.height))!)
    return image
}
3
ответ дан CodyMace 22 August 2018 в 05:30
поделиться

В примере, который вы предоставляете, используются частные функции рисования текста, к которым у вас нет доступа на iPhone. Автор дает пример того, как это сделать, используя публичный API в следующей записи . В его более позднем примере используется градиентное изображение для цвета текста. (К сожалению, похоже, что его блог с тех пор был удален, но см. Ответ Баха здесь для того подхода, который он использовал.)

Если вы все еще хотите нарисовать градиент для цвета текста в коде, это может быть сделано путем подкласса UILabel и переопределения -drawRect: чтобы в нем был такой код:

CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextTranslateCTM(context, 0.0f, self.bounds.size.height);
CGContextScaleCTM(context, 1.0f, -1.0f);

CGContextSelectFont(context, "Helvetica", 20.0f, kCGEncodingMacRoman);
CGContextSetTextDrawingMode(context, kCGTextClip);
CGContextSetTextPosition(context, 0.0f, round(20.0f / 4.0f));
CGContextShowText(context, [self.text UTF8String], strlen([self.text UTF8String]));

CGContextClip(context);

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

rgbColorspace = CGColorSpaceCreateDeviceRGB();
gradient = 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(context, gradient, topCenter, midCenter, 0);

CGGradientRelease(gradient);
CGColorSpaceRelease(rgbColorspace);         

CGContextRestoreGState(context);

Один из недостатков этого подхода заключается в том, что функции Core Graphics, которые я использую, не используют правильно отредактируйте текст в Юникоде.

Что делает код, он переворачивает контекст чертежа по вертикали (iPhone инвертирует обычную систему координат кварца для оси Y), устанавливает режим рисования текста, чтобы пересечь нарисованный текст с помощью обтравочный контур, зажимает область для рисования к тексту, а затем рисует градиент. Градиент будет заполнять только текст, а не фон.

Я попытался использовать метод NDString -drawAtPoint: для этого, который поддерживает Unicode, но все символы пробегали друг над другом, когда я менял текст mode к kCGTextClip.

14
ответ дан Community 22 August 2018 в 05:30
поделиться
  • 1
    спасибо за это :) Я просто использовал метод изображения образца label.textColor = [UIColor colorWithPatternImage: gradientImage; – DotSlashSlash 12 August 2009 в 21:37
  • 2
    Ссылка сломана .... – jjxtra 18 August 2012 в 04:57
  • 3
    – Brad Larson♦ 18 August 2012 в 14:24
  • 4
    @BradLarson Добро пожаловать. Спасибо за обновление ответа. – jjxtra 18 August 2012 в 19:37
  • 5
    Кажется, не работает с многострочным текстом – jjxtra 6 April 2014 в 06:44

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

0
ответ дан Ryan Detzel 22 August 2018 в 05:30
поделиться
  • 1
    yeh я сделал это, но он градиент заполняет текст, который он просматривает по всему виду – DotSlashSlash 12 August 2009 в 16:01
  • 2
    я имею в виду, что doesnt заполняет текст – DotSlashSlash 12 August 2009 в 16:01
Другие вопросы по тегам:

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