Gesture Recognizer not working in UIScrollView Subclass - iphone

I have subclassed UIScrollView, and i have a UIScrollView in my nib, Gestures were working fine on it, but when i changed the class of UIScrollView in Identity Inspector to my subclass of UIScrollView, the gestures stopped working, and i have this warning in my Interface Builder.
ScrollView does not have an outlet collection named gestureRecognizors.
Also i have a delegate in my subclass, which is also giving a warning:
Here is the Subclass:
#protocol ScrollViewDelegate <NSObject>
-(void)onScrollViewTouch;
#end
#interface ScrollView : UIScrollView <UIScrollViewDelegate>
#property(nonatomic, retain) id<ScrollViewDelegate> subDelegate;
#end
Here is ScrollView.m
#implementation ScrollView
#synthesize subDelegate;
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.canCancelContentTouches = NO;
self.delaysContentTouches = NO;
[self setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
[super setDelegate: self];
}
return self;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[super touchesBegan:touches withEvent:event];
[delegate onScrollViewTouch];
}
#end
Can anyone suggest what am i doing wrong here? Thanks everyone :)

Related

Move UIImageview using the UITouches

I have subclassed a uiview, in which I am adding two uiimageview, with one view for the background and another image view for an image which one i would like to move on touch. I am adding this subclass uiview from a view controller. The following is the code:
#interface CustomSlider : UIView
{
UIImageView *bgView;
UIImageView *customSliderImageView;
float minStartPoint,maxEndPoint;
}
- (id)initWithFrame:(CGRect)frame inView:(UIView*)mainView;
#end
#implementation CustomSlider
- (id)initWithFrame:(CGRect)frame inView:(UIView*)mainView {
if((self = [super init])) {
UIView *contentView = [[UIView alloc] initWithFrame:CGRectMake(15, 60, frame.size.width, frame.size.height)];
contentView.backgroundColor = [UIColor clearColor];
[mainView addSubview:contentView];
bgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"price_96.png"]];
bgView.frame = CGRectMake(5, 0, frame.size.width - 10, 8 );
[contentView addSubview:bgView];
customSliderImageView= [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"price_100.png"]];
customSliderImageView.frame = CGRectMake(20, 0, 35, frame.size.height);
[contentView addSubview:customSliderImageView];
minStartPoint = 0;
UIPanGestureRecognizer* pgr = [[UIPanGestureRecognizer alloc]
initWithTarget:self
action:#selector(handlePan:)];
[customSliderImageView addGestureRecognizer:pgr];
[pgr release];
}
return self;
}
#end
AppDelegate Classes
**// .h File**
#import <UIKit/UIKit.h>
#class UITouchTutorialViewController;
#interface UITouchTutorialAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
UITouchTutorialViewController *viewController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UITouchTutorialViewController *viewController;
#end
//////////////////////////////////////////////////////////////////////////////////
// .m File
#import "UITouchTutorialAppDelegate.h"
#import "UITouchTutorialViewController.h"
#implementation UITouchTutorialAppDelegate
#synthesize window;
#synthesize viewController;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// Override point for customization after app launch
[window addSubview:viewController.view];
[window makeKeyAndVisible];
}
- (void)dealloc {
[viewController release];
[window release];
[super dealloc];
}
#end
//////////////////////////////////////////////////////////////////////////////
UIViewController Classes
// .h file
#import <UIKit/UIKit.h>
#interface UITouchTutorialViewController : UIViewController {
IBOutlet UIImageView *cloud;
}
#end
// .m File
#import "UITouchTutorialViewController.h"
#implementation UITouchTutorialViewController
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:touch.view];
cloud.center = location;
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
[self touchesBegan:touches withEvent:event];
}
/*
// Override initWithNibName:bundle: to load the view using a nib file then perform additional customization that is not appropriate for viewDidLoad.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
// Custom initialization
}
return self;
}
*/
/*
// Implement loadView to create a view hierarchy programmatically.
- (void)loadView {
}
*/
/*
// Implement viewDidLoad to do additional setup after loading the view.
- (void)viewDidLoad {
[super viewDidLoad];
}
*/
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
// Release anything that's not essential, such as cached data
}
- (void)dealloc {
[super dealloc];
}
#end

Activating UIImageView with GestureRecognizer in a ScrollView

I,
I'm currently trying to implement a Gesture recognizer into a ScrollView.
I first created a custom ScrollView in which I integrated ImageView object.
When the user clicks on a ImageView, normally the PanGestureRecognizer activates and the ImageView object follow the move on the screen.
I have read and followed the instructions on Gesture Recognizer and the Raywenderlich blog (which is very well done).
If someone has a clue of what is missing in my code, I would be happy to read it
Thank in advance. Here is my code
#import <Foundation/Foundation.h>
#import "mainInterface03.h"
#import <QuartzCore/QuartzCore.h>
#import "boutonHome.h"
#import "DragGestureRecognizer.h"
#class boutonHome;
#class DragGestureRecognizer;
#interface TapScrollView : UIScrollView {
// id<TapScrollViewDelegate> delegate;
NSMutableArray *classementBoutons;
int n;
int o;
UIView *bouton01;
}
#property (nonatomic, retain) UIView *bouton01;
#property (retain, nonatomic) IBOutletCollection(UIButton) NSMutableSet* buttons;
-(id)init;
-(void)initierScrollView;
-(void) createGestureRecognizers;
-(IBAction)handlePanGesture:(UIPanGestureRecognizer*)sender;
#end
m.file
#import "TapScrollView.h"
#implementation TapScrollView
#synthesize bouton01;
- (id) init
{
if (self = [super init])
{
NSLog(#"Classe TapScrollView initiƩe");
}
return self;
}
-(void)initierScrollView
{
int i;
for (i=0; i<6; i++) {
UIImage *image = [UIImage imageNamed:#"back.png"];
UIImageView *bouton = [[UIImageView alloc] initWithImage:image];
[bouton setTag:i];
[bouton setFrame:CGRectMake(72*i+20,10,62,55)];
[classementBoutons insertObject:bouton atIndex:i];
[self addSubview:bouton];
}
UIPanGestureRecognizer *recognizer = [[UIPanGestureRecognizer alloc] initWithTarget:bouton01 action:#selector(handlePanGesture:)];
[bouton01 addGestureRecognizer:recognizer];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
[super touchesBegan:touches withEvent:event];
for (o=1; o<6; o++) {
if ([touch view] == [self viewWithTag:o])
{
bouton01 = [self viewWithTag:o];
}
}
return;
}
-(IBAction)handlePanGesture:(UIPanGestureRecognizer*)recognizer
{
NSLog(#"Mouvement ok");
CGPoint translation = [recognizer translationInView:self];
recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x,
recognizer.view.center.y + translation.y);
[recognizer setTranslation:CGPointMake(0, 0) inView:self];
}
#end
I am not sure if this setup can work. Essentially, you are assigning whatever view has been touched to bouton01, which carries the gesture recognizer. Seems a bit convoluted to me, and also your code is not so efficient.
It seems that when you call [super touchesBegan:touches withEvent:event]; it will pass the touch up the view hierarchy. Only after that do make the assignment to bouton01. So it would seem logical that bouton01 never receives a touch event.
Indeed, it is because of this strange approach of iterating through the views and assigning it the one that has the recognizer that this error arose. I would suggest to assign the same recognizer to all concerned views during setup.

Drag and drop images from toolbar to view canvas

I want to make a app where I need to have a toolbar. The toolbar will have various number of objects (images). These objects should be draggable and placed on view right above it.
This is a kind of drawing app where user can pick any shape and place on canvas. Can anyone tell me the best to achieve this ?
Thanks in advance.
Tough one.
What I would do is make each item on the toolbar a UIView and override touchesBegan, touchesEnded, and touchesMoved. Make your canvas another UIView. When a user clicks an item to drag, register that item somewhere, say a square. then when they drop on the canvas, draw that square at that location. To make it look pretty, would probably make a UIImageView with an alpha of like .4 to move with the user's touch, so they know what they are dragging, and where it will land.
Here is the code.
UIViewController.h
#class ToolBox;
#interface ViewController : UIViewController {
IBOutlet UIView *canvas;
IBOutlet ToolBox *toolBox;
}
#property (nonatomic, retain) UIView *canvas;
#property (nonatomic, retain) ToolBox *toolBox;
#end
UIViewController.m
#import "ViewController.h"
#import "ToolBox.h"
#import "Tool.h"
#implementation ViewController
#synthesize canvas, toolBox;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[[self toolBox] setCanvas:[self canvas]];
Tool *tool = [[[Tool alloc] initWithFrame:CGRectMake(0,0,64,64)] autorelease];
[tool setImageView:[[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"1.png"]] autorelease]];
[tool setImage:[UIImage imageNamed:#"1.png"]];
[tool addSubview:[tool imageView]];
[tool setToolBox:[self toolBox]];
[[self toolBox] addObject:tool];
}
#end
ToolBox.h
#class Tool;
#interface ToolBox : UIView {
NSMutableArray *tools;
UIView *canvas;
UIImage *currentTool;
}
#property (nonatomic, retain) UIImage *currentTool;
#property (nonatomic, retain) NSMutableArray *tools;
#property (nonatomic, retain) UIView *canvas;
-(void)addObject:(Tool *)newTool;
-(void)updatePositions;
#end
ToolBox.m
#implementation ToolBox
#synthesize tools, canvas, currentTool;
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
}
return self;
}
-(void) dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
-(NSMutableArray *)tools {
if(tools == nil) {
[self setTools:[NSMutableArray array]];
}
return tools;
}
-(void)addObject:(Tool *)newTool {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(draggingTool:) name:#"Dragging New Tool" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(draggedTool:) name:#"Dragged Tool To" object:nil];
[[self tools] addObject:newTool];
[self updatePositions];
}
-(void)updatePositions {
int x = 0;
int y = 0;
int width = 64;
int height = 64;
for(Tool *button in [self tools]) {
[button setFrame:CGRectMake(x, y, width, height)];
x += width;
[self addSubview:button];
}
}
-(void)draggingTool:(NSNotification *)notif {
NSDictionary *dict = [notif userInfo];
UIImage *image = [dict valueForKey:#"Image"];
[self setCurrentTool:image];
}
-(void)draggedTool:(NSNotification *)notif {
UITouch *touch = [[notif userInfo] valueForKey:#"Touch"];
CGPoint point = [touch locationInView:canvas];
UIImageView *imageView = [[[UIImageView alloc] initWithImage:currentTool] autorelease];
[imageView setCenter:point];
[canvas addSubview:imageView];
}
#end
Tool.h
#class ToolBox;
#interface Tool : UIView {
UIImageView *imageView;
UIImage *image;
UIImageView *ghostImageView;
ToolBox *toolBox;
}
#property (nonatomic, retain) UIImageView *imageView;
#property (nonatomic, retain) UIImage *image;
#property (nonatomic, retain) UIImageView *ghostImageView;
#property (nonatomic, retain) ToolBox *toolBox;
#end
Tool.m
#import "Tool.h"
#import "ToolBox.h"
#implementation Tool
#synthesize imageView, image, ghostImageView, toolBox;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"tool touches began");
NSDictionary *dict = [NSDictionary dictionaryWithObject:[self image] forKey:#"Image"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"Dragging New Tool" object:nil userInfo:dict];
UITouch *touch = [touches anyObject];
CGPoint center = [touch locationInView:[[self toolBox] canvas]];
[self setGhostImageView:[[[UIImageView alloc] initWithImage:[self image]] autorelease]];
[[self ghostImageView] setCenter:center];
[[[self toolBox] canvas] addSubview:[self ghostImageView]];
[[self ghostImageView] setAlpha:.4];
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"tool touches ended");
NSDictionary *dict = [NSDictionary dictionaryWithObject:[touches anyObject] forKey:#"Touch"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"Dragged Tool To" object:nil userInfo:dict];
[self setGhostImageView:nil];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"tool touch moved");
if([self ghostImageView] != nil) {
UITouch *touch = [touches anyObject];
CGPoint center = [touch locationInView:[[self toolBox] canvas]];
NSLog(#"Ghost : %2f, %2f", center.x, center.y);
[[self ghostImageView] setCenter:center];
}
}
#end
My Program came out like this -
Initial screen: The tool is ready to be dragged and dropped onto the canvas
Dropped the tool on the canvas
And here is the ghost for the transition
I'm not exactly sure how this would be implemented in objective c, but I have done almost exactly what you are describing in java. Basically, when you begin to drag the object in the toolbar, it will recognize the action and store a new instance of the item in what I call a transfer container, which is basically a global static variable. That way when the drag action competes (I.e. drops) you can just grab that object from the container and add it to wherever it was dropped.

touch and drag multiple controls in iphone

I want to select multiple views in an interface and drag them together.
How can I implement this in xcode.
For example i have some image views in a view then i want to select them by drawing a rectangle. then move them by dragging them.
Can anybody help me.
Thanks in advance
Try this code
#import "TouchView.h"
//TouchView.h
#import <Foundation/Foundation.h>
#import "TouchViewDelegate.h"
#interface TouchView : UIView {
id <TouchViewDelegate> delegate;
}
#property (retain) id delegate;
#end
//TouchView.m
#implementation TouchView
#synthesize delegate;
-(id) initWithFrame:(CGRect)frame
{
self.userInteractionEnabled = YES;
return self;
}
-(id) initWithCoder:(NSCoder *)aDecoder
{
self.userInteractionEnabled = YES;
return self;
}
-(void) awakeFromNib
{
self.userInteractionEnabled = YES;
}
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[delegate touchDown:self];
}
-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[delegate touchUp:self];
}
#end
//TouchViewDelegate.h
#import <UIKit/UIKit.h>
#protocol TouchViewDelegate
-(void) touchDown:(id) sender;
-(void) touchUp:(id)sender;
#end

MyScrollView doesn't respond to touch when I pass the touch event to superview

I have a ViewController with ScrollView SubView and those subview has a subview in it, below is the hierarchy :
AppDelegate - MyViewController - ScrollView(from xib) - MyScrollViewSubClass
// MyViewController :
// .h
#interface MyViewController : UIViewController<MyScrollViewSubClassDelegate,UIScrollViewDelegate> {
UIScrollView *scrollView; // Loaded from xib
}
#property(nonatomic,retain) IBOutlet UIScrollView *scrollView;
#end
// .m
#implementation MyViewController
#synthesize scrollView;
- (void)viewDidLoad {
[super viewDidLoad];
scrollView.delegate = self;
MyScrollViewSubClass *myScrollView = [[MapScrollView alloc] init];
myScrollView.delegate = self;
myScrollView.myDelegate = self;
scrollView addSubview:mapScrollView];
}
// The MyScrollViewSubClassDelegate #required method
- (void) onDoubleTapLocation: (CGPoint)tapPoint
{
// Working,,,NSLog shown that this line is Working...
}
// MyScrollViewSubClass + Delegate
// .h
// Protocol
#protocol MyScrollViewSubClasswDelegate <NSObject>
#required
- (void) onDoubleTapLocation: (CGPoint)tapPoint;
#end
//Interface
#protocol MyScrollViewSubClass;
#interface MyScrollViewSubClass : UIScrollView <UIScrollViewDelegate> {
id <MyScrollViewSubClasswDelegate> myDelegate;
// Another vars..
}
#property (nonatomic,assign) id<MyScrollViewSubClasswDelegate> myDelegate;
- (void)handleDoubleTap;
#end
// .m
#implementation MyScrollViewSubClass
#synthesize myDelegate;
- (id)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame])) {
// Another Code Here...
self.delegate = self; // delegate for UIScrollView
self.myDelegate = self;
//Another Code Here...
}
return self;
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
if(isDoubleTap)
{
//Call handle double tap
[self handleDoubleTap];
}
}
- (void)handleDoubleTap {
[self.myDelegate onDoubleTapLocation: tapLocation];
}
What Happen is the double tap is working on MyViewController, but now i can't scroll and pinch zoom my MyScrollViewSubClass from MyViewController, any critics, comment or better method are welcome..
Resolved :
I assign delegate on MyViewController twice
was :
myScrollView.delegate = self;
myScrollView.myDelegate = self;
Should be :
myScrollView.myDelegate = self;
Regards,
Ferry Hattawidian
Resolved :
I assign delegate on MyViewController twice
was :
myScrollView.delegate = self;
myScrollView.myDelegate = self;
Should Be :
myScrollView.myDelegate = self;
Everything else is running well... Thanks guys...