UITextView not resizing correctly - objective-c

I have a view that has a table view on the top, and a scroll view below the table view.
When I press the resize bar button item, I want to hide the table view and maximize the scroll view. I got the scroll view and table view to animate correctly, but I am trying to resize the UITextView inside the scroll view to take advantage of the extra screen space.
Whenever I calculate the resize, the UITextView goes to the top left corner of the screen, and I'm not sure why. I am not even modifying the X and Y, just the height.
CGRect newDesFrame = descriptionTextView.bounds;
newDesFrame.size.height = newDesFrame.size.height + tableViewFrame.size.height;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:.5];
self.scrollView.frame = scrollFrame;
self.descriptionTextView.frame = newDesFrame;
[UIView commitAnimations];
I am not sure why this happens. Does the descriptionTextView.bounds get messed up since it's in a UIView inside a UIScrollView? It seemed that, when I do a NSLog of the X and Y of the scroll view, it's 0,0. It's weird since it's not at 0,0 in the superview, or in the view. How do I fix this?

descriptionTextView is most likely jumping to the top left because you are, in fact, changing the origin (x and y). You are starting with:
CGRect newDesFrame = descriptionTextView.bounds;
Getting the bounds of that text view will give you a CGRect with an origin of 0,0, as 'bounds' gives you the view's rectangle in its own, local coordinate space.
Try this instead:
CGRect newDesFrame = descriptionTextView.frame;
This will give you the view's rectangle in its superview's coordinate space, including the actual origin.

It happens because you are doing
self.descriptionTextView.frame=newDesFrame ( which is Bounds property, not frame!! To read about differences Link)
Solution:
self.descriptionTextView.bounds=newDesFrame

Related

How can I animate a change to a UIButton's height without image warping?

I'm using [UIView animateWithDuration:animations:] to hide a UIButton by changing its frame.size.height to 0. However, as soon as the animation begins, the rounded rectangle and background immediately disappear while the button text clips off the bounds of the view.
The code I'm using is fairly straightforward:
CGRect newFrame = button.frame;
newFrame.size.height = 0;
[UIView animateWithDuration:2.0 animations:^{
button.frame = newFrame;
}];
I've noticed that this only happens when i'm setting the height to 0. It seems that when the animation begins, the button is simply redrawn once in its final state. The animation is performed by scaling this static image from the original size to the final one. Since a button with a height of 0 can't be seen, it results in the whole roundrect disappearing (except for the text on the button, since it's a different view).
There must be a better way to do this so the animation doesn't look as weird. How can I make the animation behave the way I want?
Does it work better if you do something like this?
CGRect newFrame = button.frame;
newFrame.size.height = 1;
[UIView animateWithDuration:2.0
animations:^{button.frame = newFrame;}
completion:^{button.hidden = YES;}];
If you are using a system rounded rect button, it might also be that they do not like being resized below a certain level, it might work better with a custom button.
Why not just setting your button's alpha value to 0 in your animation? Or do you have to animate its height?
Take an image snapshot of the button, and do an affine transform animation rotating that view upwards, or changing the y scale.

Set view position to top right programmatically in cocoa touch

I need to make sure that one view A (size: 200x200) is always aligned to top right corner inside second view B (full screen size). I want to make sure that view A stays in that place regardless of device orientation. Truth is I have no problem with this when using interface builder to position the views but I need to construct this programmatically. I suppose I should use some autoresizing settings, could you tell me which one is supposed to align the view to top right corner of its superview?
UIView parentView //your full screen view
UIView view //the 200x200 view
[parentView addSubview:view];
CGRect frame = view.frame;
//align on top right
CGFloat xPosition = CGRectGetWidth(parentView.frame) - CGRectGetWidth(frame);
frame.origin = CGPointMake(ceil(xPosition), 0.0);
view.frame = frame;
//autoresizing so it stays at top right (flexible left and flexible bottom margin)
view.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin
That positions the view on top right and set's the autoresizing mask so it stays at that position.

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.

Resizing UIView with UIScrollView subview

I have a big problem concerning the resizing of a derived UIView with a UIScrollView as subview.
In the layoutSubviews message I set the frame of the UIScrollView subview. the UIScrollView contains a UIImageView with a big image which can be moved/pinched and so on. The initial contenSize of the UIScrollView is the initial image size.
So far, so good. Moving and pinching of the image works well. Now I have to change the UIView frame (in my app to maximize the UIView). im doing that in a animation block (beginAnimations/commitAnimations). So I set the new frame (which will update the width & height) an then I call [myView layoutIfNeeded] to force the UIScrollView to update its frame in the layoutSubviews message of my view.
The UIView animates correct to its new frame and if the contentOffset of the UIScrollView is currently x 0, y 0 the UIScrollView frame will be updated properly. but here's my problem: if the contentOffset of the UIScrollView is bigger than x 0, y 0 the UIScrollView will "slide in" from upper left to its final position.
I want that the UIScrollView resizes its frame properly with the parents frame and aligns the content (in my case the UIImageView) right. But how could I achieve that?
after hours of web research i found the solution for this problem:
[UIView setAnimationBeginsFromCurrentState: YES];
this will animate all layers from the current state.

How do I pan the image inside a UIImageView?

I have a UIImageView that is displaying an image that is wider and taller than the UIImageView is. I would like to pan the image within the view using an animation (so that the pan is nice and smooth).
It seems to me that I should be able to just adjust the bounds.origin of the UIImageView, and the image should move (because the image should paint inside the view with that as its origin, right?) but that doesn't seem to work. The bounds.origin changes, but the image draws in the same location.
What almost works is to change the contentsRect of the view's layer. But this begins as a unit square, even though the viewable area of the image is not the whole image. So I'm not sure how I would detect that the far edge of the image is being pulled into the viewable area (which I need to avoid, since it displays by stretching the edge out to infinity, which looks, well, sub-par).
My view currently has its contentsGravity set to kCAGravityTopLeft via Interface Builder, if that makes a difference (Is it causing the image to move?). No other options seemed to be any better, though.
UPDATE: to be clear, I want to move the image inside the view, while keeping the view in the same spot.
I'd highly recommend enclosing your UIImageView in a UIScrollView. Have the UIImageView display the full image, and set the contentSize on the UIScrollView to be the same as your UIImageView's size. Your window into the image will be the size of the UIScrollView, and by using scrollRectToVisible:animated: you can pan to particular areas on the image in an animated fashion.
If you don't want scroll bars to appear, you can set the showsHorizontalScrollIndicator and showsVerticalScrollIndicatorproperties to NO.
UIScrollView also provides pinch-zooming functionality, which may or may not be useful to you.
Brad Larson pointed me down the right road with his suggestion to put the UIImageView inside a UIScrollView.
In the end I put the UIImageView inside of a UIScrollView, and set the scrollView's contentSize and the imageView's bounds to be the same size as the image in the UIImage:
UIImage* image = imageView.image;
imageView.bounds = CGRectMake(0, 0, image.size.width, image.size.height);
scrollView.contentSize = image.size;
Then, I can animate the scrollView's contentOffset to achieve a nice panning effect:
[UIView beginAnimations:#"pan" context:nil];
[UIView setAnimationDuration:animationDuration];
scrollView.contentOffset = newRect.origin;
[UIView commitAnimations];
In my particular case, I'm panning to a random space in the image. In order to find a proper rect to pan to and a proper duration to get a nice constant speed, I use the following:
UIImage* image = imageView.image;
float xNewOrigin = [TCBRandom randomIntLessThan:image.size.width - scrollView.bounds.size.width];
float yNewOrigin = [TCBRandom randomIntLessThan:image.size.height - scrollView.bounds.size.height];
CGRect oldRect = scrollView.bounds;
CGRect newRect = CGRectMake(
xNewOrigin,
yNewOrigin,
scrollView.bounds.size.width,
scrollView.bounds.size.height);
float xDistance = fabs(xNewOrigin - oldRect.origin.x);
float yDistance = fabs(yNewOrigin - oldRect.origin.y);
float hDistance = sqrtf(powf(xDistance, 2) + powf(yDistance, 2));
float hDistanceInPixels = hDistance;
float animationDuration = hDistanceInPixels / speedInPixelsPerSecond;
I'm using a speedInPixelsPerSecond of 10.0f, but other applications might want to use a different value.