I have a view and its subview is UIScrollView and having an UIImageView which is a subview of UIScrollView. When I try to scale UIView,UIScrollView and UIImageView is also getting scaled. But the problem is I'm getting touches on half portion of view.
Here is my code
[UIView animateWithDuration:0.5 delay:0.0 options:0 animations:^{
CGFloat DesiredWidth = 250.0;
CGFloat DesiredHeight = 300.0;
CGAffineTransform scalingTransform1;
scalingTransform1 = CGAffineTransformMakeScale(DesiredWidth/self.view1.bounds.size.width,
DesiredHeight/self.view1.bounds.size.height);
self.view1.transform = scalingTransform1;
self.view1.center=CGPointMake(268, 250); }completion:^(BOOL finished)
{ }];
Please anyone can tell me how can I get touch.I searched a lot but could not find
Thanks
I think your problem is the size of the very root UIView(i.e. the superview of the UIView you talk about) of your views. When a certain subview is larger than its superview it will not receive touch events in this portions of it's frame that go outside of the superview frame.
If you have read about the responder chain in iOS you should know that UIView calls -[hitTest: withEvent:] on it's subviews in the order they have been laid out. This method checks if a certain touch points inside the UIView frame then starts to check if a certain subview can handle the touch event in the order they are positioned in the responder chain(the view hierarchy in this case).
So when the touch event is first received a certain UIView first hit tests itself and when the location of the touch is outside it's frame it does not check it's subviews. So check very carefully all your views' frames and if some root view (it could be the view property of the UIViewController you use) is actually smaller than the subview you touch.
Also mind the transforms. In the documentation is stated that when some transforms are applied the frames of the views become irrelevant.
To summarize my reply let's have this situation:
some_superview.frame = CGRectMake(0, 0, 200, 200);
some_subview_of_the_superview.frame = CGRectMake(0, 0, 200, 300);
in the region of the subview that is actually (0, 200, 200, 100) which is the bottom 100 points the touches will be ignored by the superview because they are outside it's frame
Make sure.. your subview's frame is within its superview. If it went wrong way.. it will not detect any touch.
Related
I am using a UIView animation to resize and translate a view containing multiple subviews. The animation for the parent view happens perfectly; however, the subviews exhibit strange behaviour. When the animation begins, the subviews are immediately resized and then moved to their final position.
For example, if the duration and delay of the animation was five-seconds, as soon as the animation was called, the subviews would move to the desired end-of-animation values. After five-seconds, the superview would be resized and translated to the desired.
My code for the animation is:
[UIView animateWithDuration:0.5 animations:^{
if (UIDeviceOrientationIsLandscape(self.interfaceOrientation)) {
self.leftPaneView.frame = leftPaneLandscapeFrame;
self.rightPaneContainerView.frame = rightPaneLandscapeFrame;
}
if (UIDeviceOrientationIsPortrait(self.interfaceOrientation)) {
CGFloat offset = 300;
self.leftPaneView.frame = CGRectOffset(leftPanePortraitFrame, -offset, 0);
self.rightPaneContainerView.frame = rightPanePortraitFrame;
}
}];
Any ideas?
Note: rightPaneContainerView contains the view of a UIViewController that is a child of the view controller that calls this animation.
I managed to solve the problem. The content mode for some of the views was set to Left. When the animation started, the views would jump the left, and then be animated to the desired end-of-animation value.
An amateur mistake. Thanks everyone who took a look.
I have a custom UIScrollView in my app. When the user touches the scroll view I want it to enlarge to fill the entire screen.
I have tried using this code, however nothing happens :
-(void) touchesBegan: (NSSet *) touches withEvent:(UIEvent *) event {
NSLog(#"Touch Detected");
self.frame = CGRectMake(0, 0, 768, 1024);
}
Is there a way to dynamically change the size of the view ? Also is it possible to somehow animate the change in size ?
Thank you in advance.
Your code looks correct. Perhaps your view is clipped within a parent view making it seem as though it didn't resize, in which case you should be mindful of the clipsToBounds property of the parent view. Some other considerations (without knowing what makes you think its not working) is the contentMode property of your UIScrollView. Depending on that value, your UIScrollView may not be redrawing itself. See UIView for details (read frame property)
Animate example:
[UIView animateWithDuration:<some float value in seconds> animations:^{
self.frame = CGRectMake(0, 0, 768, 1024);
}];
Details on animate: UIView (read animateWithDuration:animations: class method).
I'm making an app what contains a scroll view with some subviews what are built up on UIGestures...
The idea is to be able to use it in both orientations, in portrait.. it would be full screen but in landscape the user would have to scroll to access all the content however I have had some issues trying to get it to work correctly.
Here is how I have my view laid out:
UIView -> UIScrollView -> UIView -> UIImageView -> Subviews with Gesture recognisers.
the first UIView is just the UIViewControllers View, the UIScrollView is what will/should handle the difference in orientation, the second UIView is just a container to stop positioning screwing up and the UIImageView holds my image what is a diagram where I have placed a series of custom checkboxes and labels into/over the UIImageView to display content and receive and handle interaction...
In Portrait, this will work flawlessly however when I rotate to landscape, the content inside the UIScrollView is shifted up by 128pixels so the top is inaccessible... this also makes the bottom 128pixels too big so there is a transparent gap..
I can fix this by running this code on the didRotateFromInterfaceOrientation: function:
int offset = 0;
if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]))
offset = 128;
else
offset = 0;
[scrollView setContentInset:UIEdgeInsetsMake(offset, 0, -offset, 0)];
The code above just alters the ContentInset's top and bottom property to adjust the postion by 128 pixels each way... the scroll view will then display the content fine...
However, when I attempt to touch any of the gestures within 128pixels from the bottom, they will not work!
I've tried so much to get it working but also if i don't alter the contentInset they will still not work (within 128 from the bottom)... It's really confusing me as I have userInteractionEnabled set to YES on all of my views but it still wont work, anything else will and content is displayed fine within this 128pixels area...
Does anybody know what is wrong with this or have anything I can try as I feel that I have tried everything possible.
Thanks for reading,
Liam
I figured it out in the end... It was an issue with the frame size changing... all I had to do was run this code on the didRotate function:
int offset = 0;
if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) {
[scrollView setFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
offset = 128;
} else {
[scrollView setFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
offset = 0;
}
[scrollView setContentInset:UIEdgeInsetsMake(offset, 0, -offset, 0)];
It just makes sure that the frame is reset back to the size of the view once rotated... I figure it was an issue with autoresize masks but I didn't have the time to play around with them and this works just as well.
Alright this is a newbie question, so I apologize in advance. I have a UIView which I laid out in Interface Builder off-screen. When the user presses a button, I would like to animate this view on-screen. It works, but I can't interact with any buttons in the UIView. I have read that only the view is moved when you animate and that the actual objects retain their positions, so I have tried setting the position of the UIViews' layers, but it causes my UIView menu to display an extra 81 pixels to the left. When this happens, I can interact with the buttons, but I need it to be flush with the right of the screen. Here is my code in the IBAction on the openMenu button:
CABasicAnimation *moveView = [CABasicAnimation animationWithKeyPath:#"position"];
moveView.delegate = self;
moveView.duration=0.5;
// If the menu is displayed, close it!
CGPoint currentPosView = [[entirePage layer] position];
CGPoint destView;
[moveView setFromValue:[NSValue valueWithCGPoint:currentPosView]];
if (menuDisplayed) {
// Move right to our destination
destView.x = currentPosView.x;
destView.y = currentPosView.y + 81;
[moveView setToValue:[NSValue valueWithCGPoint:destView]];
// Otherwise, open it
} else {
// Move left to our destination
destView.x = currentPosView.x;
destView.y = currentPosView.y - 81;
[moveView setToValue:[NSValue valueWithCGPoint:destView]];
}
// Animate the view
[[entirePage layer] addAnimation:moveView forKey:#"move"];
// Set the final position of our layer
[[entirePage layer] setPosition:destView];
menuDisplayed = !menuDisplayed;
And then in the animationDidStop method:
CGPoint currentPosMenu = [[menuBar layer] position];
if (menuDisplayed) {
currentPosMenu.x -= 81;
} else {
currentPosMenu.x += 81;
}
[[menuBar layer] setPosition:currentPosMenu];
Help???
You shouldn't need to mess with the layers. You could probably achieve the effect you want by laying out the views in Interface Builder at the positions they will be in after they are animated into view. In other words, first lay things out in their final/correct positions. Don't do anything funky in IB.
In your code, after the app is launched or in a -viewDidAppear: method if you're using a UIViewController, you could offset the views by some amount and then restore them to their original position in an animation block:
myView.transform = CGAffineTransformMakeTranslation(0,81);
[UIView beginAnimations:#"slideUp" context:nil];
myView.transform = CGAffineTransformIdentity;
[UIView commitAnimations];
As for the lack of user interaction on your views, that could be a number of things. If all of your views are subviews of something like a UIImageView, UIImageView has userInteractionEnabled set to NO by default (at least if you build one in code - I'm not sure off hand what IB's default settings are for an image view). It could also mean that the superview of your views is actually too small and its frame does not contain the subviews. (If clipping was turned on for the superview, you wouldn't even be able to see subviews that are having this particular problem.)
EDIT:
I read things more carefully and see you want things to move in response to a button press, so in other words the views will need to be hidden from the start. In that case you could still lay everything out in IB in their final position, but just set them as hidden in IB. When you push the button, set the views visible (hidden=NO) before translating them. That should allow them to be laid out in their final/correct place in IB making sure that they are positioned on the proper superviews, etc while still getting the animation effect you want.
Forget about the animations for now; you should move your view by setting its frame property.
E.g.:
CGRect menuFrame = entirePage.frame;
if (menuDisplayed)
{
menuFrame.origin.x += 81;
}
else
{
menuFrame.origin.x -= 81;
}
entirePage.frame = menuFrame;
// Do your animation here, after the view has been moved
Don't worry about the animation until you've verified that your view is being placed in the correct location. Once you've verified that that code is working correctly, then do your animation after you set the frame property.
Note that you probably don't need to use the CoreAnimation API at all, unless you're doing something complex. UIKit can do animation on its own. E.g:
[UIView beginAnimations:#"MyAnimation" context:NULL];
myFirstView.frame = ...;
myOtherView.frame = ...;
[UIView commitAnimations];
I have a UIView called goalBar which is being animated by increasing the size of the frame according to a float value called destination:
CGRect goalBarRect = CGRectMake(0, 0, destination, 29);
[UIView beginAnimations:#"goal" context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
[UIView setAnimationDuration:2.0f];
goalBar.frame = goalBarRect;
[UIView commitAnimations];
The animation works perfectly and the rectangular view increases its width over the course of the animation (from 0 to the value for destination).
However, I wish to be able to extract the values for the frame of the UIView being animated (i.e. goalBar) as the animation takes place. By that I mean that I wish to place the value of the width for the animated frame in a separate UILabel so that the user sees a counter that provides the width of the UIView as it's being animated.
Any help on how to do the above would be gratefully received.
How about observing the frame property of the view. So that you get callbacks when it changes.
See Key-Value Observing.
I've looked into this and it seems that it is not possible to get updates on the state of the components being animated during the UIView animation process.