I want to use an image of size 27x27 with the center 1 pixel stretchable as the backgroundImage of an UIButton. Here is my code:
[button setBackgroundImage:[UIImage imageNamed:#"button_image"] forState:UIControlStateNormal];
button.frame = CGRectMake(0.f, 0.f, 27.f, 27.f);
button.contentStretch = CGRectMake(13.f/27.f, 13.f/27.f, 1.f/27.f, 1.f/27.f);
[button setTitle:NSLocalizedString(#"long title", #"long title") forState:UIControlStateNormal];
[button sizeToFit];
CGRect buttonFrame = button.frame;
buttonFrame.size.width += 18.f * 2;
button.frame = buttonFrame;
But the result is no different from that without setting contentStretch at all.
So how to correctly use contentStretch to achieve what I want?
Please don't tell me again and again that I can achieve the same effect with stretchableImageWithLeftCapWidth:topCapHeight:. I know that and it's apparently not what I'm asking for. I just want to know how to properly use contentStretch. Thanks.
One issue I see is that you're dividing using integer division. 1 / 27 is equal to 0. 1.0 / 27.0 is equal to 0.037...
If all you want is a stretchable background on your button, check out stretchableImageWithLeftCapWidth:topCapHeight: on UIImage. Create the stretchable image that way, then set it to the background of your button.
I don't know the special behaviour with UIButtons (I'd also suggest to use stretchableImages there as it is a compound view). However, if you want to use contentStretch you could do so on an UIView given your data this was:
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0,0,100,100)];
view.layer.contents = (id)[[UIImage imageNamed:#"button_image"] CGImage];
view.contentStretch = CGRectMake(13./27., 13./27., 1./27., 1./27.);
This should be enough to have a UIView with a stretchable background.
Use -[UIImage stretchableImageWithLeftCapWidth:topCapHeight:].
I put this in the init method of a subclass of UIView:
// Add errorBackground & errorLabel.
rect.size.height = 26.0f;
errorBackground = [[UIImageView alloc] initWithFrame:rect];
errorBackground.image = [[UIImage imageNamed:#"ErrorBubble.png"]
stretchableImageWithLeftCapWidth:13 topCapHeight:0];
UILabel *errorLabel = [[UILabel alloc] initWithFrame:
CGRectMake(0.0f, 0.0f, rect.size.width, rect.size.height)];
errorLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth;
errorLabel.backgroundColor = [UIColor clearColor];
errorLabel.textAlignment = UITextAlignmentCenter;
errorLabel.font = [UIFont systemFontOfSize:14.0f];
errorLabel.text = #"1 Failed Passcode Attempt";
errorLabel.textColor = [UIColor whiteColor];
errorLabel.shadowColor = [UIColor blackColor];
errorLabel.shadowOffset = CGSizeMake(0.0f, -1.0f);
[errorBackground addSubview:errorLabel];
[errorLabel release];
[self addSubview:errorBackground];
ErrorBubble.png:
ErrorBubble#2x.png:
Unsatisfying but simple answer:
You can't, until Apple fixes this. IMO it's a long outstanding and very annoying bug.
The UIButton implementation consists of a couple of subviews, and the (internal) background view does not seem to reflect the settings done on the UIButton view.
Related
Could any one help me i want to add same image multiple times horizontally with same height and width. Important thing is i am creating image view dynamically i want to use same image view for all images! This is image i want to make horizontally like this but only one row needed like this.
You could achieve this by using stretchableImageWithLeftCapWidth:
UIImage *backgroundImage = [[UIImage imageNamed:#"SheetBackground.png"] stretchableImageWithLeftCapWidth:0.5 topCapHeight:0];
As per your request:
UIImage *backgroundImage = [[UIImage imageNamed:#"q4Ses.png"] stretchableImageWithLeftCapWidth:0.5 topCapHeight:0];
[_scro setBackgroundColor:[UIColor colorWithPatternImage:backgroundImage]];
And using your image:
The output is:
You can set this image on top of either UIScrollview, UIView and buttons. You do not need a for loop for that.
UPDATE:
The above code is for filling the entire background. If you wish to add only for one row then you have to create one UIView and set its colorWithPatternImage like below:
UIImage *backgroundImage = [[UIImage imageNamed:#"q4Ses.png"]
stretchableImageWithLeftCapWidth:1 topCapHeight:0];
UIView *v=[[UIView alloc]
initWithFrame:CGRectMake(0, 0, _scro.frame.size.width, 45)];
[v setBackgroundColor:[UIColor
colorWithPatternImage:backgroundImage]];
[_scro addSubview:v];
And the output:
Make a view of the height of image. But this view can have any width.
Then set your tile image in this view with following code.
UIImage *tiledImage = [UIImage imageNamed:#"myTiledImage.png"];
self.view.backgroundColor = [UIColor colorWithPatternImage:tiledImage];
This will get you the image tiled multiple times horizontally.
If the view spreads the image everywhere on screen then you'll have to add the following code to your view
self.view.clipToBounds = YES;
UIScrollView *myScrollView=[[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, 320, 480)];
CGFloat scrollWidth = 0.f;
for (int i=0;i<10;i++)//i=10,put as many image number u want to display
{
imageView = [[UIImageView alloc] initWithFrame:
CGRectMake(scrollWidth, 0, 80, 60.f)];
imageView.image=[UIImage imageNamed:#"urimagename"];
imageView.tag=i;
[myScrollView addSubview:imageView];
scrollWidth += 100;
}
myScrollView.contentSize = CGSizeMake(scrollWidth, 100);
EDIT:
You can achieve this in one more way.
CodenameLambda1's answer is better than the above one.But still some changes needs to be done in the #CodenameLambda1's answer..as the SOP's requirement is to display it in scrollview.So instead of self.view use scrollview.
UIScrollView *vie=[[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, 320, 60)];
UIImage *tiledImage = [UIImage imageNamed:#"login"];
vie.backgroundColor = [UIColor colorWithPatternImage:tiledImage];
vie.contentSize=CGSizeMake(1400,60);
vie.clipsToBounds = YES;
[self.view addSubview:vie];
I tried tintColor = [UIColor redColor] and it does the job, but it only show the expected color when the button is being pressed.
In Coloration of UIButtons of type UIButtonTypeRoundedRect they answer the same question but you need an image to implement it, is there any way to do it without an image?
Here is what i want: image
Here is what i'm getting using images: image
Remember... NO IMAGES!
well using an image is one way of doing it, but i guess you already clear that in your question that you do not wish to use an image. here is button that i created and colored programmatically.
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(100, 100, 100,50);
[btn setTitle:#"Hello" forState:UIControlStateNormal];
[btn setBackgroundColor:[UIColor colorWithRed:128.0/255.0f green:0.0/255.0f blue:0.0/255.0f alpha:0.7]];
btn.frame = CGRectMake(100.0, 100.0, 120.0, 50.0);//width and height should be same value
btn.clipsToBounds = YES;
btn.layer.cornerRadius = 20;//half of the width
btn.layer.borderColor=[UIColor redColor].CGColor;
btn.layer.borderWidth=2.0f;
[self.view addSubview:btn];
you can change the [UIColor ColorWithRed: wo whatever you want or even use [UIColor redColor] or any other things you want to do with this.
here is a screen shot:
adding a background color to rounded button is not possible, change the type of the button to custom and then use quartz core to set a round button. so add that to your project and import it in the .m and it should work. hope this works for you man.
to change the button to something similar to the image you showed change the frame to :
btn.frame = CGRectMake(50.0, 100.0, 200.0, 50.0);
and change the radius to :
btn.layer.cornerRadius = 7;
that should do it.
You can create a method to generate an UIImage from a UIColor and then set the returned image as the background of the button, for example:
- (UIImage *)imageWithColor:(UIColor *)color {
CGRect rect = CGRectMake(0, 0, 1, 1);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
UIImage *image = [self imageWithColor:[UIColor colorWithRed:151.0/255.0
green:36.0/255.0
blue:40.0/255.0
alpha:1.0]];
[self.button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[self.button setBackgroundImage:image forState:UIControlStateNormal];
self.button.layer.cornerRadius = 6.0;
self.button.layer.borderWidth = 1.0;
self.button.layer.borderColor = [UIColor darkGrayColor].CGColor;
self.button.clipsToBounds = YES;
Using this I get
here's how I should do it:
download a button image from the internet or create an image yourself, to make it look like you want it to look like. Photoshop might be your best shot for this. make sure you have a transparent background and save it as a .png.
then add it to your xcode project. to make the button:
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setBackgroundImage:[UIImage imageNamed:#"yourImage.png"] forState:UIControlStateNormal];
[btn addTarget:self action:#selector(buttonAction)
forControlEvents:UIControlEventTouchDown];
[btn setTitle:#"Use it!" forState:UIControlStateNormal];
btn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
btn.titleLabel.font = [UIFont systemFontOfSize:20];
btn.frame = CGRectMake(position and size of your button);
[self.view addSubview:btn];
yourImage.png needs to be replaced with the name of your image.
The buttonAction is the action your button performs when it's tapped. if you just add:
- (void) buttonAction
{
}
anywhere in your file, anything you added between those brackets will be performed.
Make sure the size of your button is the same as the size of your CGRect, to make sure it doesn't look stretched out or anything you don't want it to look like.
If you have any questions, feel free to ask them.
Hope this helped you
I have seen this answer
https://stackoverflow.com/a/9243472/563381
And while it works well visual as soon as you set the mask on the Navigation bar's layer it no longer responds to touches... So the back button that appears on the bar can't be clicked. Any solution to cause touches to go through a CALAyer? I didnt think CALayer's blocked touches or that a mask would ever block touches.
Well, I really don't know why CALayer blocks touches and this sounds odd to me...
The way I round corners of UINavigationBar consists in putting 2 UIImageView (10x10 pixels) in the corners and add 2 images to them. These images work as a mask, without blocking touches. If you use antialiasing to draw your images, the look is perfect.
You should try to use this code:
self.navigationController.navigationBar.translucent = YES;
This wil turn on your back button.You can see your button, but its in another layer. That's why it will not work the touches..
UPDATE:
Use this line of code for test. This will work like a charm for you.
//Style UINavigationBar
UIView *background = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 320, 44)];
background.backgroundColor = [UIColor blackColor];
[self.view addSubview:background];
self.navigationController.navigationBar.tintColor = [UIColor cyanColor];
self.navigationController.navigationBar.translucent = YES;
CALayer *capa = [self.navigationController navigationBar].layer;
[capa setShadowColor: [[UIColor blackColor] CGColor]];
[capa setShadowOpacity:0.85f];
[capa setShadowOffset: CGSizeMake(0.0f, 1.5f)];
[capa setShadowRadius:2.0f];
[capa setShouldRasterize:YES];
//Round
CGRect bounds = capa.bounds;
bounds.size.height += 10.0f; //I'm reserving enough room for the shadow
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:bounds
byRoundingCorners:(UIRectCornerTopLeft | UIRectCornerTopRight)
cornerRadii:CGSizeMake(10.0, 10.0)];
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = bounds;
maskLayer.path = maskPath.CGPath;
[capa addSublayer:maskLayer];
capa.mask = maskLayer;
//Back Btn
UIButton *btnback = [UIButton buttonWithType:UIButtonTypeCustom];
[btnback setFrame:CGRectMake(0, 0, 54, 29)];
[btnback setBackgroundImage:[UIImage imageNamed:#"back.png"] forState:UIControlStateNormal];
UILabel * btnlabel = [[UILabel alloc]initWithFrame:CGRectMake(15, 0, 40, 23)];
btnlabel.backgroundColor = [UIColor clearColor];
btnlabel.textColor = [UIColor whiteColor];
btnlabel.font = [UIFont boldSystemFontOfSize:13];
btnlabel.text = #"back";
[btnback addSubview:btnlabel];
[btnback addTarget:self action:#selector(backHome:) forControlEvents:UIControlEventTouchUpInside];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]initWithCustomView:btnback];
Please check below image. i have added scrollview in "BLACK" color and added subview in "GREY" color. now i want to make subview transparent which is define as "WHITE" color.
Please refer the below code. Let me know how to make button transparent with particular frame or let me know if you have any alternative for that.
self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0, 40.0, self.frame.size.width, 300.0)];
self.scrollView.contentSize = CGSizeMake(self.bounds.size.width,ViewHeight);
self.scrollView.autoresizingMask=UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.scrollView.delegate = self;
self.scrollView.backgroundColor =[UIColor blackColor];
[self.view addSubview:self.scrollView
UIButton *butApp = [UIButton buttonWithType:UIButtonTypeCustom];
[butApp setFrame:CGRectMake(x, y , w, h)];
[butApp setBackgroundColor:[UIColor greyColor]];
[self.scrollView addSubview:butApp];
UIButton* gapButton = [UIButton buttonWithType:UIButtonTypeCustom];
[gapButton setFrame:CGRectMake(x+3, y+10, w-6, 10)];
[gapButton setBackgroundColor:[UIColor whiteColor]];
[self.scrollView addSubview:gapButton];
Instead of this gapButton i need transparent portion in grey color so user can see black color in that portion.
Try this, I suggested it in comments. Other answer requires subclassing UIButton, which you suggested was not ideal in your situation.
UIButton *butApp = [UIButton buttonWithType:UIButtonTypeCustom];
[butApp setFrame:CGRectMake(x, y , w, h)];
//[butApp setBackgroundColor:[UIColor greyColor]]; //replace this...
[butApp setBackgroundImage:[UIImage imageNamed:#"greyWithHoleInCenter.png"]
forState:UIControlStateNormal]; //...with this
[self.scrollView addSubview:butApp];
I created a crude .png file to represent the kind of backgroundImage you might be looking for. Note that the center is clear, not white. Therefore, it should show whatever image is behind it:
Ok. Funny question. In my opinion you have to override drawRect: + drawInContext: methods by subclassing UIView class.
You also need to set the container view (the gray view) + button bg to clearColor
-(void)drawRect:(CGRect)r
{
// Let this method blank will cause drawLayer:InContext to be called
}
-(void)drawLayer:(CALayer*)layer inContext:(CGContextRef)context
{
// Fill the bg with gray
CGContextSetFillColorWithColor(context, [UIColor grayColor].CGColor);
CGContextFillRect(context, self.bounds);
// I clear the subview frames
for (UIView * v in [self subviews]) // I do it for all subviews
{
CGContextSetBlendMode(context, kCGBlendModeClear);
CGContextFillRect(context, v.frame);
}
}
I've got a little problem as seen below:
The cell has a background color, and the button doesn't. Still, it doesn't give me rounded edges, but corners. How can I fix that?
UIButton *meerKnop = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[[meerKnop layer] setCornerRadius:8.0f];
meerKnop.backgroundColor = [UIColor whiteColor];
meerKnop.frame = CGRectMake(11.0, (60.0 + (teller * 52.5)), 299.0, 50.0);
...
[meerKnop addSubview:locationLabel];
...
[meerKnop addSubview:categoryLabel];
UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipe:)];
swipe.direction = UISwipeGestureRecognizerDirectionRight;
[meerKnop addGestureRecognizer:swipe];
[swipe release];
[meerKnop addTarget:self action:#selector(alertPressed:) forControlEvents:UIControlEventTouchUpInside];
meerKnop.tag = incId;
[cell addSubview:meerKnop];
Try setting the corner radius of the layer of the button.
[button.layer setCornerRadius:10];
Remember to import if you are using layer property
Also, use:
[[button layer] setMasksToBounds:YES];
With this code the layer gets a corner radius of 10.0 and the -setMasksToBounds: tells the button’s layer to mask any layer content that comes below it in the layer tree. This is necessary in order for the layer to mask off the rounded corners.
UIButton *meerKnop = [UIButton buttonWithType:UIButtonTypeRoundedRect];
Change this to:
UIButton *meerKnop = [UIButton buttonWithType:UIButtonTypeCustom];
Edited:
UIButton *meerKnop = [UIButton buttonWithType:UIButtonTypeCustom];
[[meerKnop layer] setCornerRadius:8.0f];
meerKnop.backgroundColor = [UIColor redcolor];
meerKnop.frame = CGRectMake(11.0, (60.0 + (teller * 52.5)), 299.0, 50.0);
show me where the big white rectangle is appearing? (I hope u have cleared the cell background color).
change the background colour of the button to same as that of cell.. it will take care of the rounded edges as there colour will become same as that of the background. sry i new.. i can think of this way only at the moment.. Hope it helps..