UIAttachment not working in iOS 7 - ios

I have the following code which simply attaches a password UITextField to an anchorPoint. When I run this nothing happens.
UIDynamicItemBehavior *behavior =
[[UIDynamicItemBehavior alloc] initWithItems:#[passwordTextField]];
CGPoint anchor = passwordTextField.center;
anchor.y -= 200;
_attachment = [[UIAttachmentBehavior alloc] initWithItem:passwordTextField
attachedToAnchor:anchor];
_gravity = [[UIGravityBehavior alloc] initWithItems:#[passwordTextField]];
_gravity.magnitude = 10;
[behavior addChildBehavior:_gravity];
[behavior addChildBehavior:_attachment];
[_animator addBehavior:behavior];

The attachment doesn't change the position of the item. Instead it only makes the distance between the item and the attachment point to be fixed.
If you wish to modify the distance then try UISnapBehavior.

Related

yAxis cut off in Shinobi iOS Chart

https://www.dropbox.com/s/8fqez61k9jhnoa4/Screen%20Shot%202017-06-01%20at%201.04.25%20PM.png?dl=0
(void)createBurnoutChart {
//Create the chart (if needed)
if (burnoutChart == nil) {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
burnoutChart = [[ShinobiChart alloc] initWithFrame:CGRectMake(0, 270, 768,725)]; // iPad
else
burnoutChart = [[ShinobiChart alloc] initWithFrame:CGRectMake(0, 165, 320,290)]; // iPhone
// Set a different theme on the chart
SChartMidnightTheme *midnight = [[SChartMidnightTheme alloc] init];
[burnoutChart setTheme:midnight];
//As the chart is a UIView, set its resizing mask to allow it to automatically resize when screen orientation changes.
burnoutChart.autoresizingMask = ~UIViewAutoresizingNone;
// Initialise the data source we will use for the chart
burnoutDatasource = [[LineChartDataSource alloc] initWithFileName:LineChartSource_Burnout seriesCount:1];
// Give the chart the data source
burnoutChart.datasource = burnoutDatasource;
// Create a date time axis to use as the x axis.
SChartDateTimeAxis *xAxis = [[SChartDateTimeAxis alloc] init];
// Enable panning and zooming on the x-axis.
xAxis.enableGesturePanning = YES;
xAxis.enableGestureZooming = YES;
xAxis.enableMomentumPanning = YES;
xAxis.enableMomentumZooming = YES;
xAxis.axisPositionValue = [NSNumber numberWithInt: 0];
// And allow them to scroll past the default range
xAxis.allowPanningOutOfMaxRange = YES;
xAxis.allowPanningOutOfDefaultRange = YES;
// Make the frequency of tick marks be one day
SChartDateFrequency *freq = [[SChartDateFrequency alloc] initWithDay:1];
xAxis.majorTickFrequency = freq;
burnoutChart.xAxis = xAxis;
//Create a number axis to use as the y axis.
//TODO:Checkback
NSNumber *lowRange = [[NSNumber alloc] initWithInteger:0];
NSNumber *highRange = [[NSNumber alloc] initWithInteger:100];
SChartNumberRange *yRange = [[SChartNumberRange alloc] initWithMinimum:lowRange andMaximum:highRange];
SChartNumberAxis *yAxis = [[SChartNumberAxis alloc] initWithRange:yRange ];
//Enable panning and zooming on Y
yAxis.enableGesturePanning = YES;
yAxis.enableGestureZooming = YES;
yAxis.enableMomentumPanning = YES;
yAxis.enableMomentumZooming = YES;
// yAxis.axisPositionValue = [NSNumber numberWithInt: 0];
// And allow them to scroll past the default range
yAxis.allowPanningOutOfMaxRange = NO;
yAxis.allowPanningOutOfDefaultRange = NO;
burnoutChart.yAxis.defaultRange;
burnoutChart.yAxis = yAxis;
//Set the chart title
burnoutChart.title = #"";
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
burnoutChart.titleLabel.font = [UIFont fontWithName:#"TrebuchetMS" size:27.0f];
} else {
burnoutChart.titleLabel.font = [UIFont fontWithName:#"TrebuchetMS" size:17.0f];
}
burnoutChart.titleLabel.textColor = [UIColor whiteColor];
// If you have a trial version, you need to enter your licence key here:
// chart.licenseKey = #"";
// Add the chart to the view controller
[self.viewBurnoutChart addSubview:burnoutChart];
}
// Make sure we get the latest data
NSInteger lastScore = [burnoutDatasource reReadData];
[self vasBurnoutImage:lastScore];
[self vasBurnoutScore:lastScore];
[burnoutChart reloadData];
[burnoutChart redrawChartAndGL:YES];
//***** Important for resetting visible portion..if I ever get it towork
//[burnoutChart.xAxis resetZoomLevel];
}
The chart displays well but when it comes to the yAxis it stops exactly at the 100 limit range. I want to show more intervals so that it doesn't look like it was cut off.
There are two ways you can achieve this:
If you want to manually set the range for the axis (as you do currently), then simply increase the range e.g. to 103. The tick labels should not be affected.
If you're happy to let the chart determine the range then you can use the rangePaddingHigh property to adjust how much padding is added to the calculated range.
I hope that helps!

How to remove UIView after UIGravityBehavior has moved it off screen?

I tried to set an block on the action property, but that didn't work... any ideas? I know the UIView animation... method has a completion block, but not sure about the UIDynamicAnimations.
EDIT: adding code
[self.animator removeAllBehaviors];
UIGravityBehavior *gravityBehaviour = [[UIGravityBehavior alloc] initWithItems:#[self.onscreen]];
gravityBehaviour.gravityDirection = CGVectorMake(0, 10);
gravityBehaviour.action = ^{
if(self.onscreen.frame.origin.y > [UIScreen mainScreen].bounds.size.height)
[self.onscreen removeFromSuperview];
NSLog(#"locations is %f, height is %f", self.onscreen.frame.origin.y, [UIScreen mainScreen].bounds.size.height);
};
[self.animator addBehavior:gravityBehaviour];
UIDynamicItemBehavior *itemBehaviour = [[UIDynamicItemBehavior alloc] initWithItems:#[self.onscreen]];
[itemBehaviour addAngularVelocity:-M_PI_2 forItem:self.onscreen];
[self.animator addBehavior:itemBehaviour];
The output reflected that the view just continued to be moved even while off screen.
So I solved it by throwing one more thing in the if statement: [animator removeAllBehaviors]; that seemed to do the trick.
let dynamicBehaviour = UIDynamicItemBehavior(items: [randomWord])
weak var weakBehaviour = dynamicBehaviour
weak var weakSelf = self
dynamicBehaviour.action = {
if let currentY = weakBehaviour?.linearVelocityForItem(rndWord).y {
if currentY > CGRectGetMaxY(self.view.frame) / 2 {
weakSelf?.animator?.removeAllBehaviors()
weakSelf?.randomWord?.removeFromSuperview()
}
}
}

Blurry image after using UIDynamicAnimator

I'm using UIDynamicsAnimator with good results except that after the animations are done the image that have been pushed and bounced is blurry. Please help me.
#property (nonatomic,weak) IBOutlet UIImageView *someImage;
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
self.gravity = [[UIGravityBehavior alloc] initWithItems:#[self.someImage]];
CGVector gravityDirection = {-1.0, 0.5};
[self.gravity setGravityDirection:gravityDirection];
self.collision = [[UICollisionBehavior alloc] initWithItems:#[self.someImage]];
self.collision.translatesReferenceBoundsIntoBoundary = YES;
self.itemBehaviour = [[UIDynamicItemBehavior alloc] initWithItems:#[self.someImage]];
self.itemBehaviour.elasticity = 0.5;
[self.animator removeAllBehaviors]; // to avoid problems from the last behaviour animation
[self.collision addBoundaryWithIdentifier:#"barrier"
fromPoint:CGPointMake(444,0)
toPoint:CGPointMake(444,768)];
self.pushBehavior = [[UIPushBehavior alloc] initWithItems:#[self.someImage] mode:UIPushBehaviorModeInstantaneous];
self.pushBehavior.magnitude = 1.0f;
self.pushBehavior.angle = 0.0f;
[self.animator addBehavior:self.pushBehavior];
self.pushBehavior.pushDirection = CGVectorMake(1.0f, 0.0f)
self.pushBehavior.active = YES;
[self.animator addBehavior:self.itemBehaviour];
[self.animator addBehavior:self.collision];
[self.animator addBehavior:self.gravity];
I think your problem is that the image isn't on an exact point when the animation is done. I would sugest that you add a delegate and when the animation pauses you round the x and y for the image to the closest integer.

UISnapBehavior Causing Distortion

For whatever reason, whenever I use the snapping behavior, it causes the UIButtons to turn into rectangles of various sizes when "snapped". I'm probably just looking right over the issue. My deadline is tomorrow to get the last bugs worked out, so I would GREATLY appreciate ANY help! Thank you!
vvv - ViewController.m - vvv
//set points
CGPoint bullyboxPoint = {80, 188};
CGPoint weemPoint = {240, 188};
CGPoint yeaPoint = {80, 339};
CGPoint charityPoint = {240, 339};
CGPoint phhsPoint = {80, 488};
CGPoint experiencePoint = {240, 488};
//make the buttons closer to speed up the snap
bullybox.frame = CGRectMake(40, 788, 120, 120);
weem.frame = CGRectMake(200, 788, 120, 120);
yea.frame = CGRectMake(30, 939, 120, 120);
charity.frame = CGRectMake(190, 939, 120, 120);
phhs.frame = CGRectMake(20, 1328, 120, 120);
experience.frame = CGRectMake(180, 1328, 120, 120);
//create behaviors
UISnapBehavior *snapBehavior = [[UISnapBehavior alloc] initWithItem:self->bullybox snapToPoint:bullyboxPoint];
UISnapBehavior *snapBehavior1 = [[UISnapBehavior alloc] initWithItem:self->weem snapToPoint:weemPoint];
UISnapBehavior *snapBehavior2 = [[UISnapBehavior alloc] initWithItem:self->yea snapToPoint:yeaPoint];
UISnapBehavior *snapBehavior3 = [[UISnapBehavior alloc] initWithItem:self->charity snapToPoint:charityPoint];
UISnapBehavior *snapBehavior4 = [[UISnapBehavior alloc] initWithItem:self->phhs snapToPoint:phhsPoint];
UISnapBehavior *snapBehavior5 = [[UISnapBehavior alloc] initWithItem:self->experience snapToPoint:experiencePoint];
//dampen the snap
snapBehavior.damping = 1.2f;
snapBehavior1.damping = 1.2f;
snapBehavior2.damping = 1.2f;
snapBehavior3.damping = 1.2f;
snapBehavior4.damping = 1.2f;
snapBehavior5.damping = 1.2f;
//add behaviors
[self.animator addBehavior:snapBehavior];
[self.animator addBehavior:snapBehavior1];
[self.animator addBehavior:snapBehavior2];
[self.animator addBehavior:snapBehavior3];
[self.animator addBehavior:snapBehavior4];
[self.animator addBehavior:snapBehavior5];
The problem is probably that you're using Autolayout. Autolayout and UIKit Dynamics are enemies (if you look at Apple's example code, you'll see that they have circumvented this issue by turning Autolayout off).
The way I like to solve this problem is: Make snapshot images of the objects to be animated; hide the actual objects and put the snapshot images in their place; animate the snapshot images; when it's all over, take the snapshot images out of the interface and show the actual objects in their new location.
This works because the snapshot images are not subject to Autolayout. However, you will still need to grapple with the issue, because you cannot move buttons that are subject to Autolayout by setting their frame; you must set their constraints.

UIDynamicKit with attachment and push behaviour causes long oscillation time

I am just starting to use the UIDynamic kit and have followed examples online. I have achieved the behaviour I want, which is for a view to recieved an instantaneous force in a direction and spring back to the original spot.
I achieved this using the code below
CGPoint origCenter = self.viewContentContainer.center;
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
UIPushBehavior *push = [[UIPushBehavior alloc]
initWithItems:#[self.viewContentContainer] mode:UIPushBehaviorModeInstantaneous];
CGVector vector = CGVectorMake(200.0, 0.0);
push.pushDirection = vector;
CGPoint anchorpoint = origCenter;
UIAttachmentBehavior *attachment = [[UIAttachmentBehavior alloc] initWithItem:self.viewContentContainer attachedToAnchor:anchorpoint];
[attachment setFrequency:2.0];
[attachment setDamping:0.5];
[self.animator addBehavior:push];
[self.animator addBehavior:attachment];
However, it oscillates for a very long time at the end over 1 or 2 pixels. Changing the frequency and damping values doesn't seem to make this any better or worse.
Has anyone else experienced this?
Many Thanks.
Add this and it should fix it:
attachment.length = 1.0f;
It is an expected behavior, although it seems "unsightly". The above just offsets that "unsightliness".
Tested. Hope it helps.
i have the same problem. didn't solve it yet, but i have some ideas
i remove attachment behavior when UIGestureRecognizer ended,
but when i drag it still oscillates :(
-(void) handlePanGestureRecognizer:(UIPanGestureRecognizer*) gr
{
CGPoint att = [gr locationInView:self.view];
self.attachView.center = att;
if (gr.state == UIGestureRecognizerStateBegan)
{
_attachment.anchorPoint = att;
[_animator addBehavior:_attachment];
if (_snap)
[_animator removeBehavior:_snap];
}
if (gr.state == UIGestureRecognizerStateChanged)
{
_attachment.anchorPoint = att;
}
if (gr.state == UIGestureRecognizerStateEnded)
{
_snap = [[UISnapBehavior alloc] initWithItem:self.button snapToPoint:att];
[_animator addBehavior:_snap];
[_animator removeBehavior:_attachment];
}
}
and this is not pretty solution but it works as i like
-(void) handlePanGestureRecognizer:(UIPanGestureRecognizer*) gr
{
CGPoint att = [gr locationInView:self.view];
self.attachView.center = att;
if (_snap)
[_animator removeBehavior:_snap];
_snap = [[UISnapBehavior alloc] initWithItem:self.button snapToPoint:att];
[_animator addBehavior:_snap];
}
The way I got around these oscillations was by removing the behavior entirely, using animator.removeBehavior() and then re-adding the same behavior back to the animator.
Add this behaviour:
dynamic = UIDynamicItemBehavior()
dynamic.resistance = 1
self.animator.addBehavior(dynamic)

Resources