UIView animation does not allow center setting - objective-c

I try to move an ImageView (say, view1) so that its center matches another ImageView's center (view2), while resizing it. On completion this first view is removed, but is image is copied into the view2, so its image seems to remain.
For that purpose I tried many combinations but with any, even creating a new ImageView3 that I can insert into view2, as soon as I try to set the center of view3 to match the center of view2, nothing happens and my image disappears, never being inserted in view2. Without setting the center, everything works. Damn, Why? Did I miss something obvious or am I stupid?
Or should I definitely use coreAnimation?
[UIView animateWithDuration:0.5 animations:^{
view1.center = view2.center;
view3.center = view2.center;
} completion:^(BOOL finished){
[view2 addSubview:view3];
}];

In the completion block, you add view3 as a subview to view2. This is probably not what you want, at least not without further adjusting its position. Since you have reset its center in the animation, the coordinates are based on the parent view. When you add it to view2, the apparent position shifts based on the relative position of view2.

Related

UIButton inside a UIView not working after UIView is animated

I have seen many questions in this forum which gives answer to this topic "UIButton inside a UIView, when animated doesn't work", but after having tried out the answers like
a) UIViewAnimationOptionAllowUserInteraction to the options
b) subView.setUserInteractionEnabled = YES
c) [button addTarget:self action:#selector(buttonPressed) forControlEvents:UIControlEventTouchUpInside];
none of them is working for me :-(
Here is the scenario. App is in landscape mode and a UIView called menuView is placed at x=480,y=0. Its height=200 and width=150. So, when I tap the button on the top right corner, the following code is executed
- (IBAction)showMenu {
[menuView setUserInteractionEnabled:YES];
[optionsButton setUserInteractionEnabled:YES];
[UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationCurveEaseOut | UIViewAnimationOptionAllowUserInteraction
animations:^{
self.view.frame = CGRectOffset(self.view.frame, 0, 200);
}
completion:NULL];
}
Output?: View is appearing, but optionsButton inside the menuView is not clickable. I hooked up to an event, did an NSLog(#"Options button clicked"), but nothing happens :-(
Please tell me what I am doing wrong?
Update: When I place the subview that is "menuView" inside the self.view, then upon running and click the optionsButton, I get the NSLog message. Only if I specify the origin.x of menuView to be 480 and above, it doesn't work.
If you can see the UIButton, its userInteractionEnabled (YES by default!) is set, and its superview's userInteractionEnabled in the whole hierarchy is YES - you should be able to interact with it.
An animation will never change your userInteractionEnabled property! So what you are doing there is simply unnecessary. If you try to enable interaction during animation - that's a different story and is just an option passed to the animation message.
So if that's not your problem (and is probably not), then I guess one of the superview's frame is cropping the UIButton!
Now you see, if a UIButton (or any UIView) is outside a UIView's frame, it can still be visible, unless clipsToBounds is set on the superview.
And the outcome of that situation is: You can see me, but you can't touch me.
In my case missing a constraint on the height of the containing view caused the view height to be 0. Buttons were visible, below the view, but untouchable.
For me it was all about an overlooked mistake in the animation code itself. Where my new height was being called I was actually calling my new width, and where my new width was being called I was actually calling my new height, therefor causing the UIView to be super long yet super narrow, thus pushing all content within the center of view, outside of the view reach.
Change your UIViews background color to Red so that you can actually see where it animates to.
If your UIView is within another view, turn on clipSubviews so that you only see what is actually enabled within the subView.
Run your project.
If your UIView is not its normal height and width, more than likely you have overlooked some code in your animation call.
Make sure that your x, y, width, height are being shown in the correct orders within the animation code.
In my case, it seems like my animated transitioning is not yet completed. I forgot to to put completeTransition:Bool at the end of my animateTransition:context method.

why button cannot move in animation?

I want to click _transitButton to call onTransitButtonDidClick to move _rightView.
The problem is the button cannot do as I set self.transitButton.frame = CGRectMake(0, 0, 30, 20);.
update:
_transitButton original frame is (0,280,30,20)
the result is, the button move from the original frame to (0,0,30,20), but quickly move back to original point.
why it went back?
why and how to solve this issue?
- (IBAction)onTransitButtonDidClick:(id)sender {
[UIView animateWithDuration:0.3
delay:0.0
options:UIViewAnimationCurveEaseInOut
animations:^{
[_rightView setFrame:CGRectMake(40,0,320,548)];
[_transitButton setFrame:CGRectMake(0,0,30,20];
}
completion:nil];
}
you are using autolayout in your xib and constraints keep the button in place.
with animation it appears to work because the constraints arent evaluated for animations.
so either turn off AUTOLAYOUT for this xib or modify the appropriate constrains.
(I tried this with a small sample app and that's it.)

Rotating UIViews become unresponsive

I have a UIViewController subclass that changes its frame when the UI rotates (for example, most commonly, the frame is the same size and centered in both landscape and portrait.) When the view rotates, the view visually changes its frame as expected. But the controls (buttons, scroll views, etc.) that end up in the area of the new frame do not respond to touches. The only controls that respond are the ones that have remained in the original frame (so, if the view moves down and to the left, controls or parts of controls in the upper right corner remain responsive.) Any idea what's going on here?
Here's the code that changes the frame:
- (void) setLandscape:(bool)bLandscape {
if( bLandscape )
[self setFrame:m_landscapeFrame];
else
[self setFrame:m_portraitFrame];
}
And in the bigger view controller that handles rotation directly:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
bool bToLandscape= UIInterfaceOrientationIsLandscape(toInterfaceOrientation);
[UIView beginAnimations:NULL context:nil];
[UIView setAnimationDuration:duration];
[m_pCurrentWindowViewController setLandscape:bToLandscape];
// (Some unrelated stuff happens here...)
[UIView commitAnimations];
}
To me this seems like a bug or at least poor design on Apple's part - there should never be a time when a view is in one position visually and another position in terms of control. But I'm just looking for a way to fix this behavior.
The simplest workaround I found was to update the frame in didRotateFromInterfaceOrientation after animating in willRotateToInterfaceOrientation.

Animating a view & its subview separately

I have a view interface which contains a subview touchWheel. On clicking a minimise button on interface I'd like to perform a transform & send the view to the bottom-right corner of my screen. The thing is that I want to "detach" the touchWheel view & send it to the corner separately with the parent-view, interface, following behind (& in fact fading out).
when I try this I encounter a problem. My animation works fine initially & touchWheel is sent towards the bottom corner, as desired. When touchWheel is about half-way to its destination I animate interface so that it follows touchWheel.
Once interface starts animating it appears to control touchWheel & touchWheel changes course.
It seems that interface still retains control of touchWheel since it's its parent view.
- (void)hideInterfaceButtonClicked : (id) sender
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"RemoveGrey" object:self];
//Remove Views & transform
[touchWheel removeViews];
interfaceHidden = YES;
//Send Interface to corner
[UIView animateWithDuration:1.25
delay:0.0
options:UIViewAnimationCurveEaseIn
animations:^{
// Move to the right
CGAffineTransform translateInterface = CGAffineTransformMakeTranslation(437,200);
// Scale
CGAffineTransform scale = CGAffineTransformMakeScale(0.135,0.135);
// Apply them to the view
self.transform = CGAffineTransformConcat(scale, translateInterface);
self.alpha = 0.0;
} completion:^(BOOL finished) {
NSLog(#"Animation Has Stopped");
[[NSNotificationCenter defaultCenter] postNotificationName:#"hiddenInterfaceViewNeeded" object:self]; //after MoveView finishes
}];
}
Making touchWheel subview of something other than interface creates other problems which would complicate things further.
Any ideas how one might get around this issue? any tips greatly appreciated :)
You could do the following:
Move touchWheel to the interface's superview, recalculating its frame using convertRect:toView: so that touchWheel appears to have the same window coordinates.
Animate both the views to their final locations.
In the completion block of the animation do the opposite of step 1: make touchWheel a subview of interface, recalculating its frame again.
It doesn't seem too complicated, but there's a caveat: you may want to temporarily disable the maximize button (or whatever the appropriate control is) to prevent the maximize action during the animation. Otherwise, this approach will cause unpredictable results.

Why do updates on "contentOffset" of a UIScrollView make no effect?

I have a UIScrollView which is scrollable both vertically and horizontally. This view is filled with lots of buttons, each of them with its own width (but all with the same height).
When one of these buttons gets tapped, a slider-like interface is brought to life. If this interface goes over the selected button, the whole scroll view must be scrolled so that the button becomes visible once again.
My app behaves as expected when the Y coordinate of the scroll view's content offset is set to a limit (this limit can be 0 or the view's height). But if the content offset is located in an intermediate vertical position, the scrolling just doesn't seem to happen.
At first, I tried the following approach:
CGPoint newOffset = CGPointMake(self.scrollView.contentOffset.x + horizontalVar,
self.scrollView.contentOffset.y);
[self.scrollView setContentOffset: newOffset animated: YES];
Which didn't work, as I mentioned.
Then, I tried to manually animate the view, using its property setter:
[UIView animateWithDuration: 0.3 animations: ^{
CGPoint newOffset = CGPointMake(self.scrollView.contentOffset.x + horizontalVar, self.scrollView.contentOffset.y);
self.scrollView.contentOffset = newOffset;
}];
That approach produced the following result: if the scroll view is in an intermediate vertical position when one of its buttons gets tapped, the content offset update causes a visual change, but the view almost immediately returns to its original state.
I have no other clues on the subject. Could you please help me?
Maybe it's because you didn't set the ContentSize of your scrollView.