Detect touch in UIImageView in UIScrollView - iphone

i have images in my UIScrollview which is added in View.
plz go through my code-
#interface ScrollViewController : UIScrollView <UIScrollViewDelegate>{
UIImageView *productImage;
UILabel *productName;
NSArray *productArray;
}
#property(nonatomic,retain) UIImageView *productImage;
#property(nonatomic,retain) UILabel *productName;
#property(nonatomic,retain) NSArray *productArray;
- (id)initWitProducts:(NSArray*)_data;
*.m*
- (id)initWitProducts:(NSArray *)_data
if ((self = [super init])){
productArray=[[NSArray alloc]initWithArray:_data];
[self setFrame:CGRectMake(0, 0, 320, 480)];
int countList=[self.productArray count];
self.contentSize=CGSizeMake(320, 585);
for(int i=0;i<countList;i++)
{
productImage=[[UIImageView alloc]initWithImage:[UIImage imageNamed:[[productArray objectAtIndex:i]objectForKey:#"ProductImage"]]];
productImage.frame=CGRectMake(95, 35+i*125, 100, 100);
[productImage setUserInteractionEnabled:YES];
[self addSubview:productImage];
}
return self;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event
{
if([[touches anyObject]view]==self.productImage)
NSlog(#"Image Touched");
}
This is working well but only for last image in Array
the touchesBegan is not working for other images in Array
what should i add here to detect the touch on all the images(1st,2nd,...etc) of Array

You know all the positions of images on UIScrollview, so you can touch position on scrollView into images position in you array.
And another point - you should never compare objective-c objects using "==", always use "isEqual" method instead.

That is because you keep on updating the variable productImage, change your code to read
UIImageView *imageInstance=[[UIImageView alloc]initWithImage:[UIImage imageNamed:[[productArray objectAtIndex:i]objectForKey:#"ProductImage"]]];
imageInstance.frame=CGRectMake(95, 35+i*125, 100, 100);
[imageInstance setUserInteractionEnabled:YES];
[self addSubview:imageInstance];

Related

touchesBegan not functioning on programmatically created view and imageview

I am programmatically creating a view and a imageview while in viewControllerA for an another viewControllerB before I then goto viewControllerB. I have to do this, as I am using an image from the imagePickerController. However by doing this, touchesBegan does not function in viewControllerB
I have set UserInteractionEnabled to true/yes in both the attributes inspector of the xib and programmatically everywhere!
My xib is just a blank canvas, with one View. I have tried different settings with the connections inspector, but still no luck.
Here is my code.
viewControllerA.m
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
CGRect screenRect = [[UIScreen mainScreen] applicationFrame];
view = [[UIView alloc] initWithFrame:screenRect];
image = [info valueForKey:UIImagePickerControllerEditedImage];
SSViewController *psView = [[SSViewController alloc] initWithNibName:#"SSViewController" bundle:nil];
psView.view = [[UIView alloc] initWithFrame:screenRect];
[psView.view setUserInteractionEnabled:YES];
[picker pushViewController:psView animated:YES];
imageView = [[UIImageView alloc] initWithImage:image];
imageView.frame = CGRectMake(20, 20, 280, 280);
[imageView setUserInteractionEnabled:YES];
[psView.imageView setUserInteractionEnabled:YES];
[psView.view addSubview:imageView];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:psView action:#selector(endPS:) forControlEvents:UIControlEventTouchUpInside];
[button setTitle:#"done" forState:UIControlStateNormal];
button.frame = CGRectMake(140.0, 330.0, 80.0, 25.0);
[psView.view addSubview:button];
}
viewControllerB.h (SSViewController.h)
#interface SSViewController : UIViewController
{
IBOutlet UIImageView *imageView;
IBOutlet UIView *view;
}
#property (nonatomic,strong) IBOutlet UIImageView *imageView;
#property (nonatomic,strong) IBOutlet UIImage *image;
#property (nonatomic, strong) IBOutlet UIView *view;
- (IBAction)endPS:(id)sender;
#end
viewControllerB.m (SSViewController.m)
#implementation SSViewController
#synthesize imageView;
#synthesize image;
#synthesize view;
:
:
- (void)viewDidLoad
{
[view setUserInteractionEnabled:YES];
[imageView setUserInteractionEnabled:YES];
:
:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#"touchesBegan");
:
You're doing a number of things wrong:
Don't push a view controller on to the UIImagePickerController. If you've presented it modally, which I hope you have, you need to dismiss it (in viewControllerA) and push your new view controller (viewControllerB) onto your own navigation controller. The fact that you're pushing onto this highly customised navigation controller is most likely why touchesBegan is not being called.
Why are you manually creating the view for viewControllerB? If you're loading it from a XIB file, it will have a perfectly good view ready for you. And don't define the view property in viewControllerB.h, it's already defined in UIViewController.h.
Don't forget to call [super viewDidLoad] in viewControllerB.m. This is a classic mistake that will cause you many headaches.
EDIT:
What I would personally have done is added a method on viewControllerB as such:
viewControllerB.h
#interface SSViewController : UIViewController
{
- (void)setImage:(UIImage *)image;
}
#end
viewControllerB.m
#implementation SSViewController
{
- (void)setImage:(UIImage *)image
{
// In case the image view already exists, remove it first.
[_imageView removeFromSuperview];
_imageView = [[UIImageView alloc] initWithImage:image];
_imageView.frame = CGRectMake(20, 20, 280, 280);
[self.view addSubview:_imageView];
}
}
#end
This way, in viewControllerA.m you can just create viewControllerB.m and call this setImage: method to let viewControllerB do all the work.

Improve Touch Events UIImageView

I have 30-40 tabs open, I've found my answer.. but I'm wishing to improve.
The code does work, I am just not sure if it is efficient
The following code shows that I have 2 small images (One using UIImageView, another using UIView) in which I have attached to a UIScrollView, which is attached to a UIView which came with the UIViewController, which is attached to the UIWindow. Pretty basic.
I also have a button attached to the UIViewController to make sure zooming and scrolling worked. (By testing the static location of the button and size)
#interface Wire_TestViewController : UIViewController <UIScrollViewDelegate> {
UIScrollView *scrollview;
}
#end
Implementation:
- (void)test:(UIButton *)sender { }
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView { return scrollview; }
- (void)viewDidLoad {
[super viewDidLoad];
scrollview = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
scrollview.delegate = self;
scrollview.contentSize = CGSizeMake( 320*2, 480*2 );
scrollview.minimumZoomScale = .1;
scrollview.maximumZoomScale = 10;
[self.view addSubview:scrollview];
UIImageView *view = [[UIImageView alloc] initWithFrame:CGRectMake(320, 320, 20, 20)];
view.image = [UIImage imageNamed:#"Node.png"];
view.clearsContextBeforeDrawing = NO;
[scrollview addSubview:view];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = CGRectMake(10, 10, 100, 30);
button.tag = 51;
[button setTitle:#"new button" forState:(UIControlState)UIControlStateNormal];
[button addTarget:self action:#selector(test:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
UIView *view2 = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 30, 30)];
view2.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"WireActive.png"]];
[scrollview addSubview:view2];
TestSubclass *test = [[TestSubclass alloc] initWithFrame:CGRectMake(100, 100, 50, 50)];
test.userInteractionEnabled = TRUE;
test.image = [UIImage imageNamed:#"Node.png"];
[scrollview addSubview:test];
}
You'll see near the bottom I have a TestSubclass class made.
The code for that is as follows:
#interface TestSubclass : UIImageView { }
#end
#implementation TestSubclass
- (id)init {
[super init];
self.userInteractionEnabled = TRUE;
return self;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
printf("Being touched...\n");
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
printf("Touches Ended...\n");
}
#end
The part in which I am happy with is that I have a fully functioning Subclass of UIImageView which works as if it was a UIButton.
BUT! without the 7 backgroundImageViews (and the overhead from each of those), without the 6 labels (and the overhead from each of those), without the 6 UIImageViews ("..."), and lastly the amount of un-needed things that UIButton offers. I only wanted touch capabilities.. efficiently however. (TouchUpInside, Dragging, etc)
But, now during my research (after the extensive testing to accomplish this much), I've come across in documentation and some examples addGestureRecognizer in UIView. It seems sorta-but not entirely efficient for my needs.
I'm looking for advice, I know there are a couple problems in my code (overrided init, but didn't use it in the above code.. didn't release.. probably some subclassing mistakes (new to subClassing (to be honest)). But anything is much appreciated!! And, I hope others are helped as well!
If you want to have full control capabilities, you must subclass UIControl and use your image with in. The image can be an UIImageView subview or can be drawn in the drawRect method of your subclass or set in the CALayer view content.
Note that subclassing UIControl is not the easiest thing to do, but it gives you all "control" feature it seems you are requesting from it and I think is the most efficient or appropriate approach.

How can I use UIScrollView for overlapped images iphone

Hi, I have a big image and small image over it at a specific location...
I added them all under ScrollView, but it didn't work properly?
I want to zoom in, all together each in its place
Here is my code:
myScrollView.contentSize = CGSizeMake(imageView.frame.size.width, imageView.frame.size.height);
myScrollView.maximumZoomScale = 3.0;
myScrollView.minimumZoomScale = 1.0;
myScrollView.clipsToBounds = YES;
myScrollView.delegate = self;
[myScrollView addSubview:imageView];
thanks
Hi, mackworth; I did it, but if I didn't maximize the image, I can't move the scroll view anywhere, but if I zoomed it, I can see the rest.. I don't know why I tried changing it, but it work. Can you please look at the following code?
- (void)viewDidLoad{
[super viewDidLoad];
UIImage *image = [UIImage imageNamed:#"ucd.png"];
//creating a view for UCD image
ucdView = [[UIImageView alloc] initWithImage:image];
//setting the frame for the ucdView as the same size of ucd image
[ucdView setFrame:CGRectMake(0, 0, image.size.width, image.size.height)];
//for the red pin to display in specific loc
UIImageView *Health = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"redPin.png"]];
[Health setCenter:CGPointMake(310,135)];
//adding helathView to ucdview
[ucdView addSubview:Health];
//everything for scroll view
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, ucdView.frame.size.width, ucdView.frame.size.height)];
[scrollView setMinimumZoomScale:1.0];
[scrollView setMaximumZoomScale:3.0];
scrollView.clipsToBounds = YES;
[scrollView setContentSize:CGSizeMake(image.size.width, image.size.height)];
[scrollView setDelegate:self];
[scrollView addSubview:ucdView];//adding ucd view to scroll view
[self.view addSubview:scrollView]; // adding scrollview to self.view main view
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {//apply zooming for scrollview
return scrollView;
}
Did you implement:
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return self.imageView;
}
Also, you know that by setting the scrollView's contentSize to your imageSize, it can't grow any bigger than that, right? It'll zoom in place, cropping the outer pixels accordingly. As an aside, if that is your plan, why not just set it directly?
myScrollView.contentSize = imageView.frame.size;
=====Further answer, responding to additional source
Well, the main thing I notice is that you need to return the imageView ucdView in viewForZoomingInScrollView, not the scrollView. It looks like you already created ucdView as a property (so that it lives as long as your view does), but just in case...
1) In your .h file:
UIImageView * ucdView;
#property (nonatomic, retain) UIImageView * ucdView;
2) In your .m file;
#synthesize ucdView;
3) change your line:
ucdView = [[UIImageView alloc] initWithImage:image];
to just
self.ucdView = [[UIImageView alloc] initWithImage:image];
4) change the line
return scrollView
to:
return self.ucdView;
5) Add the following to your dealloc routine:
self.ucdView = nil;
Also, did you add <UIScrollViewDelegate> protocol to your ViewController definition (in .h file)?
Finally, you have a leak of scrollview and Health; add [scrollView release]; and [Health release] at end of viewDidLoad

How to call a method from a different class?

So, I am trying to make a shared method in my Brain class which will check the label on a pressed button (buttons of items are in different classes) and then accordingly add a image to a ShoppingList view minding the order of adding (first image added goes to position 0,0, second to position 80,0 etc.).
I have Breakfast class which represents breakfast ingredients and I wanna add a photo of a Tea to another view called ShoppingList.
I wrote a method in Brain that adds an image to a imageView and returns an imageView which is then locally passed to the button pressed.
It builds but when I press the button Tea, application crashes.
Here is my code:
Brain.h
#interface Brain : NSObject {
#private
UIImage *image;
UIImageView *imageView;
}
#property (retain) UIImageView *imageView;
#property (retain) UIImage *image;
- (id)performOperation:(NSString *)operation;
#end
Brain.m
#implementation Brain
#synthesize imageView;
#synthesize image;
- (UIImageView *)performOperation:(NSString *)operation
{
if ([operation isEqual:#"Tea"]) {
image = [UIImage imageNamed:#"Tea_photo.jpg"];
imageView = [[UIImageView alloc]initWithImage:image];
imageView.frame = CGRectMake(0, 0, 80, 80);
return imageView;
//[shoppingList.view addSubview:imageView];
//[imageView release];
}
else return 0;
}
#end
Breakfast.h
#interface Breakfast : UIViewController {
IBOutlet ShoppingList *shoppingList;
Brain *brain;
}
- (IBAction)addItemToShoppingList:(UIButton *)sender;
- (IBAction)goToShoppingList;
- (IBAction)goBack;
#end
Breakfast.m
#implementation Breakfast
- (Brain *)brain
{
if (!brain) brain = [[Brain alloc] init];
return brain;
}
- (IBAction)addItemToShoppingList:(UIButton *)sender
{
NSString *operation = [[sender titleLabel] text];
UIImageView *imageView = [[self brain] performOperation:operation];
[shoppingList.view addSubview:self.brain.imageView];
//UIImageView *imageView = [[UIImageView alloc]initWithImage:image];
//imageView.frame = CGRectMake(0, 0, 80, 80);
//[shoppingList.view addSubview:imageView];
//[imageView release];
}
- (IBAction)goToShoppingList
{
[self presentModalViewController:shoppingList animated:NO];
}
- (IBAction)goBack
{
[self dismissModalViewControllerAnimated:NO];
}
#end
PLEASE HELP, its for my thesis.
IBOutlet ShoppingList *shoppingList;
Why make this IBOutlet? Isn't ShoppingList a class that you created. Not that this solves your crash. For that u need to post the crash log....
And also in you code I can't see any allocation for shoppingList so how can you be able to use it. You need to allocate the object in the class Brain otherwise it doesn't make any sense.
I have not gone through your code. But on the basis of your description I can suggest you to create a protocol

remove UIImageView from its Superview

In my application when the user touches the screen, I put an UIImageView on the screen like this:
- (void) drawPoint:(CGPoint) toLocation {
UIImageView *image = [[UIImageView alloc] initWithFrame:CGRectMake(toLocation.x, toLocation.y, SIZE_X, SIZE_Y)];
image.tag = 1;
[image setImage:[UIImage imageNamed:#"point.png"]];
[self.myView addSubview:image];
[image release];
}
Here MyView is an UIView.
When the user has finished touching, I want to remove my UIImageView. I have tried this:
- (void) removeFromPoint:(CGPoint) location{
UIImageView *image;
[[image viewWithTag:1] removeFromSuperview];
}
or
- (void) removeFromPoint:(CGPoint) location{
UIImageView *image = (UIImageView *)[self.MyView viewWithTag:1];
[image removeFromSuperview];
}
but both of them end up in EXC_BAD_ACCESS.
Do you know how can I accomplish this?
Thanks.
If you want to remove uimage under the touch try this:
UIView * imageView = [self.myView hitTest:location withEvent:nil];
if ([imageView isKindOfClass:[UIImageView class]] && imageView.tag == 1) {
[imageView removeFromSuperview];
}
(note I've typed it here, i haven't test that code)
If you wish to debug your code enable NSZombies and check why you gets the bad_access. (check this to learn more about NSZombieEnabled http://www.cocoadev.com/index.pl?NSZombieEnabled)
If you are going to add only one view. Then I would store it in a retained property and I would add/remove it on events like this:
#property (nonatomic,retain) UIImageView* marker;
#interface
#syntesize marker;
-(void) onTouchDown {
[self.view addSubview:marker];
}
-(void) onTouchUp {
[marker removeFromSuperview];
}
The first example of removing image view is wrong.
In the second one what is POINT_TAG equal to?
Try to use tag greater then 9.
Try to debug what UIImageView *image = (UIImageView *)[self.MyView viewWithTag:POINT_TAG];
returns.