Uilabel: Background Dependent Color

UILabel: background dependent color

The easiest way is to create a UIView subclass that has a progress property and overwrites -drawRect:.

All the code you need is this:

- (void)drawRect:(CGRect)rect {

CGContextRef context = UIGraphicsGetCurrentContext();

// Set up environment.
CGSize size = [self bounds].size;
UIColor *backgroundColor = [UIColor colorWithRed:108.0/255.0 green:200.0/255.0 blue:226.0/255.0 alpha:1.0];
UIColor *foregroundColor = [UIColor whiteColor];
UIFont *font = [UIFont boldSystemFontOfSize:42.0];

// Prepare progress as a string.
NSString *progress = [NSString stringWithFormat:@"%d%%", (int)round([self progress] * 100)];
NSMutableDictionary *attributes = [@{ NSFontAttributeName : font } mutableCopy];
CGSize textSize = [progress sizeWithAttributes:attributes];
CGFloat progressX = ceil([self progress] * size.width);
CGPoint textPoint = CGPointMake(ceil((size.width - textSize.width) / 2.0), ceil((size.height - textSize.height) / 2.0));

// Draw background + foreground text
[backgroundColor setFill];
CGContextFillRect(context, [self bounds]);
attributes[NSForegroundColorAttributeName] = foregroundColor;
[progress drawAtPoint:textPoint withAttributes:attributes];

// Clip the drawing that follows to the remaining progress' frame.
CGContextSaveGState(context);
CGRect remainingProgressRect = CGRectMake(progressX, 0.0, size.width - progressX, size.height);
CGContextAddRect(context, remainingProgressRect);
CGContextClip(context);

// Draw again with inverted colors.
[foregroundColor setFill];
CGContextFillRect(context, [self bounds]);
attributes[NSForegroundColorAttributeName] = backgroundColor;
[progress drawAtPoint:textPoint withAttributes:attributes];

CGContextRestoreGState(context);
}

- (void)setProgress:(CGFloat)progress {
_progress = fminf(1.0, fmaxf(progress, 0.0));
[self setNeedsDisplay];
}

You can expand the class as needed with properties for background color, text color, font, etc.

iOS UILabel use negative background color as text color

If I were to do this I would probably create a custom UIView class with an API similar to UILabel (with just the parts I needed) plus a property to indicate what portion of the text should be reversed.

Then I would implement the drawRect: method to draw the text twice using two different clipping regions. For each half I would set the proper colors for the text and background fill.

It's possible this could be done by subclassing UILabel with the one additional property plus the custom drawRect: method.

Changing the background color of a UILabel within a UITableViewCell

Your code snippet works fine for me, but it must be done after the cell has been added to the table and shown, I believe. If called from the initWithFrame:reuseIdentifier:, you'll get an exception, as the UILabel subview has not yet been created.

Probably the best solution is to add your own UILabel, configured to your standards, rather than relying on this (very rickety) path to the built-in one.

Inverse UIlabel text color when its frame intersects an UIView

Good puzzle! Here's what I would do:

  1. Two UIViews. Let's call one the background and the other the progressBar. progressBar is stacked on top of background with the same origin on their common superview.
  2. They both have a UILabel as subview, and both labels at the same origin relative to their parent. background has a dark backgroundColor and it's label has light textColor and the progress view has things the other way around.
  3. progressBar has a narrower frame width than background and has clipsToBounds==YES

The trick is, with the views' origins the same and the labels' origins the same, and clipsToBounds on the top view, everything is going to look right.

Drop those two views into a new UIView subclass called ReallyCoolProgressView, and give it one public method:

-(void)setProgress:(float)progress progress is a number from 0.0 to 1.0. The method scales the progressBar width and sets both label's text @"Progress %f", progress*100

UIProgressBar: How to Change UILabel Color according to Background Color

If you want an answer in swift, here is the code(changed from objc to swift) from this post, which should be exactly what you need:

This is swift 4

class MyProgressView: UIView {

var progress: CGFloat = 0 {
didSet {
setNeedsDisplay()
}
}

override func draw(_ rect: CGRect) {
let context = UIGraphicsGetCurrentContext()

// Set up environment.
let size = bounds.size
let backgroundColor = UIColor(red: 108/255, green: 200/255, blue: 226/255, alpha: 1)
let foregroundColor = UIColor.white
let font = UIFont.boldSystemFont(ofSize: 42)

// Prepare progress as a string.
let progress = NSString(format: "%d%%", Int(round(self.progress * 100))) // this cannot be a String because there are many subsequent calls to NSString-only methods such as `size` and `draw`
var attributes: [NSAttributedString.Key: Any] = [.font: font]
let textSize = progress.size(withAttributes: attributes)
let progressX = ceil(self.progress * size.width)
let textPoint = CGPoint(x: ceil((size.width - textSize.width) / 2), y: ceil((size.height - textSize.height) / 2))

// Draw background + foreground text
backgroundColor.setFill()
context?.fill(bounds)
attributes[.foregroundColor] = foregroundColor
progress.draw(at: textPoint, withAttributes: attributes)

// Clip the drawing that follows to the remaining progress's frame
context?.saveGState()
let remainingProgressRect = CGRect(x: progressX, y: 0, width: size.width - progressX, height: size.height)
context?.addRect(remainingProgressRect)
context?.clip()

// Draw again with inverted colors
foregroundColor.setFill()
context?.fill(bounds)
attributes[.foregroundColor] = backgroundColor
progress.draw(at: textPoint, withAttributes: attributes)

context?.restoreGState()
}
}

Tested with playground

UIAppearance of UILabel whithin UICollectionViewCell - selected/unselected

Finally found a Workaround for this issue. I post my solution it may help someone.

first I define the color for both textColor and highlightedTextColor

UILabel.appearance(whenContainedInInstancesOf: [MyCollectionViewCell.self]).textColor = colorScheme.color1
UILabel.appearance(whenContainedInInstancesOf: [MyCollectionViewCell.self]).highlightedTextColor = colorScheme.color2

Then in MyCollectionViewCell I "bind" the isSelected to UILabel isHighlighted :

class MyCollectionViewCell: UICollectionViewCell {

@IBOutlet weak var myLabel: UILabel!

override var isSelected: Bool {
didSet {
self.myLabel.isHighlighted = isSelected
}
}
}

Works flawlessly.

Hope this can help someone



Related Topics



Leave a reply



Submit