UIButton as a subview not responding - ios

I have a UIButton inside of a UIView inside of a UIImageView that is not responding to touches. I can't figure out why. I've broken the code down to its simplest form while still doing what my original program does.
#import "TestVideoViewController.h"
#interface TestVideoViewController ()
#property (strong, nonatomic)UIImageView *panel;
#property (strong, nonatomic)UIView *panelSC;
#property (strong, nonatomic)UIButton *panelButtonSC;
#property (strong, nonatomic)UIButton *videoButton;
#end
#implementation TestVideoViewController
-(void) viewDidLoad {
_panelButtonSC = [UIButton buttonWithType:UIButtonTypeCustom];
[_panelButtonSC addTarget:self action:#selector(buttonPressedSC:) forControlEvents:UIControlEventTouchUpInside];
[_panelButtonSC setTitle:#"Open" forState:UIControlStateNormal];
_panelButtonSC.frame = CGRectMake(511, 701, 66, 67);
_panel = [[UIImageView alloc] initWithFrame:CGRectMake(100, 768, 824, 600)];
_panel.backgroundColor = [UIColor whiteColor];
_panelSC = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 784, 560)];
_panelSC.backgroundColor = [UIColor whiteColor];
_videoButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_videoButton addTarget:self action:#selector(playVideo:) forControlEvents:UIControlEventTouchUpInside];
[_videoButton setTitle:#"Play" forState:UIControlStateNormal];
[_videoButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
_videoButton.frame = CGRectMake(400, 400, 200, 40);
[_panelSC addSubview:_videoButton];
[_panel addSubview:_panelSC];
[self.view addSubview:_panel];
[self.view addSubview:_panelButtonSC];
}
- (IBAction)buttonPressedSC:(UIButton*)sender {
[self animatePanelUp];
}
- (IBAction)playVideo:(UIButton*)sender {
NSLog(#"play video");
}
- (void) animatePanelUp {
[UIView animateWithDuration: 0.5
delay: 0.0
options: UIViewAnimationOptionCurveEaseIn
animations:^{
_panel.frame = CGRectMake(47, 166, 929, 602);
}
completion:nil];
}
#end
I've looked at every similar answer here. To the best of my knowledge all of my framing is correct. There has got to be something simple and stupid that I'm missing. Why doesn't the "playVideo" method ever fire? The only time it works is if I add the button directly to self.view.

UIImageView keeps userInteractionEnabled as false by default - add following line of code it will work.
_panel.userInteractionEnabled = true;

As you are adding a few subview upon one another, check that your button is clickable and no other subview is eating up the touch event, and overall make sure that your views are user action enabled.
Hint:
There might have some problem with the imageview used, as it will have user interaction disabled by default.
Use UIView instead or do this:
_panelSC.userInteractionEnabled = true;

Make sure user interaction is enabled of the parent view. UIImageView by default has userInteractionEnabled false.
_panel.userInteractionEnabled = true

Related

How to set the default image to UIButton in Viewdidload in Objective-C?

I try to set Image for a UIButton. But how to set the default image for UIButton ?
The code of UIButton in header file is like the following.
#property (strong, nonatomic) IBOutlet UIButton *modeChangeButton;
And I try to set the image size and default image for UIButton , but it doesn't show the image. The code is like the following.
- (void)viewDidLoad
{
self.modeChangeButton = [[UIButton alloc] initWithFrame:CGRectMake(200, 450, 60, 60)];
[self.modeChangeButton setBackgroundImage:[UIImage imageNamed:#"recordmode.png"] forState:UIControlStateNormal];
}
how to set the default image for UIButton ?
Thanks in advance.
If you are using IBOutlet, you no need to reallocate your button. Please try as below
Using IBOutlet :
- (void)viewDidLoad
{
self.modeChangeButton.frame = CGRectMake(200, 450, 60, 60);
[self.modeChangeButton setBackgroundImage:[UIImage imageNamed:#"recordmode.png"] forState:UIControlStateNormal];
}
Using Programmatically:
- (void)viewDidLoad
{
self.modeChangeButton = [[UIButton alloc] initWithFrame:CGRectMake(200, 450, 60, 60)];
[self.modeChangeButton setBackgroundImage:[UIImage imageNamed:#"recordmode.png"] forState:UIControlStateNormal];
[self.view addSubView:self.modeChangeButton];
}
Also, Check your Y position of your button. Whether it is out of view frame.
You forgot to add your button as a subview.
[self.view addSubview:self.modeChangeButton];
- (void)viewDidLoad
{
[super viewDidLoad];
self.modeChangeButton = [[UIButton alloc] initWithFrame:CGRectMake(200, 450, 60, 60)];
[self.modeChangeButton setBackgroundImage:[UIImage imageNamed:#"recordmode.png"]
forState:UIControlStateNormal];
}
You have missed calling viewDidLoad of super. I am guess that might be the issue.

UITableViewController as a subview getting error

I have a UIViewController which is being loaded onto my UIViewController as a subview, however I am getting this error
Property 'frame' not found on object of type 'mynamedTableViewController *'
This is what my code looks like for the UIViewController.
.h
#import <UIKit/UIKit.h>
#import "FilterButtonsTableViewController.h"
#interface MainFilterViewController : UIViewController
#property (strong, nonatomic) UIButton *applyButton;
#property (strong, nonatomic) UIButton *cancelButton;
#property (strong, nonatomic) UIButton *clearAllButton;
#property (strong, nonatomic) FilterButtonsTableViewController *filterButtonsTableViewController;
#end
.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
// add header label
UILabel *noteHeaderLabel = [[UILabel alloc] initWithFrame:CGRectMake(25.0, 0.0, 200.0, 45.0)];
noteHeaderLabel.backgroundColor = [UIColor clearColor];
noteHeaderLabel.textColor = [UIColor lightGrayColor];
// dynamic using whatViewName
noteHeaderLabel.text = #"Filter";
[self.view addSubview:noteHeaderLabel];
// add underlines
// top
UIView *topUnderline = [[UIView alloc] initWithFrame:CGRectMake(0.0, 45.0, self.view.frame.size.width, 1.0)];
topUnderline.backgroundColor = [UIColor lightGrayColor];
topUnderline.alpha = 0.8;
// bottom
UIView *bottomUnderline = [[UIView alloc] initWithFrame:CGRectMake(0.0, self.view.frame.size.height-45.0, self.view.frame.size.width, 1.0)];
bottomUnderline.backgroundColor = [UIColor lightGrayColor];
bottomUnderline.alpha = 0.8;
// addviews
[self.view addSubview:topUnderline];
[self.view addSubview:bottomUnderline];
// add buttons to view
// apply
applyButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
applyButton.userInteractionEnabled = YES;
[applyButton addTarget:self action:#selector(alertViewSelected:) forControlEvents:UIControlEventTouchDown];
[applyButton setTitle:#"Save" forState:UIControlStateNormal];
applyButton.frame = CGRectMake(self.view.frame.size.width - 130, self.view.frame.size.height - 43, 120.0, 40.0);
[self.view addSubview:applyButton];
// cancel
cancelButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
cancelButton.userInteractionEnabled = YES;
[cancelButton setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
[cancelButton addTarget:self action:#selector(alertViewSelected:) forControlEvents:UIControlEventTouchUpInside];
[cancelButton setTitle:#"Cancel" forState:UIControlStateNormal];
cancelButton.frame = CGRectMake(self.view.frame.size.width - 260, self.view.frame.size.height - 43, 120.0, 40.0);
[self.view addSubview:cancelButton];
// cancel
clearAllButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
clearAllButton.userInteractionEnabled = YES;
[clearAllButton setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
[clearAllButton addTarget:self action:#selector(alertViewSelected:) forControlEvents:UIControlEventTouchUpInside];
[clearAllButton setTitle:#"Clear filter" forState:UIControlStateNormal];
clearAllButton.frame = CGRectMake(0.0, self.view.frame.size.height - 43, 120.0, 40.0);
[self.view addSubview:clearAllButton];
//TavleView
filterButtonsTableViewController = [[[FilterButtonsTableViewController alloc] init];
filterButtonsTableViewController.frame:CGRectMake(5.0, 65.0, (self.view.frame.size.width/2)-10, 235.0);
[self.view addSubview:filterButtonsTableViewController.view];
}
A viewcontroller does not have a frame property, only its view does.
Try this instead :
filterButtonsTableViewController.view.frame = CGRectMake(5.0, 65.0, (self.view.frame.size.width/2)-10, 235.0);
#interface MainFilterViewController : UIViewController
filterButtonsTableViewController = [[FilterButtonsTableViewController alloc] init];
[self.view addSubview:filterButtonsTableViewController.view];
// this code helps you to add tableview controller as a sub view.
#interface FilterButtonsTableViewController
self.view.frame=CGRectMake(0, 50, 150, 150);
// frame of the tableviewController is set on his class.

Cannot hide programmatically created UIButton

This issue is baffling me for a few days now.
I have 2 UIButtons, one created using the Storyboard and one created programmatically.
When I press one of the buttons, I am moved to a method that hides both the programatically built and storyboard buttons, but only the storyboard button disappears, whereas the programmatically built button remains. I have tried not only hiding but also changing the frame of the programmatically built button, but to no avail.
Here is the code used:
#property (strong, nonatomic) UIButton *catBut;
#property (weak, nonatomic) IBOutlet UIButton *whenButton;
....
....
-(void)viewDidLoad {
....
[self customizeButton:self.catBut withFrame:CGRectMake(165, 113, 135, 50)
andAction:#selector(selectedCat) andColor:[UIColor belizeHoleColor]
andTag:2 andImage:#"coffee-64.png" andText:#"Cafes" andAlignmentLeft:YES];
....
}
- (void)customizeButton:(UIButton *)but withFrame:(CGRect)rect andAction:(SEL)action
andColor:(UIColor *)col andTag:(NSUInteger)tag
andImage:(NSString *)imageName
andText:(NSString *)buttonText
andAlignmentLeft:(BOOL)alignLeft {
but = [UIButton buttonWithType:UIButtonTypeCustom];
[but setFrame:rect];
[but setTitle:buttonText forState:UIControlStateNormal];
but.tag = tag;
but.titleLabel.numberOfLines = 0;
but.titleLabel.font = [UIFont boldFlatFontOfSize:18];
[but setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
CGFloat spacing = 10; // the amount of spacing to appear between image and title
but.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
but.imageEdgeInsets = UIEdgeInsetsMake(0, spacing, 0, 0);
but.titleEdgeInsets = UIEdgeInsetsMake(0, spacing*2, 0, 0);
[but setTitleColor:[UIColor cloudsColor] forState:UIControlStateNormal];
[but setTitleColor:[UIColor cloudsColor] forState:UIControlStateHighlighted];
[but addTarget:self action:action forControlEvents:UIControlEventTouchUpInside];
[self.buttonsView addSubview:but];
}
....
- (void)selectedCat {
self.catBut.hidden = YES;
self.whenButton.hidden = YES;
}
Why is only the Storyboard button compliant to UI changes? Is there something I am missing? I have tried cancelling the AutoLayout but that didn't change a thing.
The issue is with the passing for argument in your method (customizeButton:(UIButton *)but).
Change your code to this and check
but = [UIButton buttonWithType:UIButtonTypeCustom];
to
self.catBut = [UIButton buttonWithType:UIButtonTypeCustom];
......
[self.buttonsView addSubview:self.catBut];
OR You should pass the address customizeButton:(UIButton **)but in the method
and while calling use &self.catBut
It is BOOL type, not an bool type.
try this
self.catBut.hidden = YES;
self.whenButton.hidden = YES;
I can see this property catBut, But I cann't see creation for this, as well I didn't give Outlet too. Check this. You've tried something but simply fix by following line.
[self.buttonsView addSubview:but];
self.catBut = but;

Drawing a line between two UIlabels when tapped or pressed together

I want to draw a line between two UILabels when i tap or hold both of them at the same time with code, i have no idea how to do this, it will be most appreciated if anyone has an advice , it will be most appreciated
This is how I would do it. My answer is tested btw...
To manage the tappable labels I would create my own label called LabelControl that extends UIControl. This custom control is going to have a UILabel (read-only for simplicity) as a subview. By doing this we will be able to add the Target-Action events UIControlEventTouchDown and UIControlEventTouchUpInside.
Here is the custom label:
The .h file:
#interface LabelControl : UIControl
#property (nonatomic, retain, readonly) UILabel *theLabel;
#end
The .m file:
#implementation LabelControl
#synthesize theLabel = _theLabel;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
_theLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
_theLabel.backgroundColor = [UIColor clearColor];
_theLabel.userInteractionEnabled = NO;
[self addSubview:_theLabel];
}
return self;
}
-(void)dealloc {
[_theLabel release];
[super dealloc];
}
Then for the "line" that you want to draw, I would use a UIView because that way you could just use it's hidden property to hide/show the line. Add this code inside your ViewController:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.label1 = [[[LabelControl alloc] initWithFrame:CGRectMake(60, 50, 200, 40)] autorelease];
self.label1.theLabel.text = #"Hello";
self.label1.userInteractionEnabled = YES;
self.label1.backgroundColor = [UIColor blueColor];
[self.label1 addTarget:self action:#selector(touchDown:) forControlEvents:UIControlEventTouchDown];
[self.label1 addTarget:self action:#selector(touchUp:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.label1];
self.label2 = [[[LabelControl alloc] initWithFrame:CGRectMake(60, 150, 200, 40)] autorelease];
self.label2.theLabel.text = #"World";
self.label2.userInteractionEnabled = YES;
self.label2.backgroundColor = [UIColor purpleColor];
[self.label2 addTarget:self action:#selector(touchDown:) forControlEvents:UIControlEventTouchDown];
[self.label2 addTarget:self action:#selector(touchUp:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.label2];
//the position of the line is hard-coded. You will have to modify this yourself
self.theLine = [[UIView alloc] initWithFrame:CGRectMake(60, 120, 200, 3)];
self.theLine.backgroundColor = [UIColor blueColor];
self.theLine.hidden = YES;
[self.view addSubview:self.theLine];
}
-(void)showOrHideLine {
if (self.label1.selected && self.label2.selected) {
NSLog(#"Both are selected");
self.theLine.hidden = NO;
} else {
self.theLine.hidden = YES;
}
}
-(void)touchDown:(id)sender {
//When any of the custom label gets the touch down event set the `selected` property
//to YES. (This property is inherited form `UIControl`
NSLog(#"Touch down");
LabelControl *labelControl = (LabelControl*)sender;
labelControl.selected = YES;
[self showOrHideLine];
}
-(void)touchUp:(id)sender {
//When any of the custom label gets the touch up event set the `selected` property
//to NO. (This property is inherited form `UIControl`
NSLog(#"Touch Up");
LabelControl *labelControl = (LabelControl*)sender;
labelControl.selected = NO;
[self showOrHideLine];
}
Let me know if you have any questions. Hope this helps!
I am going to outline it and give you some code (untested) but you have some work to make the full effect work.
Programtically, you could subclass UIButton. Inside your new subclass, put your touch recognition methods. Call it something like "customUIButton".
From your main view controller, create two instances of your UIButton and add them as subviews
customUIButton *Label1 = [[customUIButton alloc] init];
[Label1 setTitle:#"Your First Label" forState:UIControlStateNormal];
[Label1 addTarget:self action:#selector(itemClicked:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:Label1];
customUIButton *Label2 = [[customUIButton alloc] init];
[Label2 setTitle:#"Your Second Label" forState:UIControlStateNormal];
[Label2 addTarget:self action:#selector(itemClicked:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:Label1];
When you push the buttons, it will try to call the method "itemClicked". Make that method and receive (id)sender... - (void)itemClicked: (id)sender { Put some logic in there to indicate that the button is being pushed. You know which button by referring to the sender that was sent.
Also in your view controller, go to the DrawRect method and put in the drawing logic.
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 3.0);
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGContextMoveToPoint(context, Label1.center.x, Label1.center.y);
CGContextAddLineToPoint(context, Label2.center.x, Label2.center.y);
CGContextStrokePath(context);
CGContextRestoreGState(context);
Put this in an "if statement" so that if both buttons have focus, it will be drawn (else skip the drawing code).
How about placing a line in IB using an Image View. Hide the Image View in your viewDidLoad method. Then, whenever the user taps one of the the UILabels, unhide the Image View holding your line. It may be tricky depending on your experience with Objective-C to detect touches on a UILabel. If it is, you can place invisible buttons over each label and that should do the trick for you. For more info about detecting touches on UILabels, check this link:
Handling Touch Event in UILabel and hooking it up to an IBAction

Subview of custom UIButton class doesn't trigger click

I'm writing a custom UIButton subclass, to create my own fully customized button
to have total controll. Still, I'm having problems when I try to add a subview
to that UIButton's view. The subview blocks the "touch" events so it won't bubble to
the UIButton itself..
This is a demonstration:
I first create my CustomNavigationButton, with a frame.. It's magenta.
I can see the magenta on the screen so it's there. Secondly, I add a subview
to that CustomNavigationButton (which is green), I can see the green so it's
there, but if I click the green rectangle (subview), the "UIControlEventTouchUpInside"
doesn't get called on my CustomNavigationButton..
In my AppDelete:
CustomNavigationButton* mapBtn = [[CustomNavigationButton alloc] initWithFrame:CGRectMake(0, 0, 100, 25)];
mapBtn.backgroundColor = [UIColor magentaColor];
[mapBtn addTarget:self action:#selector(goMapHandler:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:mapBtn];
And here's my CustomNavigationButton class (which is a subclass of UIButton)
#implementation CustomNavigationButton
#synthesize bg;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// STORE INITIAL FRAME
self.initialFrame = frame;
bg = [[UIView alloc] initWithFrame:CGRectMake(0, 20, 40, 40)];
bg.backgroundColor = [UIColor greenColor];
[bg setUserInteractionEnabled:YES];
[self addSubview:bg];
}
return self;
}
#end
I figured out how to do it!
If "bg" is the subview I'm adding to the UIButton, then you should do:
bg.userInteractionEnabled = NO;
bg.exclusiveTouch = NO;
But keep in mind that, if your subview extends the frame of the UIButton,
a touch will not occur! You can check if your subview exceeds the UIButton
by giving the UIButton a background-color.

Resources