I have a center point for an UIImageView which is being updated.
At present the issue is that I see the image view move. What I am looking for is to move the imageview when the view is hidden and then show it again once the center point is updated.
I created a method that does the center point update:
-(void)updateCenterPoint {
float newhintX = (self.originalImageCenterPoint.x * self.scaleDownOriginalImageRatio) + self.insideImageFrame.frame.origin.x;
float newhintY = (self.originalImageCenterPoint.y * self.scaleDownOriginalImageRatio) + self.insideImageFrame.frame.origin.y;
if (self.hintView.hidden == NO) {
self.hintView.hidden = YES;
self.hintView.center = CGPointMake(newhintX, newhintY);
} else {
self.hintView.center = CGPointMake(newhintX, newhintY);
}
if (self.hintView.hidden) {
self.hintView.hidden = NO;
}
}
Calling this in viewDidLoad does not appear to work how I expect it to. Ideally when the view loads I do not want to the see the hintView (image view) until it is in the correct point?
Why not just do something like this:
Hide the image
Move the image
Unhide the image
Instead of asking if it is hidden etc. explicitly hide it, move it, then unhide it.
Jeff
The issue was that I was updating the center point from a method:
-(void)viewDidLayoutSubviews
This is called at some point which is too early. So the center point is still 0,0 even though it is being updated.
This meant that the view was becoming unhidden/shown before the center point had changed, therefore when the method was called again the update occurred to the centerpoint.
The resolution was to check that the point was not 0,0 if it was keep it hidden. It is never going to be 0,0 in my example - luckily.
Related
I'm trying to get a UIButton to scale but remain at its original center point, and I'm getting perplexing results with CGAffineTransformScale.
Here's the function in my UIButton subclass:
-(void)shrink {
self.transform = CGAffineTransformMakeScale(0.9,0.9);
}
With this code, the button scales to the top-left corner, but when I add code to try to set the anchor point (either of the following lines), the button gets relocated off screen somewhere:
[self.layer setAnchorPoint:CGPointMake(self.frame.size.width/2, self.frame.size.height/2)];
//same result if I use bounds instead of frame
[self.layer setAnchorPoint:self.center];
Interestingly, this line causes the view to move down and to the right some distance:
[self.layer setAnchorPoint:CGPointMake(0, 0)];
Sorry, I know there are many posts on this topic already but I honestly read and tried at least a dozen and still couldn't get this to work. I'm probably just missing something incredibly simple.
The default anchor point is 0.5, 0.5. That is why setting it to 0, 0 moves the view down and to the right. Also, if you don't want the center to move, you need to re-adjust the center after scaling it.
Just readjust its position after shrinking it.
-(void)shrink {
CGPoint centerPoint = self.center;
self.transform = CGAffineTransformMakeScale(0.9,0.9);
self.center = centerPoint;
}
I'm using UIKit Dynamics to push a UIView off screen, similar to how Tweetbot performs it in their image overlay.
I use a UIPanGestureRecognizer, and when they end the gesture, if they exceed the velocity threshold it goes offscreen.
[self.animator removeBehavior:self.panAttachmentBehavior];
CGPoint velocity = [panGestureRecognizer velocityInView:self.view];
if (fabs(velocity.y) > 100) {
self.pushBehavior = [[UIPushBehavior alloc] initWithItems:#[self.scrollView] mode:UIPushBehaviorModeInstantaneous];
[self.pushBehavior setTargetOffsetFromCenter:centerOffset forItem:self.scrollView];
self.pushBehavior.active = YES;
self.pushBehavior.action = ^{
CGPoint lowestPoint = CGPointMake(CGRectGetMinX(self.imageView.bounds), CGRectGetMaxY(self.imageView.bounds));
CGPoint convertedPoint = [self.imageView convertPoint:lowestPoint toView:self.view];
if (!CGRectIntersectsRect(self.view.bounds, self.imageView.frame)) {
NSLog(#"outside");
}
};
CGFloat area = CGRectGetWidth(self.scrollView.bounds) * CGRectGetHeight(self.scrollView.bounds);
CGFloat UIKitNewtonScaling = 5000000.0;
CGFloat scaling = area / UIKitNewtonScaling;
CGVector pushDirection = CGVectorMake(velocity.x * scaling, velocity.y * scaling);
self.pushBehavior.pushDirection = pushDirection;
[self.animator addBehavior:self.pushBehavior];
}
I'm having an immense amount of trouble detecting when my view actually completely disappears from the screen.
My view is setup rather simply. It's a UIScrollView with a UIImageView within it. Both are just within a UIViewController. I move the UIScrollView with the pan gesture, but want to detect when the image view is off screen.
In the action block I can monitor the view as it moves, and I've tried two methods:
1. Each time the action block is called, find the lowest point in y for the image view. Convert that to the view controller's reference point, and I was just trying to see when the y value of the converted point was less than 0 (negative) for when I "threw" the view upward. (This means the lowest point in the view has crossed into negative y values for the view controller's reference point, which is above the visible area of the view controller.)
This worked okay, except the x value I gave to lowestPoint really messes everything up. If I choose the minimum X, that is the furthest to the left, it will only tell me when the bottom left corner of the UIView has gone off screen. Often times as the view can be rotating depending on where the user pushes from, the bottom right may go off screen after the left, making it detect it too early. If I choose the middle X, it will only tell me when the middle bottom has gone off, etc. I can't seem to figure out how to tell it "just get me the absolute lowest y value.
2. I tried CGRectIntersectsRect as shown in the code above, and it never says it's outside, even seconds after it went shooting outside of any visible area.
What am I doing wrong? How should I be detecting it no longer being visible?
If you take a look on UIDynamicItem protocol properties, you can see they are center, bounds and transform. So UIDynamicAnimator actually modifies only these three properties. I'm not really sure what happens with the frame during the Dynamics animations, but from my experience I can tell it's value inside the action block is not always reliable. Maybe it's because the frame is actually being calculated by CALayer based on center, transform and bounds, as described in this excellent blog post.
But you for sure can make use of center and bounds in the action block. The following code worked for me in a case similar to yours:
CGPoint parentCenter = CGPointMake(CGRectGetMidX(self.view.bounds), CGRectGetMidY(self.view.bounds));
self.pushBehavior.action = ^{
CGFloat dx = self.imageView.center.x - parentCenter.x;
CGFloat dy = self.imageView.center.y - parentCenter.y;
CGFloat distance = sqrtf(dx * dx + dy * dy);
if(distance > MIN(parentCenter.y + CGRectGetHeight(self.imageView.bounds), parentCenter.x + CGRectGetWidth(self.imageView.bounds))) {
NSLog(#"Off screen!");
}
};
I have a uiimage that has a pan gesture enabling the user to move the image along the y axis. How can I make it impossible for the image position from becoming <100 for example.
Basically, I have a draggable image that I don't want to be dragged beyond a certain point on the y axis.
I had a long search for something like this but found nothing that I thought was relevent enough to me.
I am very new to programming and would appreciate any help.
Thanks in advance.
If you can drag the image, you have surely a gesture recognizer that calls a callback method during dragging repeatedly. And you probably use the current coordinate provided by the gesture recognizer to update the center property of the image that you drag.
So you could check the current coordinate in the callback method, and if it crossed a certain border, you simply do no longer update the center property of the image.
Or did I understand something wrong?
Maybe you could provide some code. This would make an answer easier.
In the pan handling method you can use something like this:
- (void)panHandle:(UIPanGestureRecognizer*)gesture
{
CGPoint point = [gesture locationInView:self.view];//get the coordinate
//check for current position of image and update only
//if it is below 100 or a desired value
if(point.y <= 100)
{
//update the coordinate of image
}
else
{
point.y = 100;
//update the coordinate. This will make your view move on x axis keeping y limits
}
}
I have an imageview that are being rotated PI/4 (radians) every time it's taped.
That works fine with this code:
- (void)handleTap:(UITapGestureRecognizer *)tapRecognize
{
if (tapRecognize == tapRecognizer)
{
CGAffineTransform transform = CGAffineTransformRotate(imageview.transform, (M_PI / 4));
[imageview setTransform:transform];
}
The tapRecognizer is asigned to the imageview.
Now, I want to check if the imageview has been rotated. This is my code:
if (CGAffineTransformEqualToTransform(imageview.transform, rot45)) //rot45 is a CGAffineTransformMakeRotation variable which is set to M_PI / 4
{
NSLog("Rotated");
}
That works fine for the first tap, when it has been rotated 45°. But I want to be able to check when it has been taped two times, which means that it has been rotated 90°. And so on. I want different actions on each rotation-angle. How can I check that?
Sorry if the question is unclear
Devise a scheme to map the tag property to rotation. On every rotation update the tag value.
Basically I would just like to touch the image and have it move with my finger across the screen without using theImage.center = touchPosition
I don't want to have the center snap to my finger. I want to move the image from whatever point I touch.
The standard way to handle this, which #richard-j-ross-iii hinted at in a comment, is to save the difference between the view's center and the touch position when the drag starts and then maintain that difference as the drag proceeds. In your touchesBegan:withEvent: method save the offset like:
_dragOffsetFromCenter = CGSizeMake(touchLocationInImageView.x - centerOfImageView.x, touchLocationInImageView.y - centerOfImageView.y);
then in touchesMoved:withEvent: you can maintain that same offset like:
myImageView.center = CGPointMake(touchLocation.x - _dragOffsetFromCenter.x, touchLocation.y - _dragOffsetFromCenter.y);