I have created a custom UIButton for an iOS 4.3+ application. I wanted to make the background image stretch, so I and used the following methods to set its background image:
[myButton setBackgroundImage:[[UIImage imageNamed:myImagePath] stretchableImageWithLeftCapWidth:leftStretchValue topCapHeight:topStretchValue] forState:UIControlStateNormal]
[myButton setBackgroundImage:[[UIImage imageNamed:myHighlightedImagePath] stretchableImageWithLeftCapWidth:eftStretchValue topCapHeight:topStretchValue] forState:UIControlStateHighlighted]
[myButton setBackgroundImage:[[UIImage imageNamed:mySelectedImagePath]
stretchableImageWithLeftCapWidth:eftStretchValue topCapHeight:topStretchValue] forState:UIControlStateSelected]
I have added an event handler to the custom button
[myButton addTarget:self action:#selector(buttonHighlighted:) forControlEvents:UIControlEventTouchDown];
[myButton addTarget:self action:#selector(buttonSelected:) forControlEvents:UIControlEventTouchUpInside];
In the above mentioned methods, I have set the selected and the highlighted state of the button accordingly. I have changed the frame of the UIButton to adjust the dimensions of an irregular image (mySelectedImage and myHighlightedImage, neither of which is a rectangle), so that it gets aligned properly along with myImage.
- (void) buttonSelected {
myButton.selected = !myButton.selected; //setting the selected property to NO in the viewDidLoad
//code to change the frame of the UIButton to accomodate the irregular image
}
- (void) buttonHighlighted {
myButton.highlighted = YES;
}
The problem I am facing is that when I select myButton, a gray color overlay is displayed on myImage for a very short time before the images myHighlightedImage and mySelectedImage are displayed as its background. I have set the background color of myButton as clearColor, thinking that might be the reason, but it is not getting solved.
What could be the possible issue... ?
button.adjustsImageWhenHighlighted = NO;
I think that is what you are looking for..
Related
I am developing an application in which I have a horizontal scroller.
The scroller area comprise of different colors [which are nothing but UIImageView of colors].
Above the scroller area is a canvas [which is also a UIImageView].
Now, what I want is that when I select any color in the scroller area, it should set on the canvas.
It is pretty much like a color picker but I am already providing solid color options to be selected by the user.
How should I go about it ? Any sample Code to get me started or my mind kicking would be awesome ?
Thanx a ton
To implement it easily.
Use UIView not UIImageView
Set UIView backgroundColor and place it on the scroll
Set UITapGestureRecognizer on views,Refer here
when a purticular view is touched you have its instance of view which
is touched
get the background color of the view and set it in the scroller
Can you take UIButtons instead of UIImageViews inside your scrollView to show colours to be picked.
This will make the implementation easier. User will select any colour button and you will receive a callback in buttons action selector method. Then based on button tag or any property you can set the colour to your canvas.
In current implementation it will be tricky as you need to know the exact content offset where the tap is done to make out which UIImageView was pressed.
coding steps:
In your scroll view add UIButtons instead of UIImageView like:
UIButton* button = [[UIButton alloc] initWithFrame:someRect];
//put some tag to button
button.tag = someInt;
//add selector to each button to get callback
[view addTarget:self action:#selector(btnSelected:) forControlEvents:UIControlEventTouchUpInside];
[scrollView addSubview:button];
In the btnSelected method put this code:
-(IBAction)btnSelected:(id)sender;
{
UIButton* button = (UIButton*) sender;
if (button.tag == someInt) {
//do something like
canvas.backgroundColor = button.backgroundColor;
}
}
Instead of using UIImageViews or UIViews as suggested, I would put custom UIButtons for picking colors.
UIButton * colorButton;
//You will probably do these inside a for loop
colorButton = [UIButton buttonWithType:UIButtonTypeCustom];
[colorButton setFrame:CGRectMake(X, Y, buttonSize, buttonSize)];
[colorButton setTitle:#"" forState:UIControlStateNormal];
[colorButton setBackgroundColor:SOME_COLOR];
//Border visualization would be good if you are putting buttons side-by-side
[colorButton.layer setBorderWidth:1.0];
[colorButton.layer setBorderColor:[[UIColor darkGrayColor] CGColor]];
//You can use this tag to identify different buttons later
[colorButton setTag:INDEX+SOME_OFFSET]; //use loop index with some offset
[colorButton addTarget:self action:#selector(colorButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
-(void) colorButtonPressed:(UIButton *) sender
{
UIColor *selectedColor = sender.backgroundColor; //Or identify with sender.tag
[yourCanvas doSmtOnCanvas:selectedColor];
}
Initialize UIImageView then add gesture recognizer to all imageViews by calling this method.
- (void) setupImageView : (UIImageView *) imageView{
[imageView setUserInteractionEnabled:YES];
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(changeUIImageViewBackgroundColor:)];
tapGestureRecognizer.numberOfTapsRequired = 1;
[imageView addGestureRecognizer:tapGestureRecognizer];
}
Now change color of canvasView within the selector by following way:
- (void) changeUIImageViewBackgroundColor : (UITapGestureRecognizer *) recognizer{
UIImageView *imageView = (UIImageView *)[recognizer view];
[canvasView setBackgroundColor:[imageView backgroundColor]];
}
You can put a tap gesture in your scrollview and whenever a tap is made in the scroll check whether the tap is on the imageview. (You will get whether the tap point in on imageview or not) and according you can change the image.
Second alternative is to take a custom button and handle on its click.
Hope it helps
I am having trouble with the behavior of one of my UIButtons. I am trying to essentially make it a toggle button, but I am running into the problem below.
I have the code:
UIButton *likeButton = [[UIButton alloc] initWithFrame:CGRectMake(horizontalOffset+buttonWidth, verticalOffset, buttonWidth, buttonHeight)];
[likeButton setImage:[UIImage imageNamed:#"like-off.png"] forState:UIControlStateNormal];
[likeButton setImage:[UIImage imageNamed:#"like-on.png"] forState:UIControlStateHighlighted];
[likeButton setImage:[UIImage imageNamed:#"like-on.png"] forState:UIControlStateSelected];
[likeButton addTarget:self action:#selector(likeButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
which fires the method:
-(void)likeButtonPressed:(id)sender {
UIButton *button = (UIButton *)sender;
[button setSelected:!button.selected];
}
The behavior I am seeing is that when I tap the button down (and highlight it), it works as expected, and the 'like-on.png' image is used for the highlighted state, and it remains on in the 'selected' state.
However, when I tap the button again, to toggle it off, I see a gray highlighted state when I press my finger. When I release my finger, I see the 'like-off' image is shown as expected.
I would like to avoid seeing the gray highlighted state when I press my finger down on the button when I go to toggle it off. Instead I would like to make sure that the highlighted state on toggle-off uses the 'like-on.png' image as specified in the code.
What's going on here? Any ideas where my code could be incorrect?
Many thanks,
Brett
You're missing the image for the selected and highlighted state:
[likeButton setImage:[UIImage imageNamed:#"like-on.png"] forState:UIControlStateSelected | UIControlStateHighlighted];
If you don't set it, the image of the normal state is used. From the -[UIButton setImage:forState:] documentation:
In general, if a property is not specified for a state, the default is to use the UIControlStateNormal value.
If you don't want your images to be modified when they are highlighted, set:
likeButton.adjustsImageWhenHighlighted = NO;
I think the selected property of UIButton is meant for something different (think of the desktop UI).
It would be more consistent to change the for all states according to a BOOL that tracks if it is "on" or "off".
Thus,
-(void)likeButtonPressed:(id)sender {
UIButton *button = (UIButton *) sender;
liking = !liking;
if (liking) {
// configure the four states with "like-on" and other images
}
else {
// configure the four states with "like-off"
}
}
Otherwise you would use the state of a UI element to represent your program logic, which is basically flawed. The only instance where this is sort of acceptable (but not really) is a UISwitch.
I have a UIToolbar that I've customized with my own background image. Consequently, the built-in UIBarButtonItem appearance doesn't work for me, so I'm using images that are already prepared to show in the bar. I create a custom button item with this method:
+ (UIBarButtonItem *)customWithImage:(UIImage *)image enabled:(BOOL)enabled target:(id)target action:(SEL)selector {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
//I've tried different values for the frame here, but no luck
button.frame = CGRectMake(0, 0, 44, 44);
button.enabled = enabled;
button.showsTouchWhenHighlighted = YES;
[button addTarget:target action:selector forControlEvents:UIControlEventTouchUpInside];
[button setImage:image forState:UIControlStateNormal];
UIBarButtonItem *it = [[[UIBarButtonItem alloc] initWithCustomView:button] autorelease];
//Tried changing this, to no avail
it.width = 32.f;
return it;
I have one button on the left and one on the right and I'm trying to make it so that if you tap on the far left or far right of the UIToolbar, the corresponding button is tapped. However, with these custom buttons, the hit targets do not extend all the way to the edges of the UIToolbar, but are inset from the sides:
http://skitch.com/andpoul/d1p8g/hit-targets
Any help greatly appreciated!
UIBarButtonItem.width might be ignored if you're using a custom view (it probably just uses the width of the view).
A lame hack is to make the toolbar wider (so it sticks outside the screen) and add transparent edges to the background image to compensate. This brings the buttons closer to the edge of the screen.
An alternative is just to use a UIImageView with UIButton subviews.
I think the only way you will have to go is to make buttons wider (change image by adding some from left for one and right for another) and adjust size...
I'm trying to add a UIButton to a UIView, but am having some trouble with getting it to respond to touches.
I have a method which returns UIButtons after I provide it with a tag:
- (UIButton*)niceSizeButtonWithTag:(int)tag {
UIButton * aButton = [UIButton buttonWithType:UIButtonTypeCustom];
[aButton setTag:tag];
[aButton addTarget:self action:#selector(buttonWasTapped:) forControlEvents:UIControlEventTouchUpInside];
CGRect newFrame = aButton.frame;
newFrame.size.width = 44;
newFrame.size.height = 44;
[aButton setFrame:newFrame];
return aButton;
}
As you can see I'm creating a new button and increasing the size.
I use this in the following way:
UIButton * anotherButton = [self niceSizeButtonWithTag:1];
[anotherButton setImage:[UIImage imageNamed:#"image" withExtension:#"png"] forState:UIControlStateNormal];
[anotherButton setCenter:CGPointMake(middleOfView)];
[aView addSubview:anotherButton];
I create a lot of buttons like this, hence the reason for the method.
The buttons are always created and added to the subview perfectly. I can see the image and they're in the correct position. The problem is that they only respond to touches in a tiny strip.
In this attached image,
alt text http://web1.twitpic.com/img/107755085-5bffdcb66beb6674d01bb951094b0e55.4c017948-full.png
The yellow shows the whole frame of the button,
The red shows the area that will respond to touches.
The grey shows a section of the view the button is added to.
If anyone could shed some light on why this is happening, it would be really useful.
UPDATE:
I should probably mention I'm trying to add this button to a UIView which is a subview of a UITableViewCell.
UPDATE 2:
Adding it directly to the UITableViewCell works, adding it to the UIView on the UITableViewCell is causing the error.
FINAL UPDATE
The problem turned out to be that I was sending the view containing the button to the back of the subviews on the UITableViewCell. Getting rid of the sendSubviewToBack: call fixed it.
Do you have any other views added to this containing view after you add the button? try setting some of your view's background color to blueColor, redColor and other colors to better see what the stack of views in your app is like. Then you should be easily able to see if there is some sort of view blocking the button.
I have an imageView and after i add it to the screen I release it.
Before that I adds a button onto it with this code.
button = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
button.frame = CGRectMake(128.00, 128.00, 23.00, 40.00);
[button setBackgroundImage:[UIImage imageNamed:#"move.png"] forState:UIControlStateNormal];
[button addTarget:self action:#selector(showAddress:) forControlEvents:UIControlEventTouchUpInside];
[imageView addSubview:button];
- (void) showAddress:(id)sender
{
NSLog(#"Working");
}
The button appears but nothing happens when I click on it to call a function. Not even the pressing-unpressing. Is this because I am releasing the imageView?
Edited:Check if userInteractionEnabled property of your UIImageView is set to YES - it is set to NO by default and that's why UIImageView (and its subviews) does not respond to touch events. I've just set it to YES in my code and it works fine.
One more note - when you add your button to another view it takes the ownership of the button and as you retained it in your code you should also release it. (Or just not retain in this case)