Collison behaviour boundries not respected - ios

Presenting a UIView from under the nav bar with "bounce effect" self.dropDownBar
Despite setting up boundaries the UIView continues to drop off the bottom of the screen
Checked here https://developer.apple.com/library/ios/documentation/uikit/reference/UICollisionBehavior_Class/Reference/Reference.html#//apple_ref/occ/instm/UICollisionBehavior/addBoundaryWithIdentifier:fromPoint:toPoint:
That states:
addBoundaryWithIdentifier:fromPoint:toPoint:
p1
The starting point for the boundary line segment.
p2
The ending point for the boundary line segment. Seem to be doing that,
and here Collision not working between items (no accepted answer and nothing suitable)
.h
<UICollisionBehaviorDelegate>
#property (strong, nonatomic) UIDynamicAnimator *animator;
.m
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
UIGravityBehavior* gravityBehavior =
[[UIGravityBehavior alloc] initWithItems:#[self.dropDownBar]];
[self.animator addBehavior:gravityBehavior];
UICollisionBehavior* collisionBehavior =
[[UICollisionBehavior alloc] initWithItems:#[self.dropDownBar]];
//To - from boundries
[collisionBehavior addBoundaryWithIdentifier:#"NotificationBoundary" fromPoint:CGPointMake(0, 45)
toPoint:CGPointMake(0, 90)];
[self.animator addBehavior:collisionBehavior];
What am I missing here?

Related

What's the proper way to add UIKit Dynamics to UICollectionViewCells?

I'm trying to use UIKit Dynamics to implement swipe-to-delete on my UICollectionViewCells. Things aren't going as planned, though. Here's the code in UICollectionViewCell's awakeFromNib method:
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.contentView];
UICollisionBehavior *collisionBehavior = [[UICollisionBehavior alloc] initWithItems:#[self.contentView]];
[collisionBehavior setTranslatesReferenceBoundsIntoBoundaryWithInsets:UIEdgeInsetsMake(0, 0, 0, -20)];
[self.animator addBehavior:collisionBehavior];
self.gravityBehavior = [[UIGravityBehavior alloc] initWithItems:#[self.containerView]];
self.gravityBehavior.gravityDirection = CGVectorMake(0, 0);
[self.animator addBehavior:self.gravityBehavior];
self.pushBehavior = [[UIPushBehavior alloc] initWithItems:#[self.containerView] mode:UIPushBehaviorModeInstantaneous];
self.pushBehavior.magnitude = 0.0f;
self.pushBehavior.angle = 0.0f;
[self.animator addBehavior:self.pushBehavior];
UIDynamicItemBehavior *itemBehavior = [[UIDynamicItemBehavior alloc] initWithItems:#[self.containerView]];
itemBehavior.elasticity = 0.45f;
[self.animator addBehavior:itemBehavior];
But this is not working so well. This is what happens at launch with the code above:
That behavior seems to be mostly generated by UICollisionBehavior. If I comment it out, the container view with everything that's not the red background doesn't animate, but does show up offset a few points to the left.
Am I right to try to implement this within UICollectionViewCell? What's the right way of doing this?
Thanks!
Never mind. It was pretty much a typo. The collision behavior was attached to the wrong object.
The right code should be
UICollisionBehavior *collisionBehavior = [[UICollisionBehavior alloc] initWithItems:#[self.containerView]];
[collisionBehavior setTranslatesReferenceBoundsIntoBoundaryWithInsets:UIEdgeInsetsMake(0, 0, 0, -20)];
[self.animator addBehavior:collisionBehavior];

Is it possible to add multiple UIGravityBehaviors to a UIDynamicAnimator?

I'm trying to create a view where some items fall along normal gravity vector and others fall along an opposite vector
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self];
// Normal Gravity
self.gravityBehavior = [[UIGravityBehavior alloc] initWithItems:#[ ]];
self.gravityBehavior.gravityDirection = CGVectorMake(0, 1);
[self.animator addBehavior:self.gravityBehavior];
// Inverse Gravity
self.inverseGravityBehavior = [[UIGravityBehavior alloc] initWithItems:#[ ]];
self.inverseGravityBehavior.gravityDirection = CGVectorMake(0, -1);
[self.animator addBehavior:self.inverseGravityBehavior];
I would think then I could just add some items to one behavior and some to the other, but it appears that adding the second gravity behavior overrides the first?
[self.gravityBehavior addItem: ballA];
[self.inverseGravityBehavior addItem: ballB];
Is this true, and if so is there another way to achieve this effect?
This behavior is definitely possible. However, it cannot be achieved with one animator using differing UIGravityBehaviors.
One solution would be to use two UIDynamicAnimator instances, each with its own UIGravityBehavior instance. Below is an example of a view controller that has two tap gesture recognizers attached, one for single tap, and one for double. The single will add a view that reacts to normal gravity. The double tap adds a view that reacts to inverted gravity. Obviously the code would need to be tweaked to match your specific requirements.
#import "ViewController.h"
#interface ViewController ()
#property (nonatomic, strong) UIDynamicAnimator *animator;
#property (nonatomic, strong) UIDynamicAnimator *secondAnimator;
#property (nonatomic, strong) UIGravityBehavior *normalGravity;
#property (nonatomic, strong) UIGravityBehavior *inverseGravity;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
self.normalGravity = [[UIGravityBehavior alloc] init];
[self.animator addBehavior:self.normalGravity];
self.secondAnimator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
self.inverseGravity = [[UIGravityBehavior alloc] init];
[self.inverseGravity setAngle:self.normalGravity.angle magnitude:(-1.0 * self.normalGravity.magnitude)];
[self.secondAnimator addBehavior:self.inverseGravity];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)viewWasTapped:(id)sender {
UIView *v = [[UIView alloc] initWithFrame:CGRectMake(30, 10, 25, 25)];
v.backgroundColor = [UIColor redColor];
[self.view addSubview:v];
[self.normalGravity addItem:v];
}
- (IBAction)viewWasDoubleTapped:(id)sender {
UIView *v = [[UIView alloc] initWithFrame:CGRectMake(90, 400, 25, 25)];
v.backgroundColor = [UIColor greenColor];
[self.view addSubview:v];
[self.inverseGravity addItem:v];
}
#end
A second option would be to use a UIPushBehavior to simulate inverted gravity. Below is a similarly set up view controller, but without the second animator and using the push behavior.
#import "ViewController.h"
#interface ViewController ()
#property (nonatomic, strong) UIDynamicAnimator *animator;
#property (nonatomic, strong) UIGravityBehavior *normalGravity;
#property (nonatomic, strong) UIPushBehavior *pushBehavior;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
self.normalGravity = [[UIGravityBehavior alloc] init];
[self.animator addBehavior:self.normalGravity];
self.pushBehavior = [[UIPushBehavior alloc] initWithItems:#[] mode:UIPushBehaviorModeContinuous];
[self.pushBehavior setAngle:self.normalGravity.angle magnitude:(-1.0 * self.normalGravity.magnitude)];
[self.animator addBehavior:self.pushBehavior];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)viewWasTapped:(id)sender {
UIView *v = [[UIView alloc] initWithFrame:CGRectMake(30, 10, 25, 25)];
v.backgroundColor = [UIColor redColor];
[self.view addSubview:v];
[self.normalGravity addItem:v];
}
- (IBAction)viewWasDoubleTapped:(id)sender {
UIView *v = [[UIView alloc] initWithFrame:CGRectMake(90, 400, 25, 25)];
v.backgroundColor = [UIColor greenColor];
[self.view addSubview:v];
[self.pushBehavior addItem:v];
}
#end
In all situations be sure you are managing which items are being impacted by the UIDynamicAnimator and the various behaviors so that you are not constantly adding to them and bogging the simulation down.

IOS UIView Bounce Animation

I have a UIVIew (container) and another UIView (box) the box view is inside of the ContainerView. When a UIButton is pressed I would like the box view to drop down off the bottom of the screen, and bounce with 10px left; then once the bouncing has stopped I still want the box to have 10px showing. Here is some sample code of from another question:
UIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:self]; //self is the container
UIGravityBehavior* gravityBehavior = [[UIGravityBehavior alloc] initWithItems:#[box]];
[animator addBehavior:gravityBehavior];
UICollisionBehavior* collisionBehavior = [[UICollisionBehavior alloc] initWithItems:#[reportBar.bar]];
collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
[animator addBehavior:collisionBehavior];
UIDynamicItemBehavior *elasticityBehavior =
[[UIDynamicItemBehavior alloc] initWithItems:#[box]];
elasticityBehavior.elasticity = 0.7f;
[animator addBehavior:elasticityBehavior];
The code is running when it should but the box isn't dropping.
Edit 1:
Self refers to the container UIView
I have also tried changing self for the currentViewController.view, no change.
Edit 2:
all of this code is inside the container view implementation file.
give a try to make animator property,
#property UIDynamicAnimator *animator;
and then your code,
_animator = [[UIDynamicAnimator alloc] initWithReferenceView:self];
...
I think you didn't specify the correct reference view. It should be either self.view or self.containerView
UIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:self];
Update
I think you should put the code in the ViewController for this scene and as #BaSha suggested create a animator property and after a button click you will add the behavior and will reference self.containerView
Just make sure that boxView is inside of the containerView
The following code snippet can provide BOUNCE EFFECT on your views.
CABasicAnimation * animation = [CABasicAnimation animationWithKeyPath:#"position.y"];</br>
[animation setFromValue:[NSNumber numberWithFloat:y-position1]];
[animation setToValue:[NSNumber numberWithFloat:y-position2]];
[animation setDuration:.7]; // time gap between the bounces
animation.repeatCount=500; // no:of times bounce effect has to be done
[YOURVIEW.layer addAnimation:animation forKey:#"somekey"];

Collision Behavior not working

I am trying my hand at UIKit Dynamics and am trying to create a simple animation with a ball that bounces off of the screen boundaries.
As shown in the code below, when I add the gravity behavior the ball seems to go off the screen as expected. But when I add the collision behavior, nothing happens. The ball stays as is at the center of the screen where I have drawn it initially.
I also trie to add a push behavior with continuous push force option, but still the ball does not move.
#implementation TAMViewController
UIDynamicAnimator* animator;
UIGravityBehavior* gravity;
UICollisionBehavior* collision;
UIPushBehavior* push;
- (void)viewDidLoad
{
[super viewDidLoad];
TAMBouncyView *ballView = [[TAMBouncyView alloc] initWithFrame:CGRectMake(0,0,
self.view.frame.size.width,
self.view.frame.size.height)];
[self.view addSubview:ballView];
animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
gravity = [[UIGravityBehavior alloc] initWithItems:#[ballView]];
[animator addBehavior:gravity];
collision = [[UICollisionBehavior alloc] initWithItems:#[ballView]];
[collision setTranslatesReferenceBoundsIntoBoundary:YES];
[animator addBehavior:collision];
push = [[UIPushBehavior alloc] initWithItems:#[ballView]
mode:UIPushBehaviorModeContinuous];
[animator addBehavior:push];
// Do any additional setup after loading the view, typically from a nib.
}

iOS touchesBegan being overridden by UIScrollView. Not a delay issue. Can't use gesture recognizer in this case

So I read quite a bit, but still I can't find the solution.
I have a UIViewController which is creating (programatically) a UIScrollView, which Contains a UIView and a UIImage. The UIView lies on top of the rest.
This UIView generates some UIImageViews which I need to get feedback from when tapped. I need to know which image was tapped by getting their tags. That's why I can't use gesture recognizer, since it can only be called on one view.
If I call this:
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
NSLog(#"tag=%#", [NSString stringWithFormat:#"%i", touch.view.tag]);
}
On the view (called GraphView, which has it's own class) I get what I need. Still, I need to do this from the ViewController side because I have to open modal window, navigation controllers, etc... If I use that same code on the ViewController nothing happens. If I disable User Interaction on the UIScrollView it works. If I disable the delay on the UIScrollView nothing happens. No matter how long you press you get nothing. touchesBegan doesn't get called at all even if the delay is enabled.
Here's the part of the implementation of the ViewController where I generate the Views:
// ScrollView
CGRect frame = CGRectMake(0, 0, 480, 320);
myScrollView = [[UIScrollView alloc] initWithFrame:frame];
myScrollView.backgroundColor = [UIColor blackColor];
myScrollView.showsVerticalScrollIndicator = YES;
myScrollView.showsHorizontalScrollIndicator = YES;
myScrollView.userInteractionEnabled = YES;
myScrollView.contentSize = CGSizeMake(SCROLLVIEW_WIDTH, SCROLLVIEW_HEIGHT);
myScrollView.delegate = self;
[self.view addSubview:myScrollView];
// Add UIImage for background
UIImageView *backgroundGraph = [[UIImageView alloc] initWithFrame:CGRectMake (0,0,SCROLLVIEW_WIDTH,SCROLLVIEW_HEIGHT)];
backgroundGraph.image = [UIImage imageNamed:#"graph_background.png"];
backgroundGraph.userInteractionEnabled = YES;
[myScrollView addSubview:backgroundGraph];
//[self.view addSubview:backgroundGraph];
[backgroundGraph release];
// Add View for Graph.
GraphView *graphViewC = [[GraphView alloc] init];
self.graphView = graphViewC;
graphView.tag = 200;
graphView.userInteractionEnabled = YES;
graphView.frame = CGRectMake(0, 0, SCROLLVIEW_WIDTH, SCROLLVIEW_HEIGHT);
graphView.backgroundColor = [UIColor clearColor];
[myScrollView addSubview:graphView];
//[self.view addSubview:graphView];
.h file on ViewController looks like this:
#import <UIKit/UIKit.h>
#class GraphView;
#interface TrackingViewController : UIViewController <UIScrollViewDelegate> {
UIScrollView *myScrollView;
GraphView *graphView;
int someNum;
#define SCROLLVIEW_HEIGHT 273
#define SCROLLVIEW_WIDTH 599
}
#property (nonatomic, retain) GraphView *graphView;
- (void) openModal;
//- (void)handleSingleTap:(UIGestureRecognizer *)gestureRecognizer;
#property (nonatomic, retain) UIScrollView *myScrollView;
#end
As always, I am thankful to everyone who can help with any ideas(and I've gotten a lot of help here always, so thanks in advance :-) ).

Resources