UIAttachmentBehavior in UITableViewCell just like Messages App - ios

I want to replicate the attachment behavior of UITableViewCell, just like what Apple made in the Messages App.
I tried subclassing UITableViewCell and here is the code :
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self];
self.attachmentBehavior = [[UIAttachmentBehavior alloc] initWithItem:self.superview attachedToAnchor:self.superview.center];
[self.attachmentBehavior setFrequency:4.5];
[self.attachmentBehavior setDamping:0.3];
UIGravityBehavior *gravityBehavior = [[UIGravityBehavior alloc] initWithItems:#[self]];
//gravity direction: right
[gravityBehavior setGravityDirection:CGVectorMake(0.0, -0.8)];
UICollisionBehavior *collisionBehavior = [[UICollisionBehavior alloc] initWithItems:#[self]];
[collisionBehavior addBoundaryWithIdentifier:#"topBoundary" fromPoint:CGPointMake(0.0f, 0.0f) toPoint:CGPointMake(self.contentView.frame.size.width, 0.0f)];
[collisionBehavior addBoundaryWithIdentifier:#"bottomBoundary" fromPoint:CGPointMake(0.0f, self.contentView.frame.size.height) toPoint:CGPointMake(self.contentView.frame.size.width, self.contentView.frame.size.height)];
UIDynamicItemBehavior* itemBehaviour = [[UIDynamicItemBehavior alloc] initWithItems:#[self]];
itemBehaviour.elasticity = 0.9;
[self.animator addBehavior:itemBehaviour];
[self.animator addBehavior:gravityBehavior];
[self.animator addBehavior:collisionBehavior];
But, it doesn't seem to work.
Can someone help me to reproduce the same functionality as the Messages app please ?
Edited :
I know that Apple uses UICollectionView instead tableview for the Messages App, but i hope there should be a way to do this kind of functionality through tableview also.

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];

Rotating an UIView using UIDynamics and gravity from CMMotionManager

I have an UIView which is a picture frame hanging on a nail from a string. I'm trying to rotate the view around its anchorPoint to keep the view's bottom flat(parallel with the ground) regardless of the devices rotation. I'm trying to achieve this by using CMMotionManager and UIDynamics and can't seem to get anything working properly today.
Here's some code...
- (void)viewDidLoad
{
[super viewDidLoad];
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
CGRect pictureFrameBounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(self.view.bounds)/2.5f, CGRectGetHeight(self.view.bounds)/5);
UIView *pictureFrame = [[UIView alloc] initWithFrame:pictureFrameBounds];
[pictureFrame setBackgroundColor:[UIColor redColor]];
[self.view addSubview:pictureFrame];
self.gravityBehavior = [[UIGravityBehavior alloc] initWithItems:#[pictureFrame]];
self.collisionBehavior = [[UICollisionBehavior alloc] initWithItems:#[pictureFrame]];
[self.collisionBehavior setTranslatesReferenceBoundsIntoBoundary:YES];
[self.animator addBehavior:self.collisionBehavior];
CGPoint anchorPoint = CGPointMake(CGRectGetMidX(self.view.bounds), CGRectGetHeight(self.view.bounds)/8);
self.attachmentBehavior = [[UIAttachmentBehavior alloc] initWithItem:pictureFrame
offsetFromCenter:UIOffsetMake(0.0f, -CGRectGetHeight(pictureFrame.bounds)/2.5f)
attachedToAnchor:anchorPoint];
[self.attachmentBehavior setDamping:0];
[self.attachmentBehavior setLength:0];
[self.attachmentBehavior setFrequency:0];
[self.animator addBehavior:self.attachmentBehavior];
UIDynamicItemBehavior *itemBehavior = [[UIDynamicItemBehavior alloc] initWithItems:#[pictureFrame]];
[itemBehavior setAllowsRotation:YES];
[self.animator addBehavior:itemBehavior];
NSOperationQueue* motionQueue = [NSOperationQueue new];
self.motionManager = [[CMMotionManager alloc] init];
[self.motionManager startDeviceMotionUpdatesToQueue:motionQueue
withHandler:^(CMDeviceMotion *motion, NSError *error) {
[self.gravityBehavior setGravityDirection:CGVectorMake(motion.gravity.x, motion.gravity.y)];
}];
}
I've tried motion.gravity.x as an angularForce on itemBehavior to verify the forces are returning correctly, and the view rotates the correct direction, which everything seems to be fine. The problem with this approach is that the view continues to rotate since theres constant force being applied. Using setGravityDirection: results with the view anchored with no rotation. Some help would be much appreciated! thanks!
try to change the NSOperationQueue to the mainQueue. This helped me.
[self.motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMDeviceMotion *motion, NSError *error) {
[self.gravityBehavior setGravityDirection:CGVectorMake(motion.gravity.x, -(motion.gravity.y))];
}];
Hope this helped you too.

Collison behaviour boundries not respected

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?

How to implement the background change viewpoint when the user is moving the iOS device?

As you may know that the iOS 7 home screen can do a visual things like, when the user moving the device, the background is moving as well. How can I do the similar thing in my application? Let say I got two images view. One is on top of another. How to implement the similar things? Thank.
you can set UIInterpolatingMotionEffect x and y ordination with help of UIMotionEffectGroup. I just test one code in to my demo and i put this here check this:-
- (void)viewDidLoad
{
[super viewDidLoad];
CGRect frame = self.view.bounds;
for (NSInteger i=0; i<1; i++) {
CGFloat left = (frame.size.width-100)/2+i%2*10;
CGFloat top = (frame.size.height-100)/2+i%3*10;
UIImageView *demoView = [[UIImageView alloc] initWithFrame:CGRectMake(left, top , 100, 100)];
[demoView setImage:[UIImage imageNamed:#"FA4nH.jpg"]];
// demoView.backgroundColor = [UIColor colorWithRed:i/12.0f green:i/18.0f blue:i/24.0f alpha:0.8];
[self.view addSubview:demoView];
UIInterpolatingMotionEffect *xAxis = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:#"center.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];
UIInterpolatingMotionEffect *yAxis = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:#"center.y" type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis];
left += i*50;
top += i *50;
xAxis.minimumRelativeValue = #(-left);
xAxis.maximumRelativeValue = #(left);
yAxis.minimumRelativeValue = #(-top);
yAxis.maximumRelativeValue = #(top);
UIMotionEffectGroup *motionEffectGroup = [[UIMotionEffectGroup alloc] init];
motionEffectGroup.motionEffects = #[xAxis, yAxis];
[demoView addMotionEffect:motionEffectGroup];
}
}
Check this in to real Device that work nice i tested this in to my one of the demo project. hope that helps to you.
in iOS 7 you have UIMotionEffect.
Another user in Stackoverflow ask a similar question.
You can read here: Solution to parallax effect in iOS 7
Also you can take a look to this library in GitHub: NGAParallaxMotion. Basically is a tiny category that help you to achieve a parallax effect with UIMotionEffect.

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.
}

Resources