Why uiscrollview doesn't make visible the contentOffset change? - iphone

Hello everyone I have a problem with a uiscrollview.
When I press a button to change the contentOffset scollview through a UIView animation so I have something like this:
NSLog(#"%#\n %f %f", scroll, scroll.contentOffset.x, scroll.contentOffset.y);
[UIView beginAnimation:#"anima" context:nil];
[UIView setAnimationDuration:0.5];
scroll.contentOffset = CGPointMake(0,index * scroll.frame.size.height;
[UIView commitAnimations];
NSLog(#"%#\n %f %f", scroll, scroll.contentOffset.x, scroll.contentOffset.y);
Making a log cotentOffSet before and after these instructions is changed and obviously the scrollview is an existing instance so it is different from nil.
The problem is that the screen does not change the offset scrollview that is not moving.
I do the same thing in other parts of the code and other scrollview but it works perfectly.
I also tried:
[scroll setContentOffset:CGPointMake(0, index * currentVerticalScrollView.frame.size.height) animated:YES] ;
but does not change too!
Why isn't it work?

Have you ensured to invoke setContentSize: on scroll originally, large enough to allow for the scroll offset?
If so, it may need a [scroll setNeedsDisplay] to give it a kick!

Related

Animation not Shown When Calling it First Time

I have one simple animation:
- (void)showMenu
{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationDelay:0.0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
self.scrollView.frame = CGRectMake(296, -150, 432, 356);
[self.buttonMenu setImage:[UIImage imageNamed:#"menu_arrow_up.png"] forState:UIControlStateNormal];
[self.view bringSubviewToFront:self.scrollView];
[UIView commitAnimations];
}
When I call this animation the first time, just the image of my button changes,
the position of my scrollview does not change.
Everything works correctly, after I called my showMenu method twice.
I call showMenu. the image of the button changes. position of scrollview not
I call another method to reset everything. image of button changes. position of scrollview not
I call showMenu. the image of the button changes. position of scrollview changes
from now on it works every time I call showmenu
the second method is closeMenu:
- (void)closeMenu
{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationDelay:0.0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
self.scrollView.frame = CGRectMake(296, -317, 432, 356);
[self.buttonMenu setImage:[UIImage imageNamed:#"menu_arrow_down.png"] forState:UIControlStateNormal];
[UIView commitAnimations];
}
So why does it work just when I click it twice?
I had the same problem when i perform a UIAnimation and simultaneously adding a UITableView programmatically. The frame of UIView changes but it will not update in display.
To solve this problem call your method using performSelector:withObject:afterDelay: with a delay of 0.
If you have autolayout turned on, you may want to wary about changing the frame of a view. Unfortunately, when the constraints are reapplied (which triggered by a myriad of seemingly innocuous actions, such as setting a text label, etc.), your manually set frame will be replaced with values governed by the constraints.
You're probably not seeing this problem manifest itself the second time time you call this routine because you're probably not doing anything immediately thereafter that causes constraints to be reapplied. Even with autolayout on, you can sometime change a frame manually, and it will work, but as soon as constraints are reapplied, the frame may get reset.
There are two solutions:
If using auto layout, you can animate the changing of constraint constants. See the latter part of this answer for an example of how to create an IBOutlet for constraint and then changing the constant property within an animation block.
You can also simply disable autolayout.

Setting UIControl's frame changes view bounds but not where it can receive touches

I have a headerView which can expand and collapse when pressed. It's default state is collapsed.
I use the following code to expand the headerView.
if (!self.headerViewIsExpanded) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[self.collapsedHeaderView removeFromSuperview];
self.headerView.frame = self.expandedHeaderView.frame;
[self.headerView addSubview:self.expandedHeaderView];
self.tableView.frame = CGRectMake(self.tableView.frame.origin.x, self.tableView.frame.origin.y + offset, self.tableView.frame.size.width, self.tableView.frame.size.height - offset);
[UIView commitAnimations];
self.headerViewIsExpanded = YES;
}
It correctly expands the view frame and diminishes the tableView frame. However, it fails to expand the touches received area of the original UIControl, so I can only collapse it by pressing where the original frame was.
How can I resolve this issue?
EDIT: Alternatively, I would accept an answer with a good explanation of why I cannot resolve the issue, or at least not resolve it safely.
EDIT 1: To be more clear, the headerView is NOT a tableView header view. It is just a view that sits on top of the table that happens to be called headerView. Both headerView and tableView are subviews of the main UIView that spans the available window.
You can try to overload layoutSubviews method. Inside you should use setFrame method for your headerView to define all view elements position.

Animating UIView frame size change with autoresizing subviews

I have a UIView which contains two subviews. I would like to change the superview's frame size with an animation and have the subviews' sizes change in accordance with their autoresize masks.
[UIView beginAnimations:#"Resize" context:nil];
[UIView setAnimationDuration:1.0];
CGRect frame = self.myView.frame;
frame.size.height += 30.0;
self.myView.frame = frame;
[UIView commitAnimations];
The view self.myView is resized over 1 second as expected, but the subviews are resizing immediately. Does anyone know why this is happening and how I might make the subviews animate their resizing as well?
From my googling around, I think it might have something to with the contentMode property. Unfortunately, I'm not really clear as to what that property does. Any help would be much appreciated.
It would have been hard for someone else to give you the correct answer w/o seeing your code though I would have asked you what you are doing after [UIView commitAnimations]. Nevertheless, glad you figured it out. I suggest you use the block animations. They make this type of mistake much easier to avoid by using a completion block. Example:
[UIView animateWithDuration:1.0
animations:^{
CGRect frame = self.myView.frame;
frame.size.height += 30.0;
self.myView.frame = frame;
}
completion:^(BOOL finished){
// whatever you need to do when animations are complete
}];
OK, so I figured out the issue after reading the answer to the following question: Animating a UIView frame, subview UIScrollView doesn't always animate
I basically was doing some work after I scheduled the animation which was causing -layoutSubviews to be called on each of my subviews which automatically caused those views to be arranged at the end point of the animation. By scheduling my animation after this work was done I was able to solve my problem.

Touch issue during UIView Animation

I am animating UIView when user touches on custom dropdown to show picker View from bottom side.UIView contains Pickerview...so when I change it's frame to move upwards.I get what I want, but pickerView doesn't recognize touch !(see screenshot below)
code is like this
CGRect pickerFrame=self.pickerSheet.frame;
CGRect viewFrame=self.view.frame;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:SHEET_ANIMATION_DURATION];
//change Frame of View containing UIPickerView
pickerFrame.origin.y=202+animatedDistance;
viewFrame.origin.y-=animatedDistance;//animated distance is value by which view needs to move upward.
[self.pickerSheet setFrame:pickerFrame];
[self.view setFrame:viewFrame];
[UIView commitAnimations];
screenshot
first of all, ++please**, stop using this animation declaration, and bedin use new, block animation:
[UIView animateWithDuration:SHEET_ANIMATION_DURATION
delay:0
options:nil
animations:^{
pickerFrame.origin.y=202+animatedDistance;
viewFrame.origin.y-=animatedDistance;
}
completion:^(BOO f){
//any actions after animation ended
}];
Second, I think your problem is somewhere else. May by, you implementing your touches or picker wrong.
Please start using the new , better animation block , but I think there is something missing in your code , you need to put the code below :
UIViewAnimationOptionAllowUserInteraction
Put this code in options in the new animation block , or find a way to put it in the old animation block

iPhone SDK: After a certain number of characters entered, the animation just won't load

Okay, this is the code:
[lblMessage setText: txtEnter.text];
[lblMessage sizeToFit];
scrollingTextView.contentSize = lblMessage.frame.size;
float width = (lblMessage.frame.size.width) + (480);
[UIView beginAnimations:#"pan" context:nil];
[UIView setAnimationDuration:durationValue];
[UIView setAnimationRepeatCount:5];
scrollingTextView.contentOffset = CGPointMake(width,0);
[UIView commitAnimations];
//The scrolling text view is rotated.
scrollingTextView.transform = CGAffineTransformMakeRotation (3.14/2);
[self.navigationController setNavigationBarHidden:YES];
btnChange.transform = CGAffineTransformMakeRotation (3.14/2);
I have the user enter in some text, press a button and then a label is replaced with the text, turned 90 degrees in a scrollview on a page.
After a certain number of characters, for example say 20.. the animation just won't load. I can go back down until the animation will run.
Any ideas on where I am going wrong, or a better way of storing the text etc etc ?
Core Animation animations are performed on a separate thread. When you enclose the change in contentOffset in a beginAnimations / commitAnimations block, that change will be animated gradually. The scrolling text view rotation that occurs next, outside of the animation block, will be performed instantly. Since both are interacting with the same control on different threads, it's not surprising that you're getting weird behavior.
If you want to animate the rotation of the text in the same way as the contentOffset, move that line of code to within the animation block.
If you want to have the rotation occur after the offset change animation has completed, set up a callback delegate method. You can use code in the beginning of your animation block similar to the following:
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(contentOffsetAnimationHasFinished:finished:context:)];
which requires you to implement a delegate method like the following:
- (void)contentOffsetAnimationHasFinished:(NSString *)animationID finished:(BOOL)finished context:(void *)context;
{
// Do what you need to, now that the first animation has completed
}
EDIT (2/6/2009):
I just created a simplified version of your application, using only the sideways text scrolling, and find no problem with the animation on the device with any number of characters. I removed all extraneous calls to layout the buttons, etc., and only animate the text. Rather than apply the rotation transform to the scroll view every time you click the button, I have it start rotated and stay that way.
I thought it might be a layer size issue, as the iPhone has a 1024 x 1024 texture size limit (after which you need to use a CATiledLayer to back your UIView), but I was able to lay out text wider than 1024 pixels and still have this work.
A full Xcode project demonstrating this can be downloaded here. I don't know what your issue is, but it's not with the text animating code you present here.
Right, this code is working fine in the simulator, and works fine until i enter more than say 20 characters in txtEnter.text:
- (IBAction)updateMessage:(id)sender
{
//Animation coding
//Put the message in a resize the label
[lblMessage setText: txtEnter.text];
[lblMessage sizeToFit];
//Resize the scrolliew and change the width.
scrollingTextView.contentSize = lblMessage.frame.size;
float width = (lblMessage.frame.size.width) + (480);
scrollingTextView.transform = CGAffineTransformMakeRotation (3.14/2);
//Begin the animations
[UIView beginAnimations:#"pan" context:nil];
[UIView setAnimationDuration:durationValue];
[UIView setAnimationRepeatCount:5];
//Start the scrolling text view to go across the screen
scrollingTextView.contentOffset = CGPointMake(width,0);
[UIView commitAnimations];
//General hiding and showing points.
[txtEnter resignFirstResponder];
[btnChange setHidden:NO];
[txtEnter setHidden:YES];
[btnUpdate setHidden:YES];
[lblSpeed setHidden:YES];
[lblBackground setHidden:YES];
[backgroundColourControl setHidden:YES];
[speedSlider setHidden:YES];
[scrollingTextView setHidden:NO];
[backgroundImg setHidden:NO];
[toolbar setHidden:YES];
[self.navigationController setNavigationBarHidden:YES animated:YES];
//Depending on the choice from the segment control, different colours are loaded
switch([backgroundColourControl selectedSegmentIndex] + 1)
{
case 1:
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackTranslucent animated:YES];
break;
case 2:
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque animated:YES];
break;
default: break;
}
btnChange.transform = CGAffineTransformMakeRotation (3.14/2);
}
I've tried your method Brad, but can't seem to get the (void) section to work properly.
What my app does its fill the label with a message and then rotates them all to act like it's in landscape mode. Then what it does it scroll the label within a scrollview to act like a scrolling message across the screen.