I'm creating custom UIView that contains two UILabels and UIButton so I created a subclass to make this possible.
Now the process looks like:
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
self.backgroundColor = [UIColor whiteColor];
self.settingsButton = [[UIButton alloc] initWithFrame:CGRectMake(frame.size.width - 2 * margin, frame.size.height - titleHeight - dateHeight, buttonSize, buttonSize)];
[self.settingsButton setImage:[UIImage imageNamed:#"settings_icon"] forState:UIControlStateNormal];
[self addSubview:self.settingsButton];
[self.settingsButton addTarget:self action:#selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
return self;
}
Button appears on UIView but it is not clickable. I tried to set self.userInteractionEnabled = YES; and a couple things but still no result :(
This is the most dumb mistake I've ever made. Transparent UINavigationBar was blocking the touch.
Related
I am unable to add button on UIView. I have UIView In which I want to add UIButton. Here is my code which I am trying to implement.
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setMultipleTouchEnabled:NO];
path = [UIBezierPath bezierPath];
[path setLineWidth:1.0];
_button = [UIButton buttonWithType:UIButtonTypeCustom];
[_button setTitle:#"" forState:UIControlStateNormal];
_button.userInteractionEnabled=YES;
_button.frame =CGRectMake(50, 130, 100, 100);
_button.backgroundColor =[ UIColor redColor];
[_button addTarget:self
action:#selector(buttonClicked)
forControlEvents:UIControlEventTouchUpInside];
[self addSubview:_button];
}
return self;
}
Your button is being added to the view. I just tried with your code line by line and I could see it. I think problem is in your UIView frame. Probably you are not seeing it because it is crossing the boundary of your super UIView.
Instead of assigning to __button, make a local UIButton object and work with it. After the local button has been added to the view, assign it to _button.
I am programmatically creating buttons in a view inside UIScrollView. I also have programmatically created UITextField. I can select and enter data into the text fields all day long. But I cannot get any sign the buttons are being touched. I can add them to the main view and they work. But when added to the view inside the UIScrollView, they are lost in another dimension. I've read plenty of info about setting userInteraction, delayContentTouches, and intercepting via gestureRecognizer. The last might be related to my problem. I return NO via [touch.view isDescendantOfView:self.myScrollViewName]. I can't get it to trigger via [touch.view isKindOfClass:[UIButton class]]. Which makes me think I have a more fundamental error I am missing?
related:
https://stackoverflow.com/a/6825839/4050489
edited to add button code per request:
self.myButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
self.myButton.frame = myButtonFrame;
self.myButton.enabled = interface.isActive;
self.myButton.userInteractionEnabled = YES;
self.myButton.exclusiveTouch = YES;
self.myButton.backgroundColor = [UIColor greenColor];
//self.myButton. = YES;
self.myButton.layer.borderWidth=1.0f;
self.myButton.layer.borderColor=[[UIColor blackColor] CGColor];
self.myButton.layer.cornerRadius = 10;
[self.myButton setTag:interface.tag];
[self.myButton setTitle:interface.Name forState:UIControlStateNormal];
[self.myButton addTarget:self action:#selector(navigatePartButtons:) forControlEvents:UIControlEventTouchUpInside];
[self.myButton setEnabled:YES]; //error check
[self.partSetupView addSubview:self.myButton];
partSetupView is a UIView in the UIScrollView.
Try this sample Code:
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIScrollView *myScroll = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 100, 300, 300)];
myScroll.backgroundColor = [UIColor redColor];
[self.view addSubview:myScroll];
UIView *myView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 300, 200)];
myView.backgroundColor = [UIColor yellowColor];
[myScroll addSubview:myView];
UIButton *myButton = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 300, 100)];
myButton.backgroundColor = [UIColor blackColor];
[myView addSubview:myButton];
[myButton addTarget:self action:#selector(btnClick) forControlEvents:UIControlEventTouchDown];
}
-(void)btnClick{
NSLog(#"Button Click");
}
#end
I need to create a view like below from the array of emails that I receive which also has the delete option.
Something similar to that of gmail's mail recipient except in my this should be scrollview. My main issue is to create the background with delete button which stretches based on the email length. My current approach is to use 3 images one for the beginning, one for the end with delete button and one in general for middle that will stretch. Is there any other or better way to do this?
NOTE:Need to support from iOS 5 and above
Here you go, I have created a SuperLabel for you though it might need some tweak.. But it will help you for sure..
SuperLabel.h
#import <UIKit/UIKit.h>
#interface SuperLabel : UIView
- (id)initWithFrame:(CGRect)frame andTitle:(NSString *)title;
#end
SuperLabel.m
#import "SuperLabel.h"
#define MAX_HEIGHT 25.0
#implementation SuperLabel
- (id)initWithFrame:(CGRect)frame andTitle:(NSString *)title
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
//Design your label view
self.backgroundColor=[UIColor colorWithRed:.8 green:.8 blue:.8 alpha:1.0];
self.layer.borderColor=[[UIColor orangeColor] CGColor];
self.layer.borderWidth=1.0;
self.layer.cornerRadius=5.0;
//Add a Label
UILabel *label=[[UILabel alloc] initWithFrame:CGRectMake(5.0, 5.0, 100.0, MAX_HEIGHT)];
label.font=[UIFont systemFontOfSize:12.0];
label.textColor=[UIColor grayColor];
label.text=title;
[label sizeToFit];
[self addSubview:label];
//We will get resized frame after using sizeToFit after setting the text in the label.
CGRect rect=label.frame;
//Add a button
UIButton *btn=[UIButton buttonWithType:UIButtonTypeCustom];
[btn setTitle:#"x" forState:UIControlStateNormal];
btn.titleLabel.font=[UIFont systemFontOfSize:12.0];
btn.titleLabel.textColor=[UIColor grayColor];
rect.origin.x=rect.origin.x+rect.size.width;
rect.origin.y=0;
rect.size=CGSizeMake(25.0, MAX_HEIGHT);
[self addSubview:btn];
[btn addTarget:self action:#selector(deleteMe:) forControlEvents:UIControlEventTouchDragInside];
btn.frame=rect;
//Change the whole frame of the label view
frame.size.height=MAX_HEIGHT;
frame.size.width=btn.frame.origin.x+btn.frame.size.width;
self.frame=frame;
}
return self;
}
-(IBAction)deleteMe:(id)sender{
[self removeFromSuperview];
}
#end
And finally add to your view by using following code..
SuperLabel *label=[[SuperLabel alloc] initWithFrame:CGRectZero andTitle:#"myemail#gmail.com"];
[self.view addSubview:label];
Cheers..
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
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.