I have a UIView - which I am using as a makeshift toolbar. It contains several UIButtons. (Six, I think) in a horizontal row.
The fifth button over will only respond to [TouchUpInside] events when I click the left half of it - whereas all the other buttons work correctly.
I have gone crazy making sure there weren't any other views overlapping it, etc - and everything seems okay.
Any idea of how to investigate further? Is there any way to see an "event inspector" to see where the touch messages may be going?
Most likely, the other half is covered by a transparent view that obstructs it. See the frames of all sibling views of the button:
for (UIView *v in myButton.superview.subviews){
NSLog(NSStringFromCGRect(v.frame);
}
And see if any of the frames above the button (the array is ordered from bottom to top) overlap with it.
If they don't, see if the whole window has any views covering the button.
The problem was as follows:
The "sixth" button was a "Info Light" type button. For some odd reason - even though the bounds of this button were clearly outside of the bounds of the offending "fifth" button - the "info light" button seems to acquire touches a bit outside it's bounding box.
When I either:
Moved the "Info Light" button further away from the "fifth" button
-or-
Changed the "Info Light" button to a regular (Round Rect) button
...the problem went away!
See the two rightmost buttons in this image:
I guess your superview bounds might be a bit too small? Try to change your superview background color to red or some vivid color and check its bounds.
Well you could try to use this technique with NSLog() to log events and get a sense of what might be happening. I'm not sure if there's a better way to log events:
Observing pinch multi-touch gestures in a UITableView
Just ran into this strange problem as well and after struggling with understanding the nature of the problem, ran across this post. Thanks for the helpful tip! I know it's an old question but this is how I was able to work around it in two ways. The first was to initially create the system info light button and simply retrieve the button image and create a custom button with that image, ignoring the initial button. The advantage to this is that you always get the latest info light graphic in case it changes in the OS. The disadvantage being that a new version of the OS might decide at some point to not make the image available in this way.
UIButton *button = [UIButton buttonWithType:UIButtonTypeInfoLight];
UIImage *img = [button imageForState:UIControlStateNormal];
button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:img forState:UIControlStateNormal];
button.showsTouchWhenHighlighted = YES;
[button addTarget:self action:#selector(infoSelected:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *barButton = [[[UIBarButtonItem alloc] initWithCustomView:button] autorelease];
[barItems addObject:barButton]; // NSMutableArray of tab bar items
The second approach, which I decided to use, so that I knew it would be available, and also to match my splash screen art in case the OS graphic changed, was to follow the same technique and simply save the original PNG to disk and add it to the project as a custom image for the button.
// Run these four lines just once in the simulator to save the original info
// light button image to disk and then eliminate these four lines and create the
// custom button with the image added to the project. Note that it may be a 1x or
// 2x image depending on the simulator device. So run it on both to get two
// versions (changing the name of course).
UIButton *button = [UIButton buttonWithType:UIButtonTypeInfoLight];
UIImage *img = [button imageForState:UIControlStateNormal];
NSData *imgData = UIImagePNGRepresentation(img);
BOOL saved = [imgData writeToFile:#"/Users/Shared/InfoLight.png" atomically:NO];
I noticed that upon selecting the infoLight type, the button could no longer be interacted with. By checking the checkbox "User Interaction Enabled" I solved the problem.
Related
This question already has an answer here:
How to detect objects from Image Processing in iOS?
(1 answer)
Closed 9 years ago.
I have an image, on an image there are three things Spoon, Cup and basket.
Now I have to identify when user click on image nothing will happen until and unless the user click on spoon, cup & basket.
If user click on spoon the spoon colour will become green.
Same for cup and basket.
And I have no idea how to do this. I want some hints from experts and how and where to start?
Any idea or suggestions would be highly welcome.
You can try out masking of views by setting the visible parts as the images of objects and set that view with the gestures
or
Make different images for the objects set it in the selected state of button and on button click change the state to selected
[button setSelected:YES];
[button setSelected:NO];
Place buttons on Spoon, Cup and basket. set button.backgroundcolor = [UIColor clearcolor]; Change images in IBAction.
lets say your image is in backgroundImageView. You got to keep 4 images. The original image, image with green spoon, image with green cup and image with green basket. And then add custom style buttons on top of spoon, cup and basket. And connect below IBAction methods to your buttons.
- (IBAction) spoonButtonPressed{
backgroundImageView.image = [UIImage imageNamed:#"IMAGE_WITH_GREEN_SPOON.png"];
}
- (IBAction) basketButtonPressed{
backgroundImageView.image = [UIImage imageNamed:#"IMAGE_WITH_GREEN_BASKET.png"];
}
- (IBAction) cupButtonPressed{
backgroundImageView.image = [UIImage imageNamed:#"IMAGE_WITH_GREEN_CUP.png"];
}
You can start investigating UIButton.
http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIButton_Class/
Make your images as Button background image in Interface builder or in code. You can do pretty much anything with image then.
Adding Buttons on your object. and go file inspector click on 5th tab make that button clear color your button dissapear.
then do what you want.
also tried to set image directly on buttons
[ButtonSpoon setImage:[UIImage imageNamed:#"spoon.png"] forState:UIControlStateNormal] ;
[ButtonCup setImage:[UIImage imageNamed:#"cup.png"] forState:UIControlStateNormal] ;
[ButtonBasket setImage:[UIImage imageNamed:#"basket.png"] forState:UIControlStateNormal] ;
I am adding two UIBarButtonItems to a UINavigationBar. The first of these is a system item - the search button - and works great. The second is a custom image (a small white Glyphish icon), but when I add this the image becomes grey. The button is perfectly clickable, just grey. Does anyone have an idea why this might be happening?
I do believe the alpha levels are correct. If I put the same icon in a UIBarButtonItem on a UIToolbar (rather than a UINavigationBar) this is how it appears:
Then, try cleaning the target.
Shift + cmd + K
It looks like it is in a highlighted state? If you're creating this button programmatically you might want to check if its UIControlState == UIControlStateHighlighted
You are using a toolbar type icon image. That Glyphish icons on toolbars and TabBars only use alpha layers. But if you are building a button you have to use a standard image. Open the image in any image editor and use the colors you want for your button and the transparent values for alpha layer where you want. It is, in some way, the inverse to the images made of alpha layers in tabbars.
I had been using a grey icon earlier. When I realized it was the wrong color, I suffixed the file with "-grey" and brought in a white icon, which took over the name of the grey icon. But somehow Xcode was still retrieving the old icon, despite its name being changed in the project (and thus in the Finder). Cached maybe? It's a mystery to me!
Thanks for your input everyone.
Try this to force reload button.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([sender isKindOfClass:UIBarButtonItem.class]) {
UIBarButtonItem *button = sender;
self.navigationItem.rightBarButtonItem = nil;
self.navigationItem.rightBarButtonItem = button;
}
}
I've had trouble getting this to work, nowhere have I seen a working example on the web. Now offering bounty on this as its making me crazy. It should be easy, but that doesn't seem to be the case.
I'd like my buttons on my UINavigationBar to be semi-transparent such that they allow the background of whatever is on the UINavigationBar to show through. This effect is seen in many applications, image examples below. You can do this by setting a custom background on the item, which i think is an unacceptable solution because it requires that you prepare images beforehand, and they won't be adaptable for variable buttons etc. They will not look like Apple UI and I don't believe there is a reason to do this either, UIKit is already drawing the background for these buttons, we just need to change it. The correct solution uses the bar items and views generated by Apple's apis.
UIBarButtonItem is not a UIView subclass. When you create one and add it to a UINavigationBar, some code somewhere in the framework draws a view for it. The framework methods seem to resist anything related to allowing transparency of the bar items, such as the tintColor property.
For example, this does NOT work:
UINavigationItem *item = [[UINavigationItem alloc] init];
UIBarButtonItem *editButton = [[UIBarButtonItem alloc] initWithTitle:#"SUCKS" style:UIBarButtonItemStyleBordered target:self action:#selector(whatever:)];
editButton.tintColor = [UIColor colorWithWhite:0.4 alpha:0.3];
item.leftBarButtonItem = editButton;
Nothing I do will make UINavigationBar allow semi-transparency for its bar items. I believe at runtime we need to:
Get the image for the bar item
Mask it for transparency
Set the new image on the bar item
But I haven't been able to get the image at runtime or mask it properly. How do you do this?
Create a custom uiview and draw a semi-transparent black rectangle in it and use that view with initWithCustomView.
see
and
Failing that, you may have to use an image (png). e.g. a 1x1 black pixel png with 30% opacity.You could then initWithImage.
EDIT: I have had this second approach working using:
buttonThree = [[UIBarButtonItem alloc] initWithTitle:#" sort button " style:UIBarButtonItemStyleBordered target:self action:#selector(sortMethod)];
UIImage *thebgUIimage = [UIImage imageNamed:#"semi.png"];
[buttonThree setBackgroundImage:thebgUIimage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
This results in a button that has a transparent background image that the navbar background image shows through. However, you would need to create an image with the rounded corners on and so need an image for each button width. Also I found this thread after trying the above
A brilliant hack is to use the UISegmentedControl with a single segment (as a button) and set its tint color. Have a look at http://charles.lescampeurs.org/2011/02/10/tint-color-uibutton-and-uibarbuttonitem. I have personally implemented this. Feel free to ask any questions.
Instead of searching for code and breaking your head, my suggestion is just to have transparent image which has just border similar to button (add shadow if necessary), create a button of custom type, add the transparent background image to it and you can text as you want. From this custom button, create your bar button item accordingly.
If you're targeting for iOS 5, you can set the background image of the button.
[_button setBackgroundImage:#"image" forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
Note that you'll need to set background images for state UIControlSateSelected and again for both control states for barMetrics: UIBarMetricsLandscape, if your application allows landscape orientation.
Note again this is an iOS 5 feature.
I believe your answer is here: http://sebastiancelis.com/2009/12/21/adding-background-image-uinavigationbar/
I currently work on a small application in which I have several UIButtons. Each of them has an UIImageView beneath it. At the moment, I associate each UIButton with each UIImageView (all are named via an IBOutlet - UIButton and UIImageView). When I press a button, the underlying image changes. I would like to know if it's possible (and how) to create a button which contains an underlying UIImage (not a UIButton image or background image), a sort of new object.
This image is slightly larger than the associated UIButton, like the apple calculator basic apps, and this image changes when I press the button.
I've tried several solutions (certainly incomplete) and I'm beginning to despair.
My current solution is functional but I do find it not particularly elegant.
UIButton has both image and backgroundImage as its properties.
To achieve what you are looking for, I would actually recommend you to stick to just a UIButton, and then using contentInset to position the image over the backgroundImage so it creates the effect I think you are looking for. This should be quite easy in interface builder...
you can make an invisible button and behind it make the image..
This will give you what you want but should be avoided at cost...
Stick to UIButton..
I believe even in calculator app they are only UIButtons and nothing else..
they have been coded to been momentary selected ..so that's why you see them kind of changing highlight for a small fraction and each button have been coded to perform specific function(+ - / equal .)
Update : i might be in doubt but if you asked for a button to have an image view inside it..
then here is the answer.
Make UIbutton. Make an ImageView and then call [theButton.view addSubview:ImageView];
Since both UIbutton and UIImage view inherit from UIView.. you can add as many subviews to them..that is inside them
If I understood your question correct then you may try the following:
UIButton *button = [UIButton alloc]init];
[button setImage:buttonImage forState:UIControlStateNormal]; when button not pressed
[button setImage:buttonImage forState:UIControlStateSelected]; when button tapped
[button release];
I have a UIViewController set up to display an info-button on the right in its UINavigationItem like this:
UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeInfoLight];
[infoButton addTarget:self action:#selector(toggleAboutView) forControlEvents:UIControlEventTouchUpInside];
self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithCustomView:infoButton] autorelease];
That works perfectly, but the only problem is that I'm left with little to no space to the right of the button, which looks pretty ugly:
Is there any way for the button to move about 5 px out from the right side?
Thanks.
infoButton.contentEdgeInsets = UIEdgeInsetsMake(0, -10, 0, 10);
Try setting infoButton.contentEdgeInsets (or imageEdgeInsets); something like
infoButton.contentEdgeInsets = (UIEdgeInsets){.right=10};
I'm not sure if it works for "system" buttons, but it might.
If that doesn't work, the easiest way is probably to stick it inside a UIView.
EDIT: Presumably the toolbar calls [customView sizeThatFits:blah] to find out how big the view "wants to be". The above code is supposed to mean "add a 10-pixel right edge inset", which for a normal (custom) button also makes the size bigger by 10 pixels.
It seems like UIButton returns a fixed size for the standard info button, ignoring any insets. Your code "works" by affecting the contentRectForBounds: and imageRectForContentRect: methods, which changes where the icon is drawn, but does not actually change the size of the button. I suspect that the icon is drawing outside the button, which may mean that the "touchable" rect is wrong (but toolbars seem to increase the touch rects for normal UIBarButtonItems, so maybe it doesn't matter).