i have a scrollview and inside a uiview that contains multiple subviews ( uiimageview). the problem is i can't pass touch gestures to the imageviews ..
#interface photoLibrary (){
UIView *view_cuImagini;
}
#property (nonatomic,retain) UIScrollView *scrl_images;
#end
#implementation photoLibrary
#synthesize scrl_images;
//..
- (void)viewDidLoad{
[super viewDidLoad];
//...
scrl_images.minimumZoomScale=0.4;
view_cuImagini=[[UIView alloc]initWithFrame:CGRectMake(scrl_images.frame.origin.x, scrl_images.frame.origin.y, scrl_images.frame.size.width, scrl_images.frame.size.height)];
view_cuImagini.backgroundColor=[UIColor blackColor];
[scrl_images addSubview:view_cuImagini];
}
-(void)AddImageViewWithFrame:(CGRect)frame andImage:(UIImage*)img andtag:(int)tag{
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imageTapped:)];
tempimg=[[UIImageView alloc] initWithFrame:frame];
UIImageView *bifat = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"bifat.jpg"]];
tempimg.image=img;
tempimg.tag=tag;
tap.delegate=self;
tempimg.userInteractionEnabled = YES;
view_cuImagini.userInteractionEnabled=YES;
[tempimg addGestureRecognizer:tap];
// [self.view addGestureRecognizer:tap];
[tempimg addSubview:bifat];
[view_cuImagini addSubview:tempimg];
}
-(void)imageTapped:(UITapGestureRecognizer *)rec{
if (rec.state==UIGestureRecognizerStateRecognized) {
NSLog(#"imageTouch with tag %i",rec.view.tag);
}
i want to be able to find the which tempimg was touched
does anybody has a solutions for this?
Related
I use UITapGestureRecognizer to handle An ImageviewTap actions. In the main ViewController it works great. But when i Use another ViewController in my APP, and copy the same UITapRecognizer code I get an EXC_BAD_ACCESS code=1 address: 0x80759d3a error message to the line when i add the recognizer to my imageview. What do I wrong?
My ImageView: It works
UIImageView *live;
live = [[UIImageView alloc]initWithFrame:CGRectMake(92, 230, 136, 100)];
live.image = [UIImage imageNamed:#"online.png"];
[live addSubview:onlineLabel2];
[live setUserInteractionEnabled:YES];
[self.view addSubview:live];
[super viewDidLoad];
and my Gesture Recognizer:
UITapGestureRecognizer *singleTaP3 = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(onlineTap:)];
singleTaP3.numberOfTapsRequired = 1;
singleTaP3.numberOfTouchesRequired = 1;
[live addGestureRecognizer:singleTaP3];
and the last line i get the crash.
It sounds like your live view is not retain, so when you try to add the gesture, the view doesn't exist anymore. Try to record your live view as a property in your interface, and synthetise it in your implementation.
I am not sure if that this causing you to crash your code but you should call
[super viewDidLoad];
at the start of the code. (If you are using ARC than this looks fine.)
[super viewDidLoad];
UIImageView *live;
live = [[UIImageView alloc]initWithFrame:CGRectMake(92, 230, 136, 100)];
live.image = [UIImage imageNamed:#"online.png"];
[live addSubview:onlineLabel2];
[live setUserInteractionEnabled:YES];
[self.view addSubview:live];
I test the following and it works.
The interface:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (strong, nonatomic) UIView *v;
- (void)tapAction;
#end
And the implementation:
#import "ViewController.h"
#implementation ViewController
#synthesize v=_v;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_v = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 50, 50)];
[_v setBackgroundColor:[UIColor redColor]];
[self.view addSubview:_v];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapAction)];
tap.numberOfTouchesRequired = 1;
tap.numberOfTapsRequired = 1;
[_v addGestureRecognizer:tap];
}
- (void)tapAction
{
NSLog(#"tap tap");
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
My problem was in my main viewcontroller. I called the new viewcontroller wrong, and get nullpointer for it. Get it in property, and it works. The problem is not with gesturetaprecognizer.
I'm using XCode 4.5.1 .
I added <UIGestureRecognizerDelegate> in .h file and in the start of .m file
#interface FirstViewController ()
#property (nonatomic, strong) UIImageView *img1;
#end
Then in viewDidLoad, creating UIImageView programmatically like
self.img1 = [[UIImageView alloc] initWithFrame:CGRectMake(50, -30, 44, 44)];
[self.img1 setImage:[UIImage imageNamed:#"image1.png"]];
[self.img1 setAlpha:0.8];
[self.img1 setHidden:NO];
[self.img1 setUserInteractionEnabled:YES];
[self.img1 setTag:901];
And then
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(guessTapObject:)];
tap.numberOfTapsRequired = 1;
tap.numberOfTouchesRequired = 1;
tap.delegate = self;
[self.img1 addGestureRecognizer:tap];
[self.view addSubview:self.img1];
[self.view bringSubviewToFront:self.img1];
and at the end
- (void)guessTapObject:(UITapGestureRecognizer *) gesture
{
// guessing the image
UIImageView *tapImageView = (UIImageView*) gesture.view;
NSLog(#"Gesture Tag: %d", tapImageView.tag);
}
I have 4 different images and creating them programmatically as described above. And applying the animation to move them from top to bottom.
I want that when user tap on the image, it should animate and disappear(i know that code). But the code is not triggering the tap event. I put the breakpoint on the start of the guessTapObject function, but don't go there ever.
At UITapGestureRecognizer declaration, debugging shows that guessTapObject is attached to the recognizer to perform the tap action.
Please help why tap event is not triggering its selector method???
Thanks for your help in advance.
Edited:
i also tried with for loop to have gesture recognizer separately for every imageview
for (UIView * view in self.view.subviews) {
if (view.tag > 900){
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(guessTapObject:)];
tap.numberOfTapsRequired = 1;
tap.numberOfTouchesRequired = 1;
// tap.delegate = self;
[view addGestureRecognizer:tap];
NSLog(#"tapView: %#", tap.view);
NSLog(#"tap: %i", tap.enabled);
}
}
I was stuck in similar issue.. Make sure imageView is set true for userInteraction..
imageView.userInteractionEnabled = YES;
It worked for me!
Check this
Add following code to your View Controller
In viewController.h file
#property (nonatomic, strong) UIImageView *img1;
#property (nonatomic, strong) UIImageView *img2;
#property (nonatomic, strong) UIImageView *img3;
In viewController.m file
Inside viewDidLoad Method
// Init Image 1
self.img1 = [[UIImageView alloc] initWithFrame:CGRectMake(50, 30, 44, 44)];
[self.img1 setImage:[UIImage imageNamed:#"image1_name.jpg"]];
[self.img1 setAlpha:0.8];
[self.img1 setHidden:NO];
[self.img1 setUserInteractionEnabled:YES];
[self.img1 setTag:901];
// Init Image 2
self.img2 = [[UIImageView alloc] initWithFrame:CGRectMake(100, 30, 44, 44)];
[self.img2 setImage:[UIImage imageNamed:#"image2_name.jpg"]];
[self.img2 setAlpha:0.8];
[self.img2 setHidden:NO];
[self.img2 setUserInteractionEnabled:YES];
[self.img2 setTag:902];
// Init Image 3
self.img3 = [[UIImageView alloc] initWithFrame:CGRectMake(50, 130, 44, 44)];
[self.img3 setImage:[UIImage imageNamed:#"image3_name.jpg"]];
[self.img3 setAlpha:0.8];
[self.img3 setHidden:NO];
[self.img3 setUserInteractionEnabled:YES];
[self.img3 setTag:903];
// Add Images to view
[self.view addSubview:self.img1];
[self.view bringSubviewToFront:self.img1];
[self.view addSubview:self.img2];
[self.view bringSubviewToFront:self.img2];
[self.view addSubview:self.img3];
[self.view bringSubviewToFront:self.img3];
// Set Tap Gesture to each image of view
for (UIView * view in self.view.subviews) {
if (view.tag > 900){
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(guessTapObject:)];
tap.numberOfTapsRequired = 1;
tap.numberOfTouchesRequired = 1;
[view addGestureRecognizer:tap];
NSLog(#"tapView: %#", tap.view);
NSLog(#"tap: %i", tap.enabled);
}
}
Make sure images should be added before for loop(adding TapGesture using array of subview)
i solved by applying gesture on view, instead of each image view separately.
[self.view addGestureRecognizer:tap];
and then in handler/selector guessTapObject function, i used this
CGPoint tapLocation = [gesture locationInView:self.view]; // gives the tap coordinates
for (UIView * view in self.view.subviews) { // gives view by iterating on each subview
CGRect dropRect = [[[view layer] presentationLayer] frame]; // specific way of getting the frame with respect to its layer
if(CGRectContainsPoint(dropRect, tapLocation)){ // checks for tap in the boundaries of view frame
if (view.tag > 900) // my specific view
// done what i want to do with that specific one
// as i removed it from my superview
}
}
}
I am trying to use a UIPageControl with my UIScrollView. It seems that i'm doing something improperly cause the page is always set to one.
This is my ViewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
scrollView.delegate = self;
UIImageView *imgView1 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"tutorialScreen1.png"]];
imgView1.frame = CGRectMake(0, 0, 320, 436);
[scrollView addSubview:imgView1];
UIImageView *imgView2 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"tutorialScreen2.png"]];
imgView2.frame = CGRectMake(320, 0, 320, 436);
[scrollView addSubview:imgView2];
UIImageView *imgView3 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"tutorialScreen3.png"]];
imgView3.frame = CGRectMake(640, 0, 320, 436);
[scrollView addSubview:imgView3];
scrollView.contentSize = CGSizeMake(960, 436);
pageControl = [[UIPageControl alloc] init];
[pageControl setNumberOfPages:3];
[pageControl setCurrentPage:0];
}
And here is my UIScrollView Delegate Method:
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollViewx{
NSLog(#"%f",scrollView.contentOffset.x);
NSLog(#"%f",(scrollViewx.contentOffset.x / 320));
pageControl.currentPage = ((scrollViewx.contentOffset.x / 320));
}
And here is y .h file:
#interface TutorialViewController : UIViewController <UIScrollViewDelegate>
#property (nonatomic,strong) IBOutlet UIScrollView *scrollView;
#property (nonatomic,strong) IBOutlet UIPageControl *pageControl;
#end
Does anyone have an idea why it doesn't change? Of course i made sure my UIPageControl is connected to its instance.
Appreciate your help...
OK. the dot isn't changing because you've created a new UIPageControl instead of using the one you set up in IB. Take out: pageControl = [[UIPageControl alloc] init];
I have 2 UIButtons setup(+/-) when tapped, the number changes by one within a UILabel. What do I need to do to have multiple UILabels and when one is touched I can change its current value with the UIButton(+/-)?
Have a variable that you use as the active label, then add a gesture recognizer to both the UIlabels to capture taps:
label.userInteractionEnabled = YES;
UIGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapRecieved:)];
[label addGestureRecognizer:tap];
[tap release];
//repeat for each additional label
Then in your tapReceived method, swap out the active label
-(void) tapRecieved:(UITapGestureRecognizer *)tap{
currentLabel = (UILabel *) tap.view;
}
Then in the method that you capture clicks to the +/- button, write to currentLabel
Edit: A quick and dirty implementation of your problem. In interface builder I made 2 labels and a button and hooked them up. When you tap a label, it becomes the currentLabel and when you tap the button, whichever label you chose is incremented by 1. Hope it helps.
.h
#import <UIKit/UIKit.h>
#interface junkViewController : UIViewController {
UILabel *label;
UILabel *label2;
UILabel *currentLabel;
int label1Value;
int label2Value;
}
#property (nonatomic, retain) IBOutlet UILabel *label;
#property (nonatomic, retain) IBOutlet UILabel *label2;
- (IBAction)buttonTap:(id)sender;
#end
.m
#import "junkViewController.h"
#implementation junkViewController
#synthesize label;
#synthesize label2;
- (void)dealloc
{
[label release];
[label2 release];
[super dealloc];
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
/*
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
[super viewDidLoad];
}
*/
-(void) tapRecieved:(UITapGestureRecognizer *)tap{
currentLabel = (UILabel *)tap.view;
NSLog(#"tap %#",tap.view);
}
-(void) viewDidLoad{
currentLabel = label;
label.text = [NSString stringWithFormat:#"%d",label1Value];
label2.text = [NSString stringWithFormat:#"%d",label2Value];
label.userInteractionEnabled = YES;
UIGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapRecieved:)];
[label addGestureRecognizer:tap];
[tap release];
tap = nil;
tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapRecieved:)];
label2.userInteractionEnabled = YES;
[label2 addGestureRecognizer:tap];
[tap release];
}
- (void)viewDidUnload
{
[self setLabel:nil];
[self setLabel2:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (IBAction)buttonTap:(id)sender {
int value = [currentLabel.text intValue] + 1;
currentLabel.text = [NSString stringWithFormat:#"%d",value];
}
#end
I had to do something similar recently for a dynamically created menu in my app. This worked well:
In the menu creation method:
#define NAV_WIDTH 220
#define NAV_HEIGHT 220
#define NAV_TOP_HEIGHT 16
#define NAV_ITEM_HEIGHT 30
#define NAV_BOTTOM_HEIGHT 24
#define NAV_LABEL_MARGIN 20
[navPage setFrame: CGRectMake(navLeftCorner, navTopCorner, NAV_WIDTH, NAV_HEIGHT)];
NSArray *menuTitles = [[NSArray alloc] initWithObjects: #"One", #"Two", #"Three", #"Four", nil];
int tag = 1;
double labelTop = NAV_TOP_HEIGHT;
for (NSString *title in menuTitles) {
UILabel *itemLabel = [[UILabel alloc] initWithFrame: CGRectMake(NAV_LABEL_MARGIN, labelTop, NAV_WIDTH - (NAV_LABEL_MARGIN * 2), NAV_ITEM_HEIGHT)];
[itemLabel setUserInteractionEnabled: YES];
UITapGestureRecognizer *menuTap = [[UITapGestureRecognizer alloc] initWithTarget: self action: #selector(menuTapped:)];
[itemLabel addGestureRecognizer: menuTap];
[itemLabel setText: title];
[itemLabel setTag: tag];
[navPage addSubview: itemLabel];
labelTop += NAV_ITEM_HEIGHT;
tag++;
}
. . . which calls this when tapped:
- (void) menuTapped: (UITapGestureRecognizer *)tap
{
UILabel *currentLabel = (UILabel *) tap.view;
int index = (currentLabel.tag - 1);
/* Do stuff based on the tag index */
}
NOTE: This is the ARC-compliant way; add [itemLabel release] after adding to the subview if you're not using ARC.
I am bit stack with creating two UIViews which are switchable (each UIView has some of subviews). Since I do not IB, I wanna do that programmatically.
I have tried adding my subviews to my first UIView, then the same with second one and then switching to view like this.
if ([self.setView superview]) {
[self.setView removeFromSuperview];
[self.view addSubview:contentView];
self.navigationItem.title = #"BaseLine";
} else {
[self.contentView removeFromSuperview];
self.view = setView;
self.navigationItem.title = #"Settings";
}
but only thing which works correctly was "title" and nothing appeared on the UIViews. The UIView seems to be OK because when I use
self.view = contentView;
or
self.view = setView;
both showing subviews correctly.
Pls someone kick me to the right direction about this.
tnx
EDIT:
Also pointing the solution, perhaps something wrong with my initialization in the loadView
CGRect screenRect = [[UIScreen mainScreen] applicationFrame];
contentView = [[UIView alloc] initWithFrame:screenRect];
setView = [[UIView alloc] initWithFrame:screenRect];
self.view = contentView;
I tried to add it first [self. view add..] but the app crashed, so I used this
EDIT2
the root controller is UITableViewController..it is in navigation view and after choosing a cell this UIVieController (percView) with two UIVies is allocated
ShakeControl *percView = [[ShakeControl alloc] init];
[self.navigationController pushViewController:percView animated:YES];
[percView release];
EDIT3
switch is done by button, but it is fine done because I used that many times and it worked
Here is an example of a view controller that does what you want (I think). It is very basic, just switching between two views with different color backgrounds. But, you could further customize those subviews in the loadView method to display whatever you need.
The interface file:
#interface SwapViewController : UIViewController {
UIView *firstView;
UIView *secondView;
BOOL displayingFirstView;
UIButton *swapButton;
}
#property (nonatomic, retain) UIView *firstView;
#property (nonatomic, retain) UIView *secondView;
#property (nonatomic, retain) UIButton *swapButton;
- (void)swap;
#end
The implementation file:
#import "SwapViewController.h"
#implementation SwapViewController
#synthesize firstView;
#synthesize secondView;
#synthesize swapButton;
- (void)loadView
{
CGRect frame = [[UIScreen mainScreen] applicationFrame];
UIView *containerView = [[UIView alloc] initWithFrame:frame];
containerView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.view = containerView;
[containerView release];
frame = self.view.bounds;
firstView = [[UIView alloc] initWithFrame:frame];
firstView.backgroundColor = [UIColor redColor];
secondView = [[UIView alloc] initWithFrame:frame];
secondView.backgroundColor = [UIColor blueColor];
self.swapButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
self.swapButton.frame = CGRectMake(10, 10, 100, 50);
[swapButton addTarget:self action:#selector(swap) forControlEvents:UIControlEventTouchUpInside];
displayingFirstView = YES;
[self.view addSubview:firstView];
[self.view addSubview:swapButton];
}
- (void)swap
{
if(displayingFirstView) {
[self.firstView removeFromSuperview];
[self.view addSubview:secondView];
displayingFirstView = NO;
} else {
[self.secondView removeFromSuperview];
[self.view addSubview:firstView];
displayingFirstView = YES;
}
[self.view bringSubviewToFront:self.swapButton];
}
#end
sample code;
BOOL firstview = YES; // First, I have added view1 as a subview;
if (firstview) {
[view1 removeFromSuperview];
[self.view addSubview:view2];
} else {
[view2 removeFromSuperview];
self.view addSubview:view1];
}