Create highlighted state background image programmatically for UIButton - iphone

I created a UIBarButton programmatically with the following code:
UIButton * rightButton = [UIButton buttonWithType:UIButtonTypeCustom];
[rightButton setFrame:CGRectMake(0, 0, 81, 30)];
[rightButton setBackgroundColor:[UIColor clearColor]];
rightButton.layer.borderColor = [UIColor blackColor].CGColor;
rightButton.layer.borderWidth = 0.5f;
rightButton.layer.cornerRadius = 5.0f;
rightButton.titleLabel.font = [UIFont fontWithName:#"HelveticaNeue-Bold" size:12];
[rightButton setTitleShadowColor:[UIColor blackColor] forState:UIControlStateNormal];
[rightButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
//set text according to sign in status
if (signIn) {
[rightButton setTitle:#"5 votes left" forState:UIControlStateNormal];
} else {
[rightButton setTitle:#"Sign in" forState:UIControlStateNormal];
}
UIBarButtonItem * rightBarButton = [[UIBarButtonItem alloc] initWithCustomView:rightButton];
self.navigationItem.rightBarButtonItem = rightBarButton;
The obtained button has the desired aspect but now what I need is that when the status of the button is highlighted there should be a gradient effect fading to black to let the user know that he has pressed the button, because right now when I pressed the button, nothing happens to the view so the user has no way to know that he has pressed the button.
I want to explore a choice that does NOT involve setting the background images for the desired states because the text of the button can change dynamically according to the app configurations so I need to do this entirely by code.

Although this won't directly answer your question, it may help. I had to create some graphics for a button dynamically and came up with a method using core graphics to create my button image. It gives me the flexibility to change to appearance parametrically in the code.It draws the button image in an abstract graphics context and then converts the result into an image that I can use for my button. YOu might get enough out of my explanation that you can try it yourself for your needs.

Subclass UIButton and add a CALayer or CAGradientLayer to achieve the highlight effect that you want. Set the initial state of the highlight layer to hidden. Override setHighlighted: with something like:
- (void) setHighlighted:(BOOL)highlight {
highlightLayer.hidden = !highlight;
[super setHighlighted:highlight];
}

Related

Hit area is only on label of UIButton

I create a UIButton like this:
button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0,0,100,100);
The button works, but the hit area is only on the text, not the entire button. I've set the background of the button to be [UIColor clearColor]. What do I need to do to make it so that the entire frame of the button is the hit area?
I suppose I could change the frame of the label to equal the button, but that seems hokey. Is there a better way?
try like this,
UIButton *button=[UIButton buttonWithType:UIButtonTypeCustom];
button.frame=CGRectMake(0,0,100,100);
button.backgroundColor=[UIColor clearColor];
[button setTitle:#"Set" forState:UIControlStateNormal];
[button setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
[button addTarget:self action:#selector(buttonClicked) forControlEvents: UIControlEventTouchUpInside];
[self.view addSubview:button];
The button in question was being built up with layers. What I ended up doing was ensuring the background layer had a solid background color. Simply setting the background of the button to clear did not work in this case.
//set a background color so it is clickable
[layer0 setBackgroundColor: CGCOLORA(0, 1) ];
Setting the opaque property of the UIButton to true worked for me (iOS10)

adding custom UIButton to UINavigationBar

So the code I have is as follows:
// Create a containing view to position the button
UIView *containingView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 23.5, 21.5)] autorelease];
// Create a custom button with the image
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:[UIImage imageNamed:#"Settings.png"] forState:UIControlStateNormal];
[button addTarget:self action:#selector(settings) forControlEvents:UIControlEventTouchUpInside];
[button setFrame:CGRectMake(-19, -3, 21.5, 21.5)];
[containingView addSubview:button];
// Create a container bar button
UIBarButtonItem *containingBarButton = [[[UIBarButtonItem alloc] initWithCustomView:containingView] autorelease];
self.navigationItem.rightBarButtonItem = containingBarButton;
The issue is that my Settings.png original image size is 21.5, 21.5 and there fore the button is super hard to click. I have to tap really hard in order to trigger the UITouchUpInside to be triggered. This will clearly be rejected if I put it in the app store, as it is not in compliance with apple's HIG. Is there a way around this? I still need to use UIView as the container for the UIButton as I'd like to position it correctly on the UINavigationBar
Try to set a bigger fram to the button like 40,40 and set the content mode to be the center so the image will apear to be in the center.
button.contentMode = UIViewContentModeCenter;
Tell me if that helped

iPhone SDK: UIBarButtonItem is not displaying border

I have a UIToolbar which I am trying to put some custom UIBarButtonItems on. However, when I use the code below, the button shows up with NO border.
UIImage *cameraRollButtonImage = [UIImage imageNamed:#"Flash.png"];
UIButton *cameraRollButton = [UIButton buttonWithType:UIButtonTypeCustom];
[cameraRollButton setImage:cameraRollButtonImage forState:UIControlStateNormal];
cameraRollButton.frame = CGRectMake(0.0, 0.0, cameraRollButtonImage.size.width, cameraRollButtonImage.size.height);
// Initialize the UIBarButtonItem
cameraRollButtonItem = [[UIBarButtonItem alloc] initWithCustomView:cameraRollButton];
[cameraRollButtonItem setStyle:UIBarButtonItemStyleBordered];
//Add the Buttons to the toolbar
NSArray *toolbarItems = [NSArray arrayWithObject:cameraRollButtonItem];
[self.cameraTabBar setItems:toolbarItems];
This displays the button just fine, however, there is NO button border (like standard the UIBarButtonItem). So the line [cameraRollButtonItem setStyle:UIBarButtonItemStyleBordered]; doesn't seem to do anything.
Does anyone have any experience with this?
I would like to be able to eventually rotate the image in the button when the device orientation is changed (keeping the toolbar static), so simply adding an image to the UIBarButtonItem doesn't work; I need to get this to work with by using the customView property.
Many thanks!
Brett
Have you considered creating your own button image with a border? You can use it as the backgroundImage of a UIButton:
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setBackgroundImage:_backgroundImage_ forState:UIControlStateNormal];
// So that the button does not gray out when disabled
[button setBackgroundImage:_backgroundImage_ forState:UIControlStateDisabled];
[button setImage:_cameraImage_ forState:UIControlStateNormal];
button.frame = CGRectMake(0, 0, 125, 30);
You could then use button with initWithCustomView:.
The PSD file here might give you an overview of how to create your own button.

UIButton in UIBarButtonItem not showing up

I have the following in my view did load on my table view controller:
UIButton *change_view = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[change_view setTitle:#"List" forState:UIControlStateNormal];
[change_view addTarget:self action:#selector(toggleView:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithCustomView: change_view];
self.navigationItem.rightBarButtonItem = button;
When I run the program, it doesn't show any title or the rounded rectangle button. However, if I change the type to UIButtonTypeInfoLight, it will show up... so what is the problem?
I'd prefer the way below to set the button's bounds.
[button setTitle:#"Title" forState:UIControlStateNormal];
[button sizeToFit];
Try to set an appropriate frame to your change_view.
When you use UIButtonTypeInfoLight type button uses some built-in size (likely depended on icon used for it), with UIButtonTypeRoundedRect type default frame is applied which must be CGRectZero rect.

Is there an way to make an invisible UIButton that will still "be there" and catch touch events for my UIImageView?

I thought to be clever and just put an transparent UIButton over an UIImageView with the exact frame size, so that I can wire it up easily with any event I like, for example TouchUpInside, and make it call a action method of an view controller when the user touches it. Well, it works until alpha is below 0.1f. If I do 0.01f, it will not work. So to get it work, when looking a long time on the screen, you'll see that 0.1f of alpha shining through. And that's totally disgusting ;)
It seems like iPhone OS trys to be clever and won't catch events on the button if it's visually not there. Any idea how to solve that?
Sure I could make a subclass of UIImageView and implement touchesBegan:... etc., but it doesn't feel really elegant. I mean...when I want to hyperlink an image on the web, I would never want create my own HTML element for that image, just to wire it up to an url when it's clicked. That just doesn't make a lot of sense to me.
You should be able to set the button's 'Type' to Custom in Interface Builder, and it will not display any text or graphical elements over the UIImageView. This way, you don't need to adjust the alpha. If the view is built from code, use:
button = [UIButton buttonWithType:UIButtonTypeCustom];
In addition to UIButtonTypeCustom, I set the button text colors to the following:
[button setTitleColor:[UIColor clearColor] forState:UIControlStateNormal];
[button setTitleShadowColor:[UIColor clearColor] forState:UIControlStateNormal];
[button setTitleColor:[UIColor clearColor] forState:UIControlStateHighlighted];
[button setTitleShadowColor:[UIColor clearColor] forState:UIControlStateHighlighted];
The best way of doing this is:
myButton.hidden = YES;
You can't use the buttonType property because it is a read only property. Only way to use it is when creating your button dynamically.
i also beleive you can assign an image to a button.
The image can take up the entire frame and can also have no other artifacts of the buttone if you set it up right.
check out the Property
UIButtonInstance.currentImage
That way you are not hogging your resources with elements that are essentially already there.
You can hide a button (or any object) and keep it active by adding a mask to its layer. The button will be invisible but will still catch events.
let layer = CAShapeLayer()
layer.frame = .zero
myButton.layer.mask = layer
Jasons answer above is nearly correct, but setting the button type is not possible. So to programmatically create an empty button, use this code:
UIButton* myButton = [UIButton buttonWithType:UIButtonTypeCustom];
myButton.frame=frame;
[self.view addSubview:myButton];
This is what i did but with using a subclass of UIButton which i later found out should not be subclassed as per the net. My subclass was called Points
Points *mypoint=[Points buttonWithType:UIButtonTypeCustom];
then if you have an image you want to add to the button :
[mypoint setImage:imageNamed:#"myimage"] forstate: UIControlStateNormal];
if you dont add this image then the button will be invisible to the user but should respond to touch. Thats how i created a hotspot on my imageView inorder to have it respond to user interaction.
It's the only way I found...
[yourButton setImage:[UIImage imageNamed:#"AnEmptyButtonWithTheSameSize.png"] forState:UIControlStateNormal];
Take care of the image. It must be .png
Custom UIButtons respond to user interactions unless their alpha is set to 0. Put a custom UIButton on top of your imageView and connect to buttonPressed action. I have also set an additional highlighted image for my UIView, now it really behaves like a UIButton. First I have defined a duration for the UIView for staying highlighted:
#define HIGHLIGHTED_DURATION 0.1
Then set the image view highlighted if the button is pressed and start a timer to keep it highlighted for that duration. Do not forget to set the highlighted image for your imageview.
- (IBAction)buttonPressed:(id)sender {
[_yourImageView setHighlighted:YES];
_timer = [NSTimer scheduledTimerWithTimeInterval:HIGHLIGHTED_DURATION
target:self
selector:#selector(removeHighlighted)
userInfo:nil
repeats:NO];
}
And simply undo highlighting when the timer finishes:
-(void) removeHighlighted{
_yourImageView.highlighted = NO;
}
lazyImageView = [[UIImageView alloc] init];
button=[[UIButton alloc]init];
[UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:#selector(aMethodForVideo:)
forControlEvents:UIControlEventTouchUpInside];
[button setBackgroundImage:[UIImage imageNamed:#"BackTransparent.png"] forState:UIControlStateHighlighted];
[button setTitle:#"" forState:UIControlStateNormal];
lazyImageView.frame=CGRectMake(x, y, w, h);
button.frame=CGRectMake(x, y, w, h);
Set frame of button and Image both have same frame .I use this code and working fine.Also set button background image forState:UIControlStateHighlighted so when you click on that when you see the click effect.
I managed to do it using the following code.
If the iPad is landscape the button will be located in the top right of the screen.
UIButton *adminButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
adminButton.frame = CGRectMake(974.0f, 0.0f, 50.0f, 50.0f);
[adminButton setBackgroundColor:[UIColor clearColor]];
[adminButton setTag:1];
[adminButton addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:adminButton];
Pressing the 'adminButton' will run the following function:
- (void)buttonPressed:(id)sender {
int buttonId = ((UIButton *)sender).tag;
switch(buttonId) {
case 1:
NSLog (#"Admin button was pressed");
break;
case 2:
//if there was a button with Tag 2 this will be called
break;
default:
NSLog(#"Key pressed: %i", buttonId);
break;
}
}