UIButton background won't be transparent - objective-c

I'm trying to create a custom UIButton, but when I set the background to be clear/transparent, it fills the background of the frame with black. I'm not creating these in IB, I need to do this programmatically. Is there something I'm missing?
UIButton* btn = [UIButton buttonWithType: UIButtonTypeCustom];
btn.frame = rect;
[btn addTarget: self action:#selector(toggleMaster) forControlEvents: UIControlEventTouchUpInside];
btn.opaque = NO;
btn.backgroundColor = [UIColor clearColor];
[btn setBackgroundImage: [UIImage imageNamed: [NSString stringWithFormat: #"%#_icon", self.currentKey]] forState: UIControlStateNormal];
[self addSubview: btn];
EDIT:
I realized I should mention I am doing this in the drawRect method of UIView. Bad practice?

I don't think you need to set the backgroundColor, UIButtonTypeCustom is already transparent by default. Did you try without it? Also, is the image transparent? The size is the same of the button?

Related

ChildView didn't maintain its ParentView Frame

Hope all of you will be fine. Guys i have a situation, I have a uiview and uibutton as under:
UIView* containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 200, self.view.frame.size.width, 70)];
containerView.backgroundColor = [UIColor whiteColor];
[self.view addSubview:containerView];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.backgroundColor = [UIColor redColor];
[button addTarget:self action:#selector(SettingPressed:) forControlEvents:UIControlEventTouchUpInside];
UIImage *image = [UIImage imageNamed:#"settings_button.png"];
[button setImage:image forState:UIControlStateHighlighted & UIControlStateNormal & UIControlStateSelected];
button.frame = CGRectMake(0,0, 40, 40);
button.center = containerView.center;
[containerView addSubview:button];
The problem is uibutton appear far from uiview instead of in the middle of uiview. What i am mistaking, please guide me.
Thanks.
First, when you change a view's center property the frame property will be changed automatically so you only should set the button center:
button.center = CGPointMake(containerView.frame.size.width / 2,
containerView.frame.size.height / 2);
Now, whenever you change the center property you need to manually tell the view to redraw itself using setNeedsDisplay :
[button setNeedsDisplay]
and lastly, the difference between frame and bounds that frame defines the position and size relative to the parent view while bounds describes the drawing area inside (or outside) the frame.

Event on an Image in iOS

I am pretty new to iOS development, so this may seem to be a stupid question.. In my xib file, i have taken a UIImageView that will show an image when the page is loaded. But when a user taps on an image, I want the next view to be loaded.. But I am not able to do that because we cannot have a delegate not a target-action mechanism for a UIImage view.. Many places, I found a workaround.. using a button and then placing an image on it, and then using it.. but I want the first way to work.. Please help..
use UITapGestureRecognizer ,and Don't forget to set imageView.userInteractionEnabled = YES; because by default image not having UserInteraction.
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
[singleTap setNumberOfTapsRequired:1];
[imageView addGestureRecognizer:singleTap];
-(void)handleSingleTap:(id)sender {
// push you view here
}
(OR) If you want
take button with BackGround image.
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(270,10,30,30);
[button setBackgroundImage:[UIImage imageNamed:#"image.png"] forState:UIControlStateNormal];
[button addTarget:self action:#selector(action:) forControlEvents:UIControlEventTouchUpInside];
Instead of Using UIImageView, you can use UIButton.
UIButton *myBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[myBtn setBackgroundImage:[UIImage imageNamed:#"your_image_Name"] forState:UIControlStateNormal];
[myBtn setBackgroundImage:[UIImage #"your_image_Name"] forState:UIControlStateHighlighted];
[myBtn addTarget:self action:#selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
also write button action:
-(void)buttonAction:(id)sender {
// Do whatever you want
}
In Case of XIB, Just use UIButton instead of UIImageView and set Background Image for both state Normal & Highlighted as you want. Rest you can manage button's action from XIB.
You can also add a fully transparent UIButton on top of your UIImageView... It should be preferred as each element has a clean semantics.

Why are UIButton actions not being called when UIButton is inside a UIScrollView

I have created a springboard like panel containing buttons as follows:
-(void)configurePanel{
self.criteriaPanel.scrollEnabled=YES;
self.criteriaPanel=[[UIScrollView alloc] initWithFrame:CGRectMake(
0.0f,
0.0f,
[UIScreen mainScreen].bounds.size.width,
(BUTTON_HEIGHT+(3*BUTTON_Y_OFFSET))
)];
UIView *scrollViewContent=[[UIView alloc]init];
NSArray *criteriaTypeButtonTitles=[NSArray arrayWithObjects:
#"Option1",
#"Option2",
#"Option3",
#"Option4",
#"Option5",
#"Option6",
nil
];
for (int i=0; i<[criteriaTypeButtonTitles count]; i++) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.tag=i;
button.frame = CGRectMake(
(((BUTTON_X_OFFSET*i)+(BUTTON_WIDTH*i))+BUTTON_X_OFFSET)
, BUTTON_Y_OFFSET
, BUTTON_WIDTH
, BUTTON_HEIGHT
);
[button setTitle:[criteriaTypeButtonTitles objectAtIndex:i] forState:UIControlStateNormal];
[button setTitleColor:[UIColor blueColor] forState:UIControlStateHighlighted];
button.titleLabel.font=[UIFont systemFontOfSize:13.0f];
[button setBackgroundColor:[UIColor grayColor]];
[button.layer setCornerRadius:10.0f];
[button.layer setBorderWidth:1.0f];
[button addTarget:self action:#selector(sortByButtonTap:) forControlEvents:UIControlEventTouchDown];
[scrollViewContent addSubview:button];
}
//based upon # of buttons
self.criteriaPanel.contentSize=CGSizeMake(
(([criteriaTypeButtonTitles count]*BUTTON_WIDTH)+([criteriaTypeButtonTitles count]*BUTTON_X_OFFSET)),
(BUTTON_HEIGHT+(2*BUTTON_Y_OFFSET)));
[self.criteriaPanel addSubview:scrollViewContent];
[self.view addSubview:self.criteriaPanel];
}
The panel displays correctly and scrolls, but the tap events (sortByButtonTap:) for the buttons are never called. I suspect this is related to the buttons being contained in a view which is contained in the scrollview. After reading a number of other questions and the docs I still can't figure out what the solution should be.
EDIT:
I experimented w/ adding the buttons to the UIScrollView (self.criteriaPanel) directly and the button taps call sortByButtonTap: so it is something to do w/ the buttons being in the scrollViewContent.
You might need to set userInteractionEnabled on the containing view scrollViewContent for the button to receive touch events:
[scrollViewContent setUserInteractionEnabled:YES];
What if you try:
[button setExclusiveTouch:YES];
Buttons tend to work abnormally when they are inside a view that also handles touch events.
Follow this code for your query,
Add UIButton in Scrollview
scrollview.pagingEnabled = YES;
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake();
[button setTitle:#"X" forState:UIControlStateNormal];
[button setTitleColor:[UIColor clearColor] forState:UIControlStateNormal];
[button addTarget:self action:#selector(btnCloseClicked:withEvent:) forControlEvents:UIControlEventTouchUpInside];
[button addTarget:self action:#selector(btnCloseDraged:withEvent:) forControlEvents:UIControlEventTouchDragInside];
[button addTarget:self action:#selector(btnCloseDragedEnd:withEvent:) forControlEvents:UIControlEventTouchDragExit];
[scrollview addSubview:button];
scrollview.userInteractionEnabled = YES;
you can put this three methods of button manually.
Let me know if you still have query.
instead of:
[button addTarget:self
action:#selector(sortByButtonTap:)
forControlEvents:UIControlEventTouchDown];
try:
[button addTarget:self
action:#selector(sortByButtonTap:)
forControlEvents:UIControlEventTouchUpInside];
I think your problem is just that you set the wrong UIControlEvent to the UIButton. Change from UIControlEventTouchDown to UIControlEventTouchUpInside. If you connect a UIButton inside the Interface Builder it will always set it to this UIControlEvent:
Another reason:
Otherwise your UIScrollView controls the interactions because it needs to know if you want to scroll it. If you place UIButtons inside your UIScrollView they will be accessible but always with a little delay. This is why you should maybe change the settings for the UIScrollView:
You can disable delays content touches and UIButtons will be accessible immediately

UIButton IB vs programmatically

When I make a custom UIButton with a background in interface builder, it gives me this default functionality of when i touch up inside, it sort of blacks out the image.
If I create the UIButton programmatically, like this:
buttonPic = [[UIButton alloc] initWithFrame:CGRectMake(5, 5, 100, 63)];
[[buttonPic imageView] setContentMode:UIViewContentModeScaleToFill];
[buttonPic setImage:[video pic] forState:UIControlStateNormal];
it doesn't behave like the one I created in IB at all. Nothing changes when I touch up inside.
Is there a settings in UIButton that I am missing?
Thanks
This is how to create a UIButton programatically.
//Specify the type of the button first. No need to use alloc-init for UIButton like other view objects.
UIButton *myBtn = [UIButton buttonWithType:UIButtonTypeCustom];
// Give UIButtonTypeRoundedRect to get default Interface builder style button.
myBtn.frame = CGRectMake(0, 0, 100, 40);
[self.view addSubview:myBtn];
// Since the button type is custom, give an image to make it visible.
[myBtn setBackgroundImage:[UIImage imageNamed:#"image.png"] forState:normal];
[myBtn addTarget:self action:#selector(myAction:) forControlEvents:UIControlEventTouchUpInside];
// These are some optional methods you may want to use.
myBtn.titleLabel.font = [UIFont fontWithName:#"Arial" size:15];
[myBtn setTitle:#"my button" forState:UIControlStateNormal];
[myBtn setTitleColor:[UIColor blackColor] forState:normal];
[myBtn setContentHorizontalAlignment:UIControlContentHorizontalAlignmentCenter];
I think you must enable one of this two options:
buttonPic.showsTouchWhenHighlighted = YES;
buttonPic.reversesTitleShadowWhenHighlighted = YES;

How can I have a UIBarButtonItem with both image and text?

When I try to use an image for a UIBarButtonItem, the text isn't shown. Is there a way to show both the text and the image?
You can init the UIBarButtonItem with a custom view that has both image and text. Here's a sample that uses a UIButton.
UIImage *chatImage = [UIImage imageNamed:#"08-chat.png"];
UIButton *chatButton = [UIButton buttonWithType:UIButtonTypeCustom];
[chatButton setBackgroundImage:chatImage forState:UIControlStateNormal];
[chatButton setTitle:#"Chat" forState:UIControlStateNormal];
chatButton.frame = (CGRect) {
.size.width = 100,
.size.height = 30,
};
UIBarButtonItem *barButton= [[[UIBarButtonItem alloc] initWithCustomView:chatButton] autorelease];
self.toolbar.items = [NSArray arrayWithObject:barButton];
I suggest a way how to do this using Storyboard:
Drag and drop to ToolBar usual UIView. It automatically will be wrapped to Bar Button Item. Adjust View width in "Size inspector". Change background color of View to clear color.
Put UIButton and UILabel inside a View. You can use constraints to adjust their positions. Also you can put thier outside of a View, for example, little higher or less (like on my picture). Put Default and Highlighted images for UIButton.
Copy Bar Button Item and adjust another buttons. Add Flexible spaces.
Create outlets.
Done :). When you run app, you get Tool Bar like this:
P.S. Here you can read how to create UIToolbar subclass using .xib
Swift 4.2 with target
extension UIBarButtonItem {
convenience init(image :UIImage, title :String, target: Any?, action: Selector?) {
let button = UIButton(type: .custom)
button.setImage(image, for: .normal)
button.setTitle(title, for: .normal)
button.frame = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)
if let target = target, let action = action {
button.addTarget(target, action: action, for: .touchUpInside)
}
self.init(customView: button)
}
}
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:[UIImage imageNamed:#"image.png"] forState:UIControlStateNormal];
[button addTarget:target action:#selector(buttonAction:)forControlEvents:UIControlEventTouchUpInside];
[button setFrame:CGRectMake(0, 0, 53, 31)];
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(3, 5, 50, 20)];
[label setFont:[UIFont fontWithName:#"Arial-BoldMT" size:13]];
[label setText:title];
label.textAlignment = UITextAlignmentCenter;
[label setTextColor:[UIColor whiteColor]];
[label setBackgroundColor:[UIColor clearColor]];
[button addSubview:label];
UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithCustomView:button];
self.navigationItem.leftBarButtonItem = barButton;
Kris Markel's answer is a good start (only < iOS7), but if you use tint color, it wount work for the image and the highlighted state of the button.
I've created a category that will create a UIBarButtonItem (leftBarButtonItem) that looks and behaves like a normal iOS7 back button. Have a look at: https://github.com/Zero3nna/UIBarButtonItem-DefaultBackButton
Swift Update for UIBarButtonItem with a custom view that has both image and text.
var chatImage: UIImage = UIImage(named: "YourImageName")
var rightButton : UIButton = UIButton(type: UIButtonType.custom)
rightButton.setBackgroundImage(rightImage, for: .normal)
rightButton.setTitle(title, for: .normal)
rightButton.frame.size = CGSize(width: 100, height: 30)
let menuUIBarButtonItem = UIBarButtonItem(customView: rightButton)