How to change the positions of UIButton on iOS/iPhone - iphone

In my application, I am creating three UIButton inside, and I want these button should be swapped among it. (i.e) If I drag and drop the (button 1) and place it on (button 2), then
(button 2) should get replaced in the position of (button 1) and also the same for (button 3). I found, for how to drag and drop the UIButton, but I can't able to swap it.
Here is my code for button creation and drag and drop:
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setTitle:#"Drag One!" forState:UIControlStateNormal];
// add drag listener
[button addTarget:self action:#selector(wasDragged:withEvent:)
forControlEvents:UIControlEventTouchDragInside];
// center and size
button.frame = CGRectMake((self.view.bounds.size.width - 10)/2.0,
(self.view.bounds.size.height - 50)/2.0,
100, 50);
button.tag=0;
[self.view addSubview:button];
.........
-(void)wasDragged:(UIButton *)button withEvent:(UIEvent *)event
{
if(button.tag==0){
UITouch *touch = [[event touchesForView:button] anyObject];
// get delta
CGPoint previousLocation = [touch previousLocationInView:button];
CGPoint location = [touch locationInView:button];
CGFloat delta_x = location.x - previousLocation.x;
CGFloat delta_y = location.y - previousLocation.y;
// move button
button.center = CGPointMake(button.center.x + delta_x,
button.center.y + delta_y);
}
...........
}

Use code like this:
[UIView animateWithDuration:0.5
delay:0.1
options: UIViewAnimationCurveEaseOut
animations:^
{
CGSize s = [[CCDirector sharedDirector] winSize];
CGRect frame = mButton.frame;
frame.origin.y = location.y ;
frame.origin.x = location.x ;
mButton.frame = frame;
}
completion:^(BOOL finished)
{
}];

Related

How to make UIButton Draggeable?

I need to drag and drop the uibutton in subview only.
Actually i am taking subview in main view. UIbutton is add in subview. When i drag the button it moves on both view but i need to drag button only in subview. Can anyone help me please.
Thanks in advance.
- (void) drag
{
//subview
UIView *viewscramble = [[UIView alloc] initWithFrame:CGRectMake(0, 90, 320, 50)];
[viewscramble setBackgroundColor:[UIColor redColor]];
[self.view addSubview:viewscramble];
//button
UIButton *btnscramble = [[UIButton alloc] initWithFrame:CGRectMake(5, 0, 50, 50)];
btnscramble.titleLabel.text = #"A";
[btnscramble setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[btnscramble addTarget:self action:#selector(imageMoved:withEvent:) forControlEvents:UIControlEventTouchDragInside];
[btnscramble setBackgroundImage:[UIImage imageNamed:#"box.png"] forState:UIControlStateNormal];
//add button`
[viewscramble addSubview:btnscramble];
[btnscramble release];
}
- (IBAction)imageMoved:(id)sender withEvent:(UIEvent *) event
{
CGPoint point = [[[event allTouches]anyObject] locationInView:viewscramble];
UIControl *control = sender;
control.center = point;
}
i just found the solution of your Question from:- http://www.cocoanetics.com/2010/11/draggable-buttons-labels/
- (void)viewDidLoad
{
[super viewDidLoad];
// create a new button
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setTitle:#"Drag me!" forState:UIControlStateNormal];
// add drag listener
[button addTarget:self action:#selector(wasDragged:withEvent:)
forControlEvents:UIControlEventTouchDragInside];
// center and size
button.frame = CGRectMake((self.view.bounds.size.width - 100)/2.0,
(self.view.bounds.size.height - 50)/2.0,
100, 50);
// add it, centered
[self.view addSubview:button];
}
- (void)wasDragged:(UIButton *)button withEvent:(UIEvent *)event
{
// get the touch
UITouch *touch = [[event touchesForView:button] anyObject];
// get delta
CGPoint previousLocation = [touch previousLocationInView:button];
CGPoint location = [touch locationInView:button];
CGFloat delta_x = location.x - previousLocation.x;
CGFloat delta_y = location.y - previousLocation.y;
// move button
button.center = CGPointMake(button.center.x + delta_x,
button.center.y + delta_y);
}
Hope its helpful for you :)
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint pointMoved = [touch locationInView:"SUBVIEWNAME.view"];  
    button.frame = CGRectMake(pointMoved.x, pointMoved.y, 64, 64);
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *tap = [touches anyObject];
CGPoint pointToMove = [tap locationInView:yourSubView]; // just assign subview where you want to move the Button
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
if([touch view] == YOUR_BUTTON_OBJECT){
CGPoint point = [touch locationInView:YOUR_PARENT_VIEW];
//YOUR_X_LIMIT is your subview end in x direction.
//YOUR_Y_LIMIT is your subview end in y direction.
if(point.x < YOUR_X_LIMIT && point.y < YOUR_Y_LIMIT){
button.center = point;
}else{
// do nothing since touch is outside your limit.
}
}
}
Use UIControlEventTouchDragInside and UIControlEventTouchUpInside events of UIButton like
// add drag listener
[button addTarget:self action:#selector(wasDragged:withEvent:) forControlEvents:UIControlEventTouchDragInside];
// add tap listener
[button addTarget:self action:#selector(wasTapped:) forControlEvents:UIControlEventTouchUpInside];
You can use hbdraggablebutton control..

drag & rotate gesture on iPad

I have a problem, I want to add some gesture to a uibutton for move and rotate it, I use this code
[self.button addTarget:self action:#selector(wasDragged:withEvent:) forControlEvents:UIControlEventTouchDragInside];
UIRotationGestureRecognizer *rotationGesture = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:#selector(handleRotate:)];
[self.button addGestureRecognizer:rotationGesture];
- (void)wasDragged:(UIButton *)button withEvent:(UIEvent *)event
{
// get the touch
UITouch *touch = [[event touchesForView:self.button] anyObject];
// get delta
CGPoint previousLocation = [touch previousLocationInView:self.button];
CGPoint location = [touch locationInView:self.button];
CGFloat delta_x = location.x - previousLocation.x;
CGFloat delta_y = location.y - previousLocation.y;
// move button
self.button.center = CGPointMake(self.button.center.x + delta_x,self.button.center.y + delta_y);
}
- (void)handleRotate:(UIRotationGestureRecognizer *)recognizer {
if(recognizer.state == UIGestureRecognizerStateBegan || recognizer.state == UIGestureRecognizerStateChanged)
{
recognizer.view.transform = CGAffineTransformRotate(recognizer.view.transform, recognizer.rotation);
[recognizer setRotation:0];
}
}
all work I can rotate the button and move the button, the problem is if I rotate the button and then move it...in this case not work, I can move the button but not where I want...where is the problem?
You are calculating the difference between the position of touches relative to the button. This does not work as expected when the button is rotated. Instead you should try computing it relative to the superview of the button or the window.
Instead of this:
CGPoint previousLocation = [touch previousLocationInView:self.button];
CGPoint location = [touch locationInView:self.button];
You should use this:
CGPoint previousLocation = [touch previousLocationInView:self.button.superview];
CGPoint location = [touch locationInView:self.button.superview];

how to detect wether the UIImage is moving

I am creating an UIImageView through timer which is called in touchesended and moving it. After completion of animation I am removing its object. If I touch the screen continuously 6 to 7 times, one of the image(created from the timer code block) is not moving and so not deallocating..
this is my code:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:self.view];
flakeImage = [UIImage imageNamed:#"bubble.png"];
TimerView1=[NSTimer scheduledTimerWithTimeInterval:(0.1) target:self selector:#selector(onTimer:) userInfo:[NSValue valueWithCGPoint:location] repeats:NO];
}
- (void)onTimer:(id) sender {
NSValue *value=[TimerView1 userInfo];
CGPoint location = [value CGPointValue];
int time= [secLabel.text intValue];
int tick = 0;
tick = time+1;
secLabel.text = [NSString stringWithFormat:#"%.2i", tick];
double scale = 1 / round(random() % 100) + 1.0;
double speed = 1 / round(random() % 100) + 1.0;
UIImageView* flakeView1 = [[UIImageView alloc]initWithImage:flakeImage];
flakeView1.tag=100;
int endX = round(random() % 320);
int endY = round(random() % 480);
flakeView1.frame = CGRectMake(location.x, location.y, 35.0 * scale, 35.0 * scale);
[self.view addSubview:flakeView1];
[UIView beginAnimations:nil context:flakeView1];
[UIView setAnimationDuration:6 * speed];
flakeView1.frame = CGRectMake(endX,endY, 5.0 * scale, 5.0 * scale);
[UIView setAnimationDidStopSelector:#selector(onAnimationComplete:finished:context:)];
[UIView setAnimationDelegate:self];
[UIView commitAnimations];
if(tick == 1)
{
[TimerView1 invalidate];
secLabel.text=[NSString stringWithFormat:#"0"];
}
}
- (void)onAnimationComplete:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
UIImageView *flakeView1 = context;
[flakeView1 removeFromSuperview];
[flakeView1 release];
flakeView1=nil;
}
I dont know why it is happening..Is there any way to detect if that image is moving or not?
I have seen many posts, they suggest to use animationKeys.How to use that for detecting if image is Animating or not?

Changing an Image on TouchesBegan

Hey, I am trying to change the image when the user touches the ImageView. At the moment the ImageView has the image "heart1.png" so when i touch the ImageViewer on screen it will change to "heart2.png" this is my code, help is much appreciated:
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:self.view];
if (location.x >= imageView.frame.origin.x && location.x <= imageView.frame.origin.x + imageView.frame.size.height && location.y >= imageView.frame.origin.y && location.y <= imageView.frame.origin.y + imageView.frame.size.height) {
imageView.image = [UIImage imageNamed:#"heart2.png"];
}
}
That looks like a problem to me:
if (location.x >= imageView.frame.origin.x && location.x <= imageView.frame.origin.x + imageView.frame.size.--> height <--
should be width there probably :)
Rather than fool around with checking coordinates against a bounding rect, why don't you simplify things by using interface building to place a custom (i.e. invisible) UIButton right over the image? Then you can hook up touchesUpInside to an IBAction method. Then there's no awkward if statements in your code and less chance of making mistakes like this.
Consider using an UIButton instead.
[button setImage:[UIImage imageNamed:#"heart1.png"] forState:UIControlStateNormal];
[button setImage:[UIImage imageNamed:#"heart2.png"] forState:UIControlStateHighlighted];
There is no need to find location of view, You don't have to do move UIImageView. Simply do this:
-(void)viewDidLoad
{
// imageView is your UIImageView
imageView = [[UIImageView alloc]initWithFrame:CGRectMake(0.0, 0.0, 320.0, 480.0)];
[imageView setImage:[UIImage imageNamed:#"heart1.png"]];
[imageView setUserInteractionEnabled:YES];
// Make sure userInteractionEnable is set to be YES; otherwise the touch event will be happen on UIView not on ImageView;
[self.view addSubview:imageView];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches]anyObject];
if([touch view]==imageView)
[imageView setImage:[UIImage imageNamed:#"heart2.png"]];
}

Drag and drop objects and return them to their original position

I'm trying to drag an image and let it return to it's original position after releasing it. So far, I can drag an image by creating it as a button using the following code: (as seen in the answer to this question: Basic Drag and Drop in iOS )
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self action:#selector(imageTouch:withEvent:) forControlEvents:UIControlEventTouchDown];
[button addTarget:self action:#selector(imageMoved:withEvent:) forControlEvents:UIControlEventTouchDragInside];
[button setImage:[UIImage imageNamed:#"vehicle.png"] forState:UIControlStateNormal];
[self.view addSubview:button];
And later I define:
- (IBAction) imageMoved:(id) sender withEvent:(UIEvent *) event
{
CGPoint point = [[[event allTouches] anyObject] locationInView:self.view];
UIControl *control = sender;
control.center = point;
}
How can I make it return to it's original position after releasing it ?, for starters I will save the position at which each image is supposed to return, but then, there is anyway to indicate an UIImage to go from it's current position and move to another one ?, or any other alterative solution ?
UIGestureRecognizer is recommended by Apple for recent iOSes. You can use it not only for UIButton, but also for UIView (especially UIImageView in your case), etc. So I would like to recommend it.
In the interface:
#interface TestDragViewController : UIViewController {
IBOutlet UIImageView *dragImage;
CGPoint originalCenter;
}
In viewDidLoad, plz remember to enable userInteraction:
- (void)viewDidLoad {
[super viewDidLoad];
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self
action:#selector(dragGesture:)];
[dragImage addGestureRecognizer:panGesture];
[dragImage setUserInteractionEnabled:YES];
}
And in its selector, I just set animation to visualize the returning effect:
#pragma mark -
#pragma mark UIPanGestureRecognizer selector
- (void) dragGesture:(UIPanGestureRecognizer *) panGesture{
CGPoint translation = [panGesture translationInView:self.view];
switch (panGesture.state) {
case UIGestureRecognizerStateBegan:{
originalCenter = dragImage.center;
}
break;
case UIGestureRecognizerStateChanged:{
dragImage.center = CGPointMake(dragImage.center.x + translation.x,
dragImage.center.y + translation.y);
}
break;
case UIGestureRecognizerStateEnded:{
[UIView animateWithDuration:kImageReturnTime
animations:^{
dragImage.center = originalCenter;
}
completion:^(BOOL finished){
NSLog(#"Returned");
}];
}
break;
default:
break;
}
[panGesture setTranslation:CGPointZero inView:self.view];
}
Cheers,
Tommy
Define CGPoint Globally, or in .h file.
CGPoint point;
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self action:#selector(imageTouch:withEvent:)forControlEvents:UIControlEventTouchDown];
[button addTarget:self action:#selector(imageMoved:withEvent:) forControlEvents:UIControlEventTouchDragInside];
[button setImage:[UIImage imageNamed:#"vehicle.png"] forState:UIControlStateNormal];
[self.view addSubview:button];
And later I define:
- (IBAction) imageMoved:(UIButton*) sender withEvent:(UIEvent *) event
{
point = [[[event allTouches] anyObject] locationInView:self.view];
UIControl *control = sender;
control.center = point;
[sender addTarget:self action:#selector(touches:withEvent:) forControlEvents:UIControlEventTouchUpInside];
}
-(void)touches:(UIButton *)button withEvent:(UIEvent *)event {
[UIView animateWithDuration:0.1 delay:0 options:UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionAllowUserInteraction animations:^{
button.center = point;
} completion:^(BOOL finished){
if (finished) {
// do anything yu want
}
it works awesome cause i am using it in my project!
How about calling a selector on UIControlEventTouchUpInside and then in the selector, just set the frame of your button to a new x and y coordinate (the ones that you have saved).
In the solution I linked to in the thread you are referring I have created a generic drag drop manager that takes care of the return of a dragged object to the original position (if released outside a known dropzone). Currently there is no animation in the solution, but you could combine some of the ideas presented above.
See the some how generic drag and drop solution in iOS
You know what, I was just working on this yesterday, so here you go with a little bonus animation:
- (void)previewImageTouchUpInside:(UIButton*)aButton {
if (!previewImageDragged) {
[self selectPreviewImage:aButton];
return;
}
previewImageDragged = NO;
// If user drag photo a little and then release, we'll still treat it as a tap
// instead of drag
if ((originalPositionOfButton.x - aButton.center.x) *
(originalPositionOfButton.x - aButton.center.x) +
(originalPositionOfButton.y - aButton.center.y) *
(originalPositionOfButton.y - aButton.center.y) < 10) {
aButton.center = originalPositionOfButton;
[self selectPreviewImage:aButton];
return;
}
[UIView animateWithDuration:0.5
delay:0
options:UIViewAnimationOptionCurveEaseOut |
UIViewAnimationOptionAllowUserInteraction animations:^{
aButton.center = originalPositionOfButton;
} completion:nil];
}
- (void)previewImageDraggedInside:(UIButton*)aButton event:(UIEvent*)event {
if (!previewImageDragged) {
originalPositionOfButton = aButton.center;
[self.view bringSubviewToFront:aButton];
[self.view bringSubviewToFront:[self.view viewWithTag:CHOOSE_PHOTO_BUTTON_TAG]];
}
UITouch* touch = [[event allTouches] anyObject];
previewImageDragged = YES;
aButton.center = CGPointMake(aButton.center.x+[touch locationInView:self.view].x-
[touch previousLocationInView:self.view].x,
aButton.center.y+[touch locationInView:self.view].y-
[touch previousLocationInView:self.view].y);
}
It still has a few magic numbers and I haven't renamed the functions and variables to suit your example, but it should be clear. I also did the indentation here since I don't manually break long lines in my code.