I have a 3x3 grid of UIViews with UIGestureRecognizers added to them, arranged like so:
The way it works is that tapping on a square enlarges it 2x using CGAffineTransformScale and overlays that over the other squares. The problem is that the touch area stays the same size as the 1.0 scale for some reason.
I add the squares using
CGRect squareFrame = CGRectMake(1 + squareSpacing + ((squareDimension + squareSpacing) * i), topMargin, squareDimension, squareDimension);
SquareView *square = [[SquareView alloc] initWithFrame:squareFrame];
[square setPosition:i];
square.layer.zPosition = 0;
[self.view addSubview:square];
[squaresArray addObject:square];
The Squares have gesture recognizers added in their init:
fingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapped:)];
[self addGestureRecognizer:fingerTap];
The tapped function does the following:
[UIView animateWithDuration:1.0
delay:0.0
usingSpringWithDamping:0.8
initialSpringVelocity:10.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
CGAffineTransform transform = self.transform;
self.transform = CGAffineTransformScale(transform, 2.0, 2.0);
}
completion:nil];
I outlined the touch area in red. I have tried playing with the zPosition but I don't know what to do to make it work, I am stuck. I want to be able to tap the enlarged square anywhere for it to close, but I am limited to the red area.
Thanks in advance.
EDIT: Sorry that the pictures are so large. Code added.
Steven
You might trying bringing the expanded UIView to the front of your parent view so that your tap events aren't captured by any overlapped views:
[parentView bringSubviewToFront:tappedView];
Related
I have scrollview and inside scrollview I have 2 views as MainView and another as SideMenuView.
What I want to make animation like below.
Any idea what needs to be done to get this working?
Psuedo Code below:
- (void)animateSideMenu{
homeView.frame = CGRectMake(sideMenuWidth, 0.0, (self.view.frame.size.width - sideMenuWidth), self.view.frame.size.height);
[UIView animateWithDuration:1.0 delay:0.0
options:UIViewAnimationOptionCurveLinear
animations:^{
sideMenu.frame = CGRectMake(0.0, 0.0, sideMenuWidth, sideMenuHeight);
[self flipAnimation];
} completion:^(BOOL finished) {
}];
}
- (void)flipAnimation{
CABasicAnimation *yRotate = [CABasicAnimation animationWithKeyPath:#"transform.rotation.y"];
yRotate.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_2, 0, 1, 0)];
yRotate.toValue = #(M_PI * 1.5);
yRotate.duration = 0.5;
yRotate.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
[sideMenu.layer addAnimation:yRotate forKey:#"yRotate"];
}
Below are the steps to develop this type of animation:
set the frame of homeView(Red colour view) of screen size & add pan gesture to this view.
set frame of sideMenu view in negative x-axis.
Create a responder function for pan gesture recogniser, in this function call the above mentioned animateSideMenu function.
Adjust the animation parameters accordingly.
Try with this & let me know if anything comes up.
I would not use a scrollview but rather a UIPanGestureRecognizer in which I would detect your current "pan offset" and calculate a current fraction of the animation and positions of those two views (let's simplify it so that the menu is view1 and the rest view2).
Then I would simply set an appropriate transform in the .Changed state.
In .Ended state I would see whether the menu is closer to being open or close and create an animation with .toValue set accordingly. You should use CAAnimations or better - Facebook pop animations because you can pause and remove them and the views stay put and not jump to their initial positions (as is often the case with UIViewAnimate).
If you need help with writing exact code you can write here and I'll edit my answer.
There's tutorial for exactly that menu, though it's in Swift:
https://www.raywenderlich.com/87268/3d-effect-taasky-swift
I have a page in my app in which there is user's profile pic in a circle as its there in Twitter profile page.
I have to add a functionality such that when I tap on it, the image should expand. Animation needs to be added in such a way that a new bigger circle should slowly appear from the centre of the smaller circle and reach the centre of the screen.
Any ideas as to how this can be implemented?
Try UIView Animation block with changing bigger circle's position, size, alpha, and corner radius (if required).
Place your bigger circle (with smaller size initially) on top of smaller circle and hide it initially. Then before animation, un-hide it and animate using a block like this:
[UIView animateWithDuration:1.0 animations:^{
// set bigger circle destination position i.e. centre of screen
// set bigger circle final size
// set other properties like alpha, corner radius etc
} completion:nil];
Use CATransform3DScale transform and UIView Animation
CATransform3D avatarTransform = CATransform3DIdentity;
avatarTransform = CATransform3DScale(avatarTransform, avatarScaleFactor,avatarScaleFactor, 0);
[UIView animateWithDuration:1.0 animations:^{
//Change the frame to reach the center of screen
self.avatar.layer.transform = headerTransform
} completion:nil]
You can simply use CGAffineTransformScale and scale your ImageView inside UIView's animateWithDuration block.
imgV.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.0, 0.0);
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaseInOut
animations:^{
imgV.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1.0, 1.0);
}
completion:^(BOOL finished) {
NSLog(#"done");
}];
For further references you can look into these Stackoverflow questions :
Animate a UIImageView
iOS View Transform Animation
i have simple UIView animation block which animates the origin of 2 views. I have a Button on a special position placed on a mapview view. so when i'd like to animate the center of the map and move the pin with the map, the map moves faster than the button. Is there a way, to speed up the animation of the button or to slow down the animation of the map? At the moment it looks like the map moves and the button jumps to his end position.
CGPoint newCenter = mapView.center;
newCenter.x -= 1;
newCenter.y -= (button.frame.size.height/2)
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationCurveEaseIn animations:^{
CGPoint screenPoint = fakePin.frame.origin;
screenPoint.x -= 5;
screenPoint.y += button.frame.size.height-4;
mapView.mapCoord = [mapView.map convertPoint:screenPoint toCoordinateFromView:self.view];
self.mapView.map.centerCoordinate = mapView.mapCoord;
[button setCenter:newCenter];
}];
Any Ideas?
Why not show the button as an annotation? Then it would move along the map.
Still, try to animate the property frame on the button instead of center. You'll need to do the calculations on your own but I think that may be the problem.
i just figured out, that the Problem was that my setCenter: was called without animating, somehow it worked with the Google Maps in ios5 (animating itself but not in ios6=
No it works!!
I am performing a task in such a way that I took one image and twenty to thirty rectangular cell button.
For those rectangular cells I named them as 1,2,3,4,5,--------,30. I arranged the rectangular cells in an 6*7 matrix. Now if I click the rectangular cell button 29, the image has to find the shortest path in that matrix to reach that clicked button.
How do I perform this?
You have a single image that you want to animate to the location of one of 30 buttons? Further, you want it to move not in a diagonal, but first horizontally, then vertically? CodaFi's code is quite close to what I would do. I'd write an IBAction method that I would attach to all the buttons. Startig with CodaFi's code as a basis, here's the action method I'd suggest:
-(IBAction)animateImageToButton: (id) sender
{
button = (UIButton *) sender;
//First animate the image to the x position of the button
CGPoint fPoint = CGPointMake(button.center.x, image.center.y);
CGPoint sPoint = button.center;
//animate x position first.
[UIView animateWithDuration: 1.0f animations: ^
{
[image setCenter:fPoint];
}
completion ^(BOOL finished)
{
//Once that animation is complete, create
//a second animation to move to the button's y position
[UIView animateWithDuration: 1.0f animations: ^
{
[image setCenter:sPoint];
}];
}];
}
That code would move a single UIImageView, called Image, onto the button that was tapped.
I would not name the buttons but give them tags. I would use the following scheme:
button.tag = xCoordinate *100 + yCoordinate;
So, for example, for the third button from the left in the top row the tag would be 301. Retrieve the coordinates like this:
xCoordinate = button.tag / 100;
yCoordinate = button.tag % 100;
Now all you have to do is animate the image to the center of the button or some other point near there by changing the x and y coordinates of the image's frame.
I disagree with the tag approach that mundi's layed out, because the images would move in diagonal lines to reach their destination. I imagine a for-loop would be appropriate, so here's my approach:
-(void)animateOnLinesWithClickedButton:(UIButton*)button {
for (UIButton *image in self.view.subviews){
CGPoint fPoint = CGPointMake(button.center.x, image.center.y);
CGPoint sPoint = button.center;
//animate x position first.
[UIView animateWithDuration:1.0f animations:^{
[image setCenter:fPoint];
}
completion^(BOOL finished){
[UIView animateWithDuration:1.0f animations:^{
[image setCenter:sPoint];
}];
}];
}
}
This will animate your buttons one by one to the correct x, then y position. Use the delay variation of this method to create a more realistic effect.
I have a UIImageView that I rotate around its center:
imageHorizon.layer.anchorPoint = CGPointMake(0.5, 0.5);
imageHorizon.transform = CGAffineTransformRotate(imageHorizon.transform, angleToRotate*(CGFloat)(M_PI/180));
Sometimes I also move this image to the left or right and then rotate again. I would like to keep the rotation center all the time on the same point (which is actually the center of the super view). How can I do that ?
cheers,
self.imgView.layer.anchorPoint = CGPointMake(0.0,1.0);
self.imgView.layer.position = CGPointMake(100,200.0);
CGAffineTransform cgaRotateHr = CGAffineTransformMakeRotation(-(3.141/4));
[self.imgView setTransform:cgaRotateHr];
This is an older question, but the other solutions did not work well for me, so I came up with another solution:
Rotating an image is essentially just a normal rotation with a translation applied, ensuring that the point you want to rotate around is still in the same spot after the rotation. To do this, calculate the position's CGPoint in your image before the rotation, get the position after the rotation, and apply the difference as a translation on the image, "snapping" it into the right position. Here is the code that I've been using:
Keep in mind that the translation should be applied via CGAffineTransform, not moving the .center, because the translation will need to be relative to the rotation, and CGAffineTransformTranslate() takes care of that.
// Note: self is the superview of _imageView
// Get the rotation point
CGPoint rotationPointInSelf = self.center; // or whatever point you want to rotate around
CGPoint rotationPointInImage = [_imageView convertPoint:rotationPointInSelf fromView:self];
// Rotate the image
_imageView.transform = CGAffineTransformRotate(_imageView.transform, angle);
// Get the new location of the rotation point
CGPoint newRotationPointInImage = [_imageView convertPoint:rotationPointInSelf fromView:self];
// Calculate the difference between the point's old position and its new one
CGPoint translation = CGPointMake(rotationPointInImage.x - newRotationPointInImage.x, rotationPointInImage.y - newRotationPointInImage.y);
// Move the image so the point is back in it's old location
_imageView.transform = CGAffineTransformTranslate(_imageView.transform, -translation.x, -translation.y);
You can make the image a subview of another view and then rotate the superview to get that effect. Another approach is to set the anchorPoint property as described in the docs.
I'm using this code to rotate around the point (0,0).
Maybe it help you figure out how to active what you want.
float width = self.view.frame.size.width;
float height = self.view.frame.size.height;
CGRect frame_smallView = CGRectMake(-width, -height, width, height);
UIView *smallView = [[UIView alloc] initWithFrame:frame_smallView];
smallView.backgroundColor = darkGrayColor;
// Select x and y between 0.0-1.0.
// The default is (0.5f,0.5f) that is the center of the layer
// (1.0f,1.0f) is the right bottom corner
smallView.layer.anchorPoint = CGPointMake(1.0f, 1.0f);
// Rotate around this point
smallView.layer.position = CGPointMake(0, 0);
[self.view insertSubview:smallView belowSubview:self.navBar];
[UIView animateWithDuration:1
animations:^{
smallView.transform = CGAffineTransformMakeRotation(M_PI);
}
completion:^(BOOL finished){
[self.navigationController popViewControllerAnimated:NO];
}];