I'm trying to set the foreground/tintColor of a UISegmentedControl to a horizontal gradient. I want the gradient to extend across the control and appropriately adjust when each segment is clicked. See image below:
I've tried setting the tintColor using the stackoverflow solution found here, but using colorWithPattern doesn't seem to work when I change it to be horizontal:
Here's what I'm using now:
UIView* test2 = [[UIView alloc] initWithFrame:CGRectMake(10, 60, 200, 25)];
test2.backgroundColor = [self gradientFromColor:[UIColor redColor] toColor:[UIColor greenColor] withWidth:test2.frame.size.width];
[self.view addSubview:test2];
UISegmentedControl *test = [[UISegmentedControl alloc] initWithItems:#[#"one", #"two"]];
test.frame = CGRectMake(10, 100, 200, 25);
test.tintColor = [self gradientFromColor:[UIColor redColor] toColor:[UIColor greenColor] withWidth:test.frame.size.width];
[self.view addSubview:test];
...
- (UIColor*) gradientFromColor:(UIColor*)c1 toColor:(UIColor*)c2 withWidth:(int)width{
CGSize size = CGSizeMake(width, 1);
UIGraphicsBeginImageContextWithOptions(size, NO, 1);
CGContextRef context = UIGraphicsGetCurrentContext();
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
NSArray* colors = [NSArray arrayWithObjects:(id)c1.CGColor, (id)c2.CGColor, nil];
CGGradientRef gradient = CGGradientCreateWithColors(colorspace, (CFArrayRef)colors, NULL);
CGContextDrawLinearGradient(context, gradient, CGPointMake(0, 0), CGPointMake(width, 0), 0);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
CGGradientRelease(gradient);
CGColorSpaceRelease(colorspace);
UIGraphicsEndImageContext();
return [UIColor colorWithPatternImage:image];
}
I'm thinking I need to do some work with masking but I've been having trouble getting it to work.
Related
How can I call this function?
I am trying to call this function from -viewDidLoad.
I tried [circularImageWithImage(imageView.image, myclor, 0.2)];
static UIImage *circularImageWithImage(UIImage *inputImage,
UIColor *borderColor,
CGFloat borderWidth)
{
CGRect rect = (CGRect){ .origin=CGPointZero, .size=inputImage.size };
UIGraphicsBeginImageContextWithOptions(rect.size, NO, inputImage.scale); {
// Fill the entire circle with the border color.
[borderColor setFill];
[[UIBezierPath bezierPathWithOvalInRect:rect] fill];
// Clip to the interior of the circle (inside the border).
CGRect interiorBox = CGRectInset(rect, borderWidth, borderWidth);
UIBezierPath *interior = [UIBezierPath bezierPathWithOvalInRect:interiorBox];
[interior addClip];
[inputImage drawInRect:rect];
}
UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return outputImage;
}
You can try with this code.
UIImage *image = [UIImage imageNamed:#"yourImage.png"];
UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];//set your frame
//imageView.center = self.view.center;
UIImage *modifiedImage = circularImageWithImage(image, [UIColor redColor], 1.2);//border width >= 1.0 is better. Otherwise you may not see this
imageView.image = modifiedImage;
[self.view addSubview:imageView];
UIImage *sample = circularImageWithImage(imageView.image, myclor, 0.2);
In my application delegate's didFinishLaunchingWithOptions function, I try to customize the appearance of my navigation bar.
[UINavigationBar appearance].translucent = NO;
[[UINavigationBar appearance]
setBackgroundImage:[UIImage
imageWithColor:[UIColor whiteColor]
size:CGSizeMake(1.0f, 1.0f)
]
forBarMetrics:UIBarMetricsDefault
];
[UINavigationBar appearance].shadowImage = [UIImage
imageWithColor:[UIColor redColor]
size:CGSizeMake(0.5f, 0.5f)
];
I expect a 1px tall opaque red shadow. Instead I am given a 2px tall translucent red shadow. How can make it appear exactly as I want it to? I've done the analogous appearance settings to UITabBar. It, on the other hand, behaves nicely.
The category function that creates dynamic images is defined as so:
+ (UIImage*)imageWithColor:(UIColor *)color size:(CGSize)size
{
CGRect rect = CGRectMake(0.0f, 0.0f, size.width, size.height);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
You need to create a graphics context that is retina-aware :
let pixelScale = UIGraphicsBeginImageContextWithOptions(fillRect.size, false, UIScreen.main.scale)
After that, your shadow image will become 1 physical pixel tall.
Here's full code:
extension UIImage {
static func imageWithColor(color: UIColor) -> UIImage {
let pixelScale = UIScreen.main.scale
let pixelSize = 1 / pixelScale
let fillSize = CGSize(width: pixelSize, height: pixelSize)
let fillRect = CGRect(origin: CGPoint.zero, size: fillSize)
UIGraphicsBeginImageContextWithOptions(fillRect.size, false, pixelScale)
let graphicsContext = UIGraphicsGetCurrentContext()
CGContextSetFillColorWithColor(graphicsContext, color.CGColor)
CGContextFillRect(graphicsContext, fillRect)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
}
On GitHub:
https://github.com/salutis/swift-image-with-color
Uh...is this what you want?
In my view controller, I simply added a UIView with 1 pixel height and an offset of 44pixels:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.view.backgroundColor = [UIColor whiteColor];
[self setupNavBar];
}
-(void)setupNavBar
{
self.navigationItem.title = #"Contacts";
CGRect applicationFrame = [[UIScreen mainScreen] applicationFrame];
UIView *bar = [[UIView alloc] initWithFrame:CGRectMake(0, 44, applicationFrame.size.width, 1.0)];
bar.backgroundColor = [UIColor redColor];
[self.navigationController.navigationBar addSubview:bar];
}
You can change the color to whatever you want.
I am trying to show text above CALayer but somehow I am not able to achieve it. I have used following code:
- (void)drawRect:(CGRect)rect
{
self.layer.sublayers = nil;
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSaveGState(ctx);
// Code to show grid lines clipped
CGRect overallRectForBarItem = CGRectMake(20, 20, 176, 35);
CAShapeLayer *barItemShape = [CAShapeLayer layer];
barItemShape.frame = overallRectForBarItem;
barItemShape.path = [UIBezierPath bezierPathWithRect:overallRectForBarItem].CGPath;
barItemShape.strokeColor = [UIColor lightGrayColor].CGColor;
barItemShape.fillColor = [UIColor lightGrayColor].CGColor;
[self.layer addSublayer:barItemShape];
[self drawTextForBarItem:#"TESTING" inRect:CGRectMake(100, 40, 35, 0)];
// Other code clipped
CGContextRestoreGState(ctx);
}
-(void) drawTextForBarItem:(NSString*)barItemTitle inRect:(CGRect)rect
{
float actualFontSize = 14.0;
UIFont *font = [ISUtility getSystemFont:actualFontSize];
CGSize size = [barItemTitle sizeWithFont:font];
NSMutableParagraphStyle *paragraphStyle = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease];
paragraphStyle.lineBreakMode = NSLineBreakByTruncatingTail;
paragraphStyle.alignment = NSTextAlignmentRight;
[barItemTitle drawInRect:CGRectMake(rect.origin.x, rect.origin.y - size.height/2, rect.size.width, size.height) withAttributes:#{NSFontAttributeName:font, NSForegroundColorAttributeName:[UIColor blueColor], NSParagraphStyleAttributeName:paragraphStyle}];
}
Following is the screen shot of simulator.
I have also tried zPosition but no use.
barItemShape.zPosition = -1000;
The most possible cause of you issue is that you creating CGContextRef but adding sublayer when you need to draw lightgray rectangle. I think, that it would be more consistant to draw your rectange with CoreGraphics functions and that draw your text.
To be more detailed, it seems that you drawing text in current layer but adding sublayer that will be above your text.
For instance, you can use this code to give it a try:
UIColor * redColor = [UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:1.0];
CGContextSetFillColorWithColor(context, redColor.CGColor);
CGContextFillRect(context, self.bounds);
I need to put a text over an image in iPhone. It's like the Eurosport iPhone app.
(source: mzstatic.com)
In the same way I need to put a text in my app. How can I do this?
Thanks.
I found two ways
1:
UIImageView *imageView = [[UIImageView alloc] init];
imageView.frame = CGRectMake(0, 25, 200, 200);
imageView.image = [UIImage imageNamed:#"Choice set.png"];
UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 20)];
myLabel.text = #"Hello There";
myLabel.textColor = [UIColor whiteColor];
myLabel.backgroundColor = [UIColor blueColor];
[imageView addSubview:myLabel];
[self.view addSubview:imageView];
[imageView release];
[myLabel release];
2:
Add text to UIImage
-(UIImage *)addText:(UIImage *)img text:(NSString *)text1{
int w = img.size.width;
int h = img.size.height;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, w, h, 8, 4 * w, colorSpace, kCGImageAlphaPremultipliedFirst);
CGContextDrawImage(context, CGRectMake(0, 0, w, h), img.CGImage);
char* text= (char *)[text1 cStringUsingEncoding:NSASCIIStringEncoding];
CGContextSelectFont(context, "Arial",20, kCGEncodingMacRoman);
CGContextSetTextDrawingMode(context, kCGTextFill);
CGContextSetRGBFillColor(context, 0, 0, 0, 1);
CGContextShowTextAtPoint(context,10,10,text, strlen(text));
CGImageRef imgCombined = CGBitmapContextCreateImage(context);
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
UIImage *retImage = [UIImage imageWithCGImage:imgCombined];
CGImageRelease(imgCombined);
return retImage;
}
then call
UIImage *image = [UIImage imageNamed:#"myimage.png"];
imageView.image = [self addText:image text:#"Hello there"];
Just simple make label with clear background.
yourLabel.backgroundColor = [UIColor clearColor];
I am using method described here to set a gradient background for vanilla UIView instance without creating a subclass. However the view comes out completely black. Here's my code:
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 315.0f, 44.0f)];
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, 315.0, 44.0f, 8, 4 * 315, colorSpace, kCGImageAlphaNoneSkipFirst);
// Colors only for debugging purposes
CGColorRef startColor = (__bridge CGColorRef)[UIColor greenColor];
CGColorRef endColor = (__bridge CGColorRef)[UIColor redColor];
CFMutableArrayRef colors = CFArrayCreateMutable(kCFAllocatorDefault, 2, &kCFTypeArrayCallBacks);
CFArrayAppendValue(colors, startColor);
CFArrayAppendValue(colors, endColor);
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, colors, (const CGFloat []){0.25f, 0.75f});
CGContextDrawLinearGradient(context, gradient, CGPointZero, CGPointMake(0.0f, 44.0f), 0);
CGImageRef cgImage = CGBitmapContextCreateImage(context);
UIImage *backgroundGradient = [UIImage imageWithCGImage:cgImage];
[view setBackgroundColor:[UIColor colorWithPatternImage:backgroundGradient]];
CFRelease(colors);
CGGradientRelease(gradient);
CGImageRelease(cgImage);
CGColorSpaceRelease(colorSpace);
CGContextRelease(context);
return view;
I believe something might be wrong with the allocation of context since the created images are returned of desired size (315x44). What did I miss? What else can I check that would help me debug this problem?
That's not how you get a CGColorRef you need to do
[UIColor redColor].CGColor