I want to drag my label in Application. I create new label when starting Application
UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, 100, 200, 100)];
myLabel.text = #"DRAG ME!!!";
[self.view addSubview:myLabel];
How can I drag this label? I can't find normal tutorial and i new in Xcode...
The following implementation may help you. Change your above label with this one and you can see that now your label is draggable.
#import "DraggableLabel.h"
#interface DraggableLabel()
{
CGPoint _previousLocation;
}
#end
#implementation DraggableLabel
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.userInteractionEnabled = YES;
UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self
action:#selector(handlePan:)];
self.gestureRecognizers = #[panRecognizer];
}
return self;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.superview bringSubviewToFront:self];
_previousLocation = self.center;
}
- (void)handlePan:(UIPanGestureRecognizer *)panGestureRecognizer
{
CGPoint translation = [panGestureRecognizer translationInView:self.superview];
self.center = CGPointMake(_previousLocation.x + translation.x,
_previousLocation.y + translation.y);
}
#end
Related
Hello fellow programmers.,
I want to create dynamic UIView of size 100X100 around my double click on Main UIView (Everytime I double click diffrant place). I totally don't have any idea about it. So can't provide any code for it. Anyone can help??
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *myTouch = [[touches allObjects] objectAtIndex: 0];
CGPoint currentPos = [myTouch locationInView: self.view];
NSLog(#"Point in myView: (%f,%f)", currentPos.x, currentPos.y);
UIView*hover = [[UIView alloc] initWithFrame:CGRectMake(currentPos.x - 50, currentPos.y - 50 , 100, 100)];
hover.backgroundColor = [UIColor grayColor];
[self.view addSubview:hover];
}
try this code
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(addDynamicView:)];
self.view.userInteractionEnabled = TRUE;
tapGesture.numberOfTapsRequired = 2;
[self.view addGestureRecognizer:tapGesture];
adding the custom view
- (void)addDynamicView:(UITapGestureRecognizer*)aGesture{
/** add view with specified frame **/
CGRect rect = CGRectMake(10, 10, 100, 100);
UIView *lView = [[UIView alloc] initWithFrame:rect];
lView.backgroundColor = [UIColor blackColor];
[self.view addSubview:lView];
}
I'd like to drag customView.
But, when I drag the customView, it always move from location (0, 0).
Please look at following image.
the red parts is the customView, and when I drag it, it move to the location.
How do I fix it to make move customView correctly?
I have this code.
labelview is the customView(subclass of UIView).
- (void)viewDidLoad
{
[super viewDidLoad];
_labelView = [[LabelView alloc]initWithFrame:CGRectMake(20, 60, 200, 100)];
UIPanGestureRecognizer* pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:#selector(panAction:)];
[_labelView addGestureRecognizer:pan];
[self.view addSubview:_labelView];
}
- (void)panAction:(UIPanGestureRecognizer *)sender
{
CGPoint p = [sender translationInView:self.view];
CGPoint movedPoint = CGPointMake(_labelView.center.x + p.x, _labelView.center.y + p.y);
sender.view.center = movedPoint;
[sender setTranslation:movedPoint inView:self.view];
}
While the other two answers are technically correct, they are not ideal solutions because when you add a gesture recognizer to self.view then anytime you drag anywhere in self.view you will drag your LabelView, but I imagine you only want to drag it when you actually have your finger on the LabelView itself.
So, just keep what you have, but change this one line:
[sender setTranslation:movedPoint inView:self.view];
to
[sender setTranslation:CGPointZero inView:self.view];
You have implemented the logic upside down. It has to be exactly other way around. Set the ´UIPanGestureRecognizer´ to UIViewController's view and set the center of your custom view.
- (void)viewDidLoad
{
[super viewDidLoad];
_labelView = [[LabelView alloc]initWithFrame:CGRectMake(20, 60, 200, 100)];
UIPanGestureRecognizer* pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:#selector(panAction:)];
// [_labelView addGestureRecognizer:pan]; must be removed
[self.view addGestureRecognizer:pan]; // must be added
[self.view addSubview:_labelView];
}
- (void)panAction:(UIPanGestureRecognizer *)sender
{
CGPoint p = [sender translationInView:self.view];
CGPoint movedPoint = CGPointMake(_labelView.center.x + p.x, _labelView.center.y + p.y);
[_labelView setCenter:movedPoint];
}
I solved by writing following code.
Thank you for answers.
- (void)viewDidLoad
{
[super viewDidLoad];
_labelView = [[LabelView alloc]initWithFrame:CGRectMake(20, 60, 200, 100)];
UIPanGestureRecognizer* pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:#selector(panAction:)];
[_labelView addGestureRecognizer:pan];
[self.view addSubview:_labelView];
}
- (void)panAction:(UIPanGestureRecognizer *)sender
{
CGPoint p = [sender translationInView:sender.view];
CGPoint movedPoint = CGPointMake(sender.view.center.x + p.x, sender.view.center.y + p.y);
sender.view.center = movedPoint;
[sender setTranslation:CGPointZero inView:sender.view];
}
I'd like to make some drag-able UIView.
But in case of following code, you can drag only one UIView you have added at the last.
I have this code.
LabelView class is subclass of UIView.
ViewControlle.h
#interface ViewController : UIViewController
#property (nonatomic, strong) LabelView* labelView;
#end
ViewController.m
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_labelView = [[LabelView alloc]initWithFrame:CGRectMake(100, 200, 200, 50)];
[self.view addSubview:_labelView];
UIPanGestureRecognizer* pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:#selector(panAction:)];
[_labelView addGestureRecognizer:pan];
UIButton* addButton = [[UIButton alloc]initWithFrame:CGRectMake(270, 60, 40, 40)];
[addButton addTarget:self action:#selector(newLabelView) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:addButton];
}
- (void)panAction:(UIPanGestureRecognizer *)sender
{
CGPoint p = [sender translationInView:self.view];
CGPoint movedPoint = CGPointMake(_labelView.center.x + p.x, _labelView.center.y + p.y);
_labelView.center = movedPoint;
[sender setTranslation:CGPointZero inView:self.view];
}
- (void)newLabelView
{
_labelView = [[LabelView alloc]initWithFrame:CGRectMake(20, 60, 200, 50)];
[self.view addSubview:_labelView];
UIPanGestureRecognizer* pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:#selector(panAction:)];
[_labelView addGestureRecognizer:pan];
}
You should apply the getsture for all the view. and then change the methods. _labelView.center = movedPoint; to [sender view].center = movedPoint;
- (void)panAction:(UIPanGestureRecognizer *)sender
{
CGPoint p = [sender translationInView:self.view];
CGPoint movedPoint = CGPointMake(_labelView.center.x + p.x, _labelView.center.y + p.y);
[sender view].center = movedPoint;
[sender setTranslation:CGPointZero inView:self.view];
}
You could create a mutable array, and then add each new view into that array. You do this by adding:
NSMutableArray *viewsArray = [[NSMutableArray alloc] init];
// after creating the custom view
[viewsArray addObject:customView];
Then, you can add a pan gesture on top of the views in the array, that way they are all using the pan gesture
for(LabelView *l in viewsArray) {
[l addGestureRecognizer:panGestureRecognizer];
}
this will add a UIPanGestureRecognizer to all the custom views in the array that you created in the beginning of this answer.
Hope this helps!
I'm using UIDynamics in my app. my app has two squares. one is fixed and the other can be moved (by applying a pan gesture). when i try to collide them they don't collide. the delegate methods never get called. here's my code and i hope someone can point out the problem.
UIDynamicAnimator* animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
UICollisionBehavior* collisionBehavior = [[UICollisionBehavior alloc] initWithItems:#[self.square1, self.square2]];
collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePan:)];
[self.square1 addGestureRecognizer:pan];
[collisionBehavior setCollisionMode:UICollisionBehaviorModeEverything];
[animator addBehavior:collisionBehavior];
collisionBehavior.collisionDelegate = self;
Make animator as a property or instance variable. otherwise it will
be cleared after view load.
Make sure implemented UICollisionBehaviorDelegate protol and correspond methods
Here is my works implementation based on your code.
Interface:
#import <UIKit/UIKit.h>
#interface DynamicViewController : UIViewController<UICollisionBehaviorDelegate>
#property (strong, nonatomic) UIDynamicAnimator *animator;
#property (strong, nonatomic) UIPushBehavior *pushBehavior;
#end
Implementation:
#synthesize pushBehavior = _pushBehavior;
#synthesize animator = _animator;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
UIView *square1 = [[UIView alloc] initWithFrame:CGRectMake(100, 30, 30, 30)];
square1.center = CGPointMake(150, 150);
square1.backgroundColor = [UIColor greenColor];
UIView *square2 = [[UIView alloc] initWithFrame:CGRectMake(100, 300, 30, 30)];
square2.center = CGPointMake(250, 350);
square2.backgroundColor = [UIColor redColor];
[self.view addSubview:square1];
[self.view addSubview:square2];
_animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
UICollisionBehavior* collisionBehavior = [[UICollisionBehavior alloc] initWithItems:#[square1, square2]];
collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
[collisionBehavior setCollisionMode:UICollisionBehaviorModeEverything];
collisionBehavior.collisionDelegate = self;
[_animator addBehavior:collisionBehavior];
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePan:)];
[square1 addGestureRecognizer:pan];
}
#pragma mark push behavior
- (void)handlePan:(UIPanGestureRecognizer *)gesture
{
if(gesture.state == UIGestureRecognizerStateBegan){
if (_pushBehavior) {
[_animator removeBehavior:_pushBehavior];
}
_pushBehavior = [[UIPushBehavior alloc] initWithItems:#[gesture.view] mode:UIPushBehaviorModeContinuous];
[_animator addBehavior:_pushBehavior];
}
CGPoint offset =[gesture translationInView:self.view];
_pushBehavior.pushDirection = CGVectorMake(offset.x,offset.y);
_pushBehavior.magnitude = sqrtf(offset.x * offset.x + offset.y * offset.y) / 50;
if (gesture.state == UIGestureRecognizerStateEnded) {
[_animator removeBehavior:_pushBehavior];
_pushBehavior = nil;
}
}
#pragma mark Colision delegate
- (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2 atPoint:(CGPoint)p;
{
NSLog(#"Colision Began");
}
- (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2;
{
NSLog(#"Colision End");
}
Your UIDynamicAnimator* animator is destroyed when function ends due to ARC. Thats why you are not able to see any animations. Make it a instance variable and you will be fine.
I think there is some bug with UIDynamics (but not 100% sure let me know if I'm wrong).
I couldn't make my dynamic works until I created instance variables for UIDynamicAnimator and UIGravityBehavior.
Try add instance variable to the .m file in class extension as:
UIDynamicAnimator* animator;
UICollisionBehavior* collisionBehavior;
And change your first two line of code to:
animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
collisionBehavior = [[UICollisionBehavior alloc] initWithItems:#[self.square1, self.square2]];
It should help.
You have to specify the bounds using "addBoundaryWithIdentifier" for the collision class and remove the non-moving item form the collision
I was trying to create a label that should be draggable. But the dragged event is not firing (checked with break point). Below is the code.
- (IBAction)InsertText:(UIBarButtonItem *)sender {
UILabel *lblWatermark = [[UILabel alloc] initWithFrame:currentImage.frame];
lblWatermark.text = #"Copyright";
lblWatermark.userInteractionEnabled = YES;
[lblWatermark sizeToFit];
UIPanGestureRecognizer *gesture = [[UIPanGestureRecognizer alloc]
initWithTarget:self
action:#selector(labelDragged:)];
[lblWatermark addGestureRecognizer:gesture];
[currentImage addSubview:lblWatermark];
}
- (void)labelDragged:(UIPanGestureRecognizer *)gesture
{
UILabel *label = (UILabel *)gesture.view;
CGPoint translation = [gesture translationInView:label];
// move label
label.center = CGPointMake(label.center.x + translation.x,
label.center.y + translation.y);
[gesture setTranslation:CGPointZero inView:label];
}
Thank you in advance,
Spotted the error. Actually I had also to make
userInteractionEnabled = YES
Not only for the label But also for the Imageview in which I am adding the label.
Make sure your ViewController is the delegate for UIGestureRecognizer with (.h file):
#interface View : UIView <UIGestureRecognizerDelegate>
And then set:
gesture.delegate = self;