The below code to hide background of UIsearchBar works fine till iOs4.2 but not in iOS4.3 or later.
for (UIView *subview in searchBar.subviews) {
if ([subview isKindOfClass:NSClassFromString(#"UISearchBarBackground")]) {
[subview removeFromSuperview];
break;
}
}
In iOS 7 another UIView was added to the UISearchBar, here is the solution for iOS 7:
UIView *vw = [yourSearchBar.subviews objectAtIndex:0];
for (id img in vw.subviews) {
if ([img isKindOfClass:NSClassFromString(#"UISearchBarBackground")]) {
[img removeFromSuperview];
}
}
You could also do the following (also works in iOS 7):
[yourSearchBar setBackgroundImage:[UIImage new]];
[yourSearchBar setTranslucent:YES];
Their is no issue for this code ....but also giving you a alternate solution , replace code of for loop to
[[[searchBar subviews] objectAtIndex:0] removeFromSuperview];
I know it is late but for reference here it is
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
UIGraphicsBeginImageContext(rect.size);
UIImage *image = nil;
CGContextRef context = UIGraphicsGetCurrentContext();
if (context) {
CGContextSetFillColorWithColor(context, [UIColor clearColor].CGColor);
CGContextFillRect(context, rect);
image= UIGraphicsGetImageFromCurrentImageContext();
}
UIGraphicsEndImageContext();
dispatch_async(dispatch_get_main_queue(), ^{
self.backgroundImage = image;
});
});
Related
I just create my own custom button that seem like iOS6 and earlier buttons but on iOS7 my CustomButton turn transparent when highlighted.
I have try to set property adjustsImageWhenHighlighted at NO but nothing change, [self setAlpha:1.f] doesn't work either.
Following, my init method:
-(void) baseInit:(CGRect)frame :(CGFloat *)colorsNormal :(CGFloat *)colorsHighlighted :(CGFloat *)colorsDisabled
{
self.layer.borderWidth=1.0f;
self.layer.borderColor=[[UIColor colorWithRed:0.67f green:0.67f blue:0.67f alpha:1.0f] CGColor];
self.layer.cornerRadius=7.0f;
self.clipsToBounds = YES;
UIImage *image = [self generateUIImageWithGradient:frame :colorsNormal];
[self setBackgroundImage:image forState:UIControlStateNormal];
[self setTitleColor:[UIColor colorWithRed:0.22f green:0.33f blue:0.53f alpha:1.0f] forState:UIControlStateNormal];
UIImage *image2 = [self generateUIImageWithGradient:frame :colorsHighlighted];
[self setBackgroundImage:image2 forState:UIControlStateHighlighted];
[self setTitleColor:[UIColor colorWithRed:1.0f green:1.0f blue:1.0f alpha:1.0f] forState:UIControlStateHighlighted];
UIImage *image3 = [self generateUIImageWithGradient:frame :colorsDisabled];
[self setBackgroundImage:image3 forState:UIControlStateDisabled];
}
-(id) generateUIImageWithGradient:(CGRect)frame :(CGFloat *)colors
{
CGSize size = CGSizeMake(frame.size.width, frame.size.height);
UIGraphicsBeginImageContextWithOptions(size, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
size_t gradientNumberOfLocations = 2;
CGFloat gradientLocations[2] = {0.0, 1.0};
CGGradientRef gradient = CGGradientCreateWithColorComponents(colorspace, colors, gradientLocations, gradientNumberOfLocations);
CGContextDrawLinearGradient(context, gradient, CGPointMake(0, 0), CGPointMake(0, size.height), 0);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
CGGradientRelease(gradient);
CGColorSpaceRelease(colorspace);
UIGraphicsEndImageContext();
return image;
}
And my method call :
CGFloat colorsNormal [] = {1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f};
CGFloat colorsHighlighted [] = {0.03f,0.55f,0.97f,1.0f,0.0f,0.37f,0.90f,1.0f};
CGFloat colorsDisabled [] = {1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f};
[self baseInit:rect :colorsNormal :colorsHighlighted :colorsDisabled];
That work like a charm on iOS6 and NormalState work on iOS7.
Thanks for your help
Set the button type property to UIButtonTypeCustom seem to work. Problem solved.
I'm having this issue when trying to overlay a UIButton's Image with a color.
The overlay color is appearing underneath the Image.
Here is the code that I have in my drawRect method (I have subclassed UIButton):
(void)drawRect:(CGRect)rect
{
CGRect bounds = self.imageView.bounds;
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);
CGContextTranslateCTM(context, 0.0, self.imageView.image.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextClipToMask(context, bounds, [self.imageView.image CGImage]);
CGContextFillRect(context, bounds);
}
Any ideas on how to get the red color on top of the Image?
Succeeded with this hacky code:
- (void)drawRect:(CGRect)rect
{
UIImage* img = [self imageForState:UIControlStateNormal];
[self setImage:nil forState:UIControlStateNormal];
CGRect bounds = self.imageView.bounds;
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [UIColor colorWithRed:1 green:0 blue:0 alpha:0.2].CGColor);
CGContextDrawImage(context, bounds, img.CGImage);
CGContextFillRect(context, bounds);
}
It seems the image is drawn after drawRect so unless you make it nil, it goes on top of whatever you draw there.
This is solution is not final. I'll edit it with what I get to next.
EDIT: The right solution is to add a semi-transparent UIView on top of the image like this:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
UIView* tintView = [[UIView alloc] initWithFrame:self.bounds];
tintView.backgroundColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:0.2];
tintView.userInteractionEnabled = NO;
[self addSubview:tintView];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
UIView* tintView = [[UIView alloc] initWithFrame:self.bounds];
tintView.backgroundColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:0.2];
tintView.userInteractionEnabled = NO;
[self addSubview:tintView];
}
return self;
}
Note: you should do this in your UIButton subclass.
I would like to call a method which takes a screenshot and then load this screenshot as a subview. I am using Apples sample code on how to take a screen shot (see below) and was trying to use the result (an image) in my code. However, I don't really know how to get the image from the method into my code. This is what I tried; it's obviously wrong, but it's all I could come up with:
// Test Screenshot:
screenShot = [UIImage screenshot]; // THIS DOESN'T WORK
screenShotView = [[UIImageView alloc] initWithImage:screenShot];
[screenShotView setFrame:CGRectMake(0, 0, 320, 480)];
[self.view addSubview:screenShotView];
And this is Apple's sample code for the method:
- (UIImage*)screenshot
{
NSLog(#"Shot");
// Create a graphics context with the target size
// On iOS 4 and later, use UIGraphicsBeginImageContextWithOptions to take the scale into consideration
// On iOS prior to 4, fall back to use UIGraphicsBeginImageContext
CGSize imageSize = [[UIScreen mainScreen] bounds].size;
if (NULL != UIGraphicsBeginImageContextWithOptions)
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
else
UIGraphicsBeginImageContext(imageSize);
CGContextRef context = UIGraphicsGetCurrentContext();
// Iterate over every window from back to front
for (UIWindow *window in [[UIApplication sharedApplication] windows])
{
if (![window respondsToSelector:#selector(screen)] || [window screen] == [UIScreen mainScreen])
{
// -renderInContext: renders in the coordinate space of the layer,
// so we must first apply the layer's geometry to the graphics context
CGContextSaveGState(context);
// Center the context around the window's anchor point
CGContextTranslateCTM(context, [window center].x, [window center].y);
// Apply the window's transform about the anchor point
CGContextConcatCTM(context, [window transform]);
// Offset by the portion of the bounds left of and above the anchor point
CGContextTranslateCTM(context,
-[window bounds].size.width * [[window layer] anchorPoint].x,
-[window bounds].size.height * [[window layer] anchorPoint].y);
// Render the layer hierarchy to the current context
[[window layer] renderInContext:context];
// Restore the context
CGContextRestoreGState(context);
}
}
// Retrieve the screenshot image
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
Any help would be very much appreciated! Thanks.
EDIT: This is the viewDidLoad method in which I create a TextView and then try to capture a screen shot of it:
- (void)viewDidLoad {
// Setup TextView:
NSString* someText = #"Some Text";
CGRect frameText = CGRectMake(0, 0, 320, 480);
aTextView = [[UITextView alloc] initWithFrame:frameText];
aTextView.text = someText;
[self.view addSubview:aTextView];
// Test Screenshot:
screenShotView = [[UIImageView alloc] initWithImage:[self screenshot]];
[screenShotView setFrame:CGRectMake(10, 10, 200, 200)];
[self.view addSubview:screenShotView];
[self.view bringSubviewToFront:screenShotView];
[super viewDidLoad];
}
To use the image just change this line
screenShot = [UIImage screenshot];
To
screenShot = [self screenshot];
Edit: Check to see if the [self screenshot] returns a valid image or nil.
- (void)viewDidLoad {
// Setup TextView:
NSString* someText = #"Some Text";
CGRect frameText = CGRectMake(0, 0, 320, 480);
aTextView = [[UITextView alloc] initWithFrame:frameText];
aTextView.text = someText;
[self.view addSubview:aTextView];
// Test Screenshot:
UIImage *screenShotImage = [self screenShot];
if(screenShot){
screenShotView = [[UIImageView alloc] initWithImage:screenShotImage];
[screenShotView setFrame:CGRectMake(10, 10, 200, 200)];
[self.view addSubview:screenShotView];
[self.view bringSubviewToFront:screenShotView];
}else
NSLog(#"Something went wrong in screenShot method, the image is nil");
[super viewDidLoad];
}
Hi I want to change the UIButton background color which user Tap on the button.
I am showing background color using gradient, when user tap I need to change the gradient color.
[btn setTitle: #"Next" forState:UIControlStateNormal];
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = btn.bounds;
gradient.cornerRadius = 10.0f;
locations = [[NSArray alloc] initWithObjects: 0.0f, 0.0f, 0.0f,0.0f, nil];
[gradient setLocations:locations];
colorNext = [[NSArray alloc] initWithObjects:…., nil];
gradient.colors = colorNext;
[locations release];
[btn.layer insertSublayer:gradient atIndex:0];
btn.titleLabel.textColor = [UIColor blackColor];
Changing the internal layer hierarchy of a UIButton is not recommended since it may break in a future update of the iOS. Also, it may cause Apple to reject your application. A better solution would be to create a button subclass. Here is an example of how to do it:
#interface MyButton : UIButton
#end
#implementation MyButton
- (id)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame])
{
[self addObserver:self forKeyPath:#"highlighted" options:NSKeyValueObservingOptionNew context:NULL];
}
return self;
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect
{
[super drawRect:rect];
if (self.highlighted == YES)
{
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
const CGFloat *topGradientColorComponents = CGColorGetComponents([UIColor whiteColor].CGColor);
const CGFloat *bottomGradientColorComponents = CGColorGetComponents([UIColor blackColor].CGColor);
CGFloat colors[] =
{
topGradientColorComponents[0], topGradientColorComponents[1], topGradientColorComponents[2], topGradientColorComponents[3],
bottomGradientColorComponents[0], bottomGradientColorComponents[1], bottomGradientColorComponents[2], bottomGradientColorComponents[3]
};
CGGradientRef gradient = CGGradientCreateWithColorComponents(rgb, colors, NULL, sizeof(colors) / (sizeof(colors[0]) * 4));
CGColorSpaceRelease(rgb);
CGContextDrawLinearGradient(ctx, gradient, CGPointMake(0, 0), CGPointMake(0, self.bounds.size.height), 0);
CGGradientRelease(gradient);
}
else
{
// Do custom drawing for normal state
}
}
- (void)dealloc
{
[self removeObserver:self forKeyPath:#"highlighted"];
[super dealloc];
}
#end
You may need to modify it a bit to get it to do what you want but I think you get the basic idea.
Try this:
[Button addTarget:self action:#selector(doSomething:) forControlEvents:UIControlEventTouchUpInside];
[Button addTarget:self action:#selector(setBgColorForButton:) forControlEvents:UIControlEventTouchDown];
[Button addTarget:self action:#selector(clearBgColorForButton:) forControlEvents:UIControlEventTouchDragExit];
-(void)setBgColorForButton:(UIButton*)sender
{
[sender setBackgroundColor:[UIColor blackColor]];
}
-(void)clearBgColorForButton:(UIButton*)sender
{
[sender setBackgroundColor:[UIColor redColor]];
}
-(void)doSomething:(UIButton*)sender
{
double delayInSeconds = 0.3;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[sender setBackgroundColor:[UIColor redColor]];
});
//do something
}
You can use this method to create and solid UIImage of specified color and then apply it to your button. I've made a category for UIImage to do this.
+ (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size
{
UIGraphicsBeginImageContext(size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, color.CGColor);
CGContextFillRect(context, (CGRect){.size = size});
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
+ (UIImage *)imageWithColor:(UIColor *)color
{
return [UIImage imageWithColor:color size:CGSizeMake(1, 1)];
}
Usage:
[button setBackgroundImage:[UIImage imageWithColor:[UIColor redColor]]
forState:UIControlStateNormal];
As Matthias pointed out, you can safely use 1x1 image for your button background – it will be stretched to fill the button.
I found this AYUIButton on GitHub and it works perfectly :)
Here is sample code:
[btn setBackgroundColor:[UIColor redColor] forState:UIControlStateNormal];
[btn setBackgroundColor:[UIColor blueColor] forState:UIControlStateHighlighted];
When you set the TintColor of the Button it works when highlighted
[YourButton setTintColor:[UIColor color]];
Swift
Extension for UIButton that let you specify background color for each state:
https://github.com/acani/UIButtonBackgroundColor
Please note that for iphone 6 plus you should change the following, inside the extension in the .swift class, that will fix it for all the versions:
//let rect = CGRect(x: 0, y: 0, width: 0.5, height: 0.5) comment this line
let rect = CGRect(x: 0, y: 0, width: 1, height: 1)
I have applied following code to my application to change the navigation bar image.
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigationController.navigationBar setTintColor:[UIColor blackColor]];
[self setNavigationBarTitle];
}
-(void)setNavigationBarTitle {
UIView *aViewForTitle=[[[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 45)] autorelease];
UIImageView *aImg=[[UIImageView alloc] initWithFrame:CGRectMake(-8, 0, 320, 45)];
aImg.image=[UIImage imageNamed:#"MyTabBG.png"];
[aViewForTitle addSubview:aImg]; [aImg release];
UILabel *lbl=[[[UILabel alloc] initWithFrame:CGRectMake(0, 0, 305, 45)] autorelease];
lbl.backgroundColor=[UIColor clearColor]; lbl.font=[UIFont fontWithName:#"Trebuchet MS" size:22];
lbl.shadowColor=[UIColor blackColor]; [lbl setShadowOffset:CGSizeMake(1,1)];
lbl.textAlignment=UITextAlignmentCenter; lbl.textColor=[UIColor whiteColor]; lbl.text=#"Mobile Tennis Coach Overview";
[aViewForTitle addSubview:lbl];
[self.navigationItem.titleView addSubview:aViewForTitle];
}
See following images. You can see the problem that I am facing.
Each view controller of my application has above methods to set the navigation bar background.
How ever, when I push a new view controller to my application. Back button will be appear.
I need back button to be appear. But The image should be behind back button.
Now I am little confused here.
Can you help me regarding this?
Thanks in advance for sharing your knowledge with me.
Thanks a lot.
After an annoying night, I found a slight tweak to this, if you use drawLayer. With drawRect, when you play a video, or youtube video, the navbar is replaced with the image. And I read a few posts that this caused their app to be rejected.
#implementation UINavigationBar (UINavigationBarCategory)
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
if([self isMemberOfClass:[UINavigationBar class]])
{
UIImage *image = [UIImage imageNamed:#"navBarBackground.png"];
CGContextClip(ctx);
CGContextTranslateCTM(ctx, 0, image.size.height);
CGContextScaleCTM(ctx, 1.0, -1.0);
CGContextDrawImage(ctx,
CGRectMake(0, 0, self.frame.size.width, self.frame.size.height), image.CGImage);
}
else
{
[super drawLayer:layer inContext:ctx];
}
}
#end
If this article is accurate, all should be fine with this approach:
http://developer.apple.com/iphone/library/qa/qa2009/qa1637.html
The short answer is that modifying the structure of the UINavigationBar is not supported by Apple. They really do not want you do be doing what you are trying to do. That is what is causing the issue you are seeing.
Please file a radar requesting this feature so that it can get enough attention to be officially added at some point.
Having said that, to solve the issue you can add a category to UINavigationBar with a -drawRect: method and draw the background image in that method. Something like this will work:
- (void)drawRect:(CGRect)rect
{
static UIImage *image;
if (!image) {
image = [UIImage imageNamed: #"HeaderBackground.png"];
if (!image) image = [UIImage imageNamed:#"DefaultHeader.png"];
}
if (!image) return;
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextDrawImage(context, CGRectMake(0, 0, self.frame.size.width, self.frame.size.height), image.CGImage);
}