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
Related
I am using two images named "ATrackThumb" & "BTrackThumb" in my iPad application, to be moved by the touch of an user. I am using some methods for this purpose. But image movement is not working.
Methods are:
#pragma mark responding to touch events
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event{
for (UITouch *touch in touches) {
CGPoint t = [touch locationInView:touch.view];
if(t.x > (ATrackThumb.center.x-25) && t.x < (ATrackThumb.center.x+25) && t.y > (ATrackThumb.center.y-25) && t.y < (ATrackThumb.center.y+25)){
ASliderLastTouch = touch;
}
if(t.x>(BTrackThumb.center.x-25) && t.x < (BTrackThumb.center.x+25) && t.y > (BTrackThumb.center.y-25) && t.y < (BTrackThumb.center.y+25)){
BSliderLastTouch = touch;
}
}
}
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event{
for (UITouch *touch in touches) {
CGPoint t = [touch locationInView:touch.view];
//Check Slider for Contact
if(touch==ASliderLastTouch){
if(t.x>205)
[ATrackThumb setCenter:CGPointMake(205,ATrackThumb.center.y)];
else if(t.x<24)
[ATrackThumb setCenter:CGPointMake(24,ATrackThumb.center.y)];
else
[ATrackThumb setCenter:CGPointMake(t.x,ATrackThumb.center.y)];
hourSlider.value=(ATrackThumb.center.x-24)/15;
[self updateHour];
}
if(touch==BSliderLastTouch){
if(t.x>205)
[BTrackThumb setCenter:CGPointMake(205,BTrackThumb.center.y)];
else if(t.x<24)
[BTrackThumb setCenter:CGPointMake(24,BTrackThumb.center.y)];
else
[BTrackThumb setCenter:CGPointMake(t.x,BTrackThumb.center.y)];
minutesSlider.value=(BTrackThumb.center.x-24)/3.0;
[self updateMinute];
}
}
}
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event{
for (UITouch *touch in touches) {
if(touch==ASliderLastTouch)ASliderLastTouch=nil;
if(touch==BSliderLastTouch)BSliderLastTouch=nil;
}
}
where is the problem?
Following code is use for move image on your touch
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
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
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 :)
First of all, this problem did not exist in iOS 4.3. I can still run the program in iOS 4.3 and won't see any problem. Secondly, this is an iPad app.
The problem is that when I hold down an image and drag it, it won't be dragged. It worked in iOS 4.3 but not iOS 5.
I created new testing project and cleared everything that's not needed. The project I chose is a Single View Application and did not alter any of the AppDelegate files.
Here is the code.
myUIScrollViewClass.h
#import <UIKit/UIKit.h>
#interface myUIScrollViewClass : UIScrollView
{
}
#end
myUIScrollViewClass.m
#import "myUIScrollViewClass.h"
#implementation myUIScrollViewClass
- (id)init
{
self = [super init];
if (self)
{
}
return self;
}
- (void)didReceiveMemoryWarning
{
[self didReceiveMemoryWarning];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.nextResponder touchesBegan: touches withEvent:event];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.nextResponder touchesMoved: touches withEvent:event];
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.nextResponder touchesEnded: touches withEvent:event];
}
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.nextResponder touchesCancelled: touches withEvent:event];
}
#end
ViewController.h
#import <UIKit/UIKit.h>
#import "myUIScrollViewClass.h"
#interface ViewController : UIViewController <UIScrollViewDelegate>
{
myUIScrollViewClass *mainScrollView_;
UIImageView *aTouchedImage_;
}
#property (retain, nonatomic) myUIScrollViewClass *mainScrollView_;
#property (retain, nonatomic) UIImageView *aTouchedImage_;
#end
ViewController.m
#import "ViewController.h"
#implementation ViewController
#synthesize mainScrollView_;
#synthesize aTouchedImage_;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
mainScrollView_ = [[myUIScrollViewClass alloc] initWithFrame:self.view.frame];
[self.view addSubview:mainScrollView_];
mainScrollView_.delegate = self;
mainScrollView_.contentSize = CGSizeMake(1024, 768);
mainScrollView_.clipsToBounds = YES;
mainScrollView_.bounces = NO;
mainScrollView_.bouncesZoom = NO;
mainScrollView_.showsVerticalScrollIndicator = NO;
mainScrollView_.showsHorizontalScrollIndicator = NO;
mainScrollView_.backgroundColor = [UIColor whiteColor];
mainScrollView_.userInteractionEnabled = YES;
aTouchedImage_ = [[UIImageView alloc] initWithImage: [UIImage imageNamed:#"image1.png"]];
[aTouchedImage_ setFrame:CGRectMake(0, 0, 80, 80)];
[mainScrollView_ addSubview:aTouchedImage_];
[aTouchedImage_ setCenter:CGPointMake(512, 334)];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return YES;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)anEvent
{
mainScrollView_.scrollEnabled = NO;
for (UITouch *touch in touches)
{
[aTouchedImage_ setCenter:[touch locationInView:self.view]];
}
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)anEvent
{
mainScrollView_.scrollEnabled = NO;
for (UITouch *touch in touches)
{
[aTouchedImage_ setCenter:[touch locationInView:self.view]];
}
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)anEvent
{
mainScrollView_.scrollEnabled = YES;
for (UITouch *touch in touches)
{
}
}
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)anEvent
{
mainScrollView_.scrollEnabled = YES;
for (UITouch *touch in touches)
{
}
}
#end
It seems I will answer my own question.
I have requested a support from Apple Developer Technical Support, and they told me to place my code in the UIScrollView rather than passing the touch events to another view. Apple themselves admitting that there is a problem with passing touch events.
Here is an extract of their reply:
"It looks like not all touch events are getting through to your view controller. Your UIScrollView is blocking touch events from getting through, even though is forwards those events to the next responder. The behaviour is very erratic, some touch events are being forwarded to your view controller, but not all of them."
"Looks like a behaviour change in iOS 5.0.x. My guess it's because of the view controller containment feature that was introduced."
The other way to do it is to use UIGestureRecognizer to implement dragging of views. Something like the code below:
- (void)viewDidLoad
{
// ... other initialization code here
UILongPressGestureRecognizer *longPress = [[[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(dragChild:)] autorelease];
[longPress setMinimumPressDuration:0]; // recognize immediately when a finger comes down
[draggableView addGestureRecognizer:longPress];
}
- (void)dragChild:(UILongPressGestureRecognizer *)longPress
{
[[longPress view] setCenter:[longPress locationInView:[[longPress view] 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...