subView not animating properly when main View shrinks - ios

My app has a UIView called stepView that needs to grow and shrink, always expanding down and to the right, and always shrinking up and to the left. It has a subview, durationLabel, which runs along the entire width of the stepView and has a fixed height.
When the stepView is animated to grow larger, the label grows properly along with it: the text and the label's background slide to the right in sync with the growing stepView. However, when the stepView is animated to grow smaller, it immediately snaps to its new size, leaving a gap between the stepView's shrinking right edge and its right edge until the animation completes.
The label initialization code in stepView.m:
CGRect duration_frame = CGRectMake(0, 0, self.frame.size.width, HEADER_HEIGHT);
self.durationLabel = [[UILabel alloc] initWithFrame:duration_frame];
[self.durationLabel setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
[self addSubview:self.durationLabel];
And the animation code:
[UIView animateWithDuration:ANIM_DURATION
animations:^{
[stepView setFrame:newFrame];
}
];
Using bounds/center instead of frame produces the same effect. I've considered using a transform instead, but the code for calculating "newFrame" is somewhat involved, so I'd rather avoid rewriting it if possible. I've also tried manually changing the label's frame in the same animation block, but that simply makes it disappear entirely (possibly because I was trying to animate both a view's frame and its subview's frame in the same animation block?). I've also confirmed stepView and its subviews aren't undergoing any other animations at the same time, although there are animations happening to unrelated views in separate animation blocks.
I'm at a loss for why the label should animate perfectly when the stepView grows but fail to animate at all when it shrinks. I haven't seen anything in the documentation that indicates there would be a difference. Thank you for any help you can provide.

I think this is an issue with UILabel - using another UIView as subview instead of an UILabel the animation works fine also when you shrink.
If I understand correctly what you need to obtain as result, however, I would suggest you to try the following:
don't set the autoresizingMask property
// [self.durationLabel setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
set the stepView clipToBounds property to YES
self.clipToBounds = YES;
This way the UILabel frame will not change but only the part which is actually within the stepView bounds will be visible. I hope this might help.
Update: just done a quick research and found that the question is already answered here resize uiview with UILabel and animate it correctly - the answers provided seem to be aligned to what I've suggested above.

Related

Adding ScrollView to ViewController with 2 custom Views

My viewController has one view with images and labels and one textView
Im new in objective c.
My problem is to add ScrollView in my ViewController with 2 custom views(UIView and UITextView).(image in the link) I have tried many things posted here in Stack but nothing works for me.
Thank YOU!
Here is what i have :
self.scrollView.contentSize=self.scrollView.frame.size;
self.scrollView.frame=self.view.frame;
[self.view addSubview:self.scrollView];
Adjusting view's frame was the technology of 5 years ago. You should never set the frame manually, not anymore. Instead start learning Autolayout and Constraints.
These tutorials may help:
https://www.raywenderlich.com/115440/auto-layout-tutorial-in-ios-9-part-1-getting-started-2
https://www.appcoda.com/auto-layout-guide/
You are setting the content size equal to the frame size before you actually set the frame, so it's probably just 0.
You need to just switch the calls around:
self.scrollView.frame=self.view.frame;
self.scrollView.contentSize=self.scrollView.frame.size;
[self.view addSubview:self.scrollView];
The other thing to keep in mind is that because you are setting the frame of a nested view to the frame of its superview, your layout will break (or at least not do what you expect), if the origin of your superview ever changes. If the origin is 0, 0, then you are fine for the moment, but otherwise you may want to set the subview (scrollView) frame to be equal to the superview (self.view) bounds instead of the frame, like this:
self.scrollView.frame=self.view.bounds

iOS - create UIButton manually with given size

I’ a little confused with UIView’s bounds and frame. I’m creating UIButton manually with the same size as its super view:
UIButton *button = [[UIButton alloc]initWithFrame:aView.bounds];
button.backgroundColor = [UIColor blueColor];
[aView addSubview:button];
But in the simulator the button and its super view have different size. I don’t really understand this..
(I didn't use IB to create the button because next I’d like to create a 2D array of buttons within that super view, so I think maybe it’s better to create them manually)
I strongly suspect you're putting you code in viewDidLoad before the view has has a chance to finish laying out its subviews. Move your code to viewDidLayoutSubviews instead.
You are correct to use aView.frame rather than aView.bounds. Both will give you the size (width and height of the aView) but frame gives you the position of aView in its superview. The button will need the position relative to aView not aView's superview. Bounds will give you aView's position in its own coordinate system (most likely 0, 0).
What could be happening is you are creating the button using aViews size before aView's frame has been determined. When is aView's frame being determined? Is aView being created via interface builder? When are you creating the button?
The code you provided does work - that is the correct way to make a subview the same size as its superview. There are two possible explanations for why you think that isn't happening:
You might be misinterpreting what you see in the simulator. The view you see behind the button might not be aView. I'm going to discount that possibility and go with the second possibility:
You are running that code before aView achieves its final size. In other words, you are inserting button, but then layout comes along and changes the size of aView. That change in the size of aView doesn't change the size of button, so button is left with the size aView used to have at the time you created and inserted it.

Why does changing a UITextView's frame origin completely disfigure my entire frame size?

I have a UITextview with a small UIViewController on top of it, whose view is a UITextView (It's red in the screenshots).The small red textView is the subView of the bigger textView under it.
Heres what it looks like. The small textView is red and is in the shape small square (let's say 50 x 50). It is purposely cut of the edge of the screen. That's how it's positioned.
This is in portrait. When the device is rotated to landscape, I'd like the small textView to move to the left so it's no longer on top of the bigger textView, but it's still a subview. So I make a new CGRect that's the same size as the small textView's frame, and then change the x coordinate of the origin. Then reassign the small textViews frame to the altered one. Here's how:
-(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || toInterfaceOrientation ==UIInterfaceOrientationLandscapeRight) {
CGRect smallFrame = self.smallTextView.view.frame;
smallFrame.origin.x -=20.0;
self.smallTextView.view.frame = smallFrame;
}
}
Heres the result:
Obviously this is incorrect. I don't even touch the textView's frame size, but those attributes are changed! What's stranger is that if I NSLog the size dimensions, they are the same as they were before the rotation, 50 x 50.
A few observations:
This only happens when the small red textView is a textView. I could replace that view with a UIImageView and this problem does no occur.
I'm fairly certain this is happening because it's a subview of another UITextView. Why? How? No clue.
I'm starting to think the problem lies in how the big superview UITextView is rotating, and somehow the subview small red textView is being effected some way. Even though "Autoresize Subviews" in interface builder is not checked for either textViews. The large superview textView is constrained to a specific width and height in IB with constraints. So the size doesn't really change there.
I'd really appreciate some help with this. I've been looking at it for a few days and just can't pinpoint a cause or solution.
Solved this a while ago. Assigning the textView's center property instead of its frame solves the problem.
CGPoint center = self.smallTextView.view.center;
center.x -=20.0;
self.smallTextView.center = center;
Even still, assigning the textView's frame with a different origin still causes the bug, even in iOS 7. But assigning the center works just fine.

ios vacuum wrap UIView

my UIView has a dynamic amount of views inside of it and also has a background color to it. I'm trying to tuck the UIView in around all the items, but it's not working.
[self sizeToFit] Seems to work just fine on a UILabel, but not on a UIView.
I know I can calculate the area manually by looping through all the subviews, but that just seems like too much work for something like this.
I'm hoping someone knows a simpler way.. Thanks
UPDATE
If you're using auto layout, you can make your container view fit its subviews snugly. Set up constraints between your container and its subviews, and set up constraints between the subviews and the container's superview, but do not set up constraints between the container and its superview.
ORIGINAL
There's no built-in support for automatically shrink-wrapping a view around its subviews.
The sizeToFit method works by sending [self sizeThatFits:self.bounds.size], then resizing itself based on the size returned by sizeThatFits:.
UILabel overrides the sizeThatFits: method to compute the size of its text in its font.
You will need make a custom UIView subclass and override sizeThatFits:. It's pretty simple:
- (CGSize)sizeThatFits:(CGSize)size {
CGRect rect = CGRectZero;
for (UIView *subview in self.subviews)
rect = CGRectUnion(rect, subview.frame);
return rect.size;
}
I don't think there is a "dynamic" way. You see, resizing only works the way around, a subview ca be made to dynamicaly change it's size when a superview does.
Anyway, what you are describing as "too much work" is exactly (more or less) what sizeToFit does...

uiscrollview inside of a uiview does not work

a UIScrollView works just fine by it's self (in IB). However, once you put the UIScrollView inside of a UIVIew in IB, it no longer works. I'm doing this with no subclassing so what's the deal?
Answer
You have to make sure Autoresize Subviews is checked on the containing UIView.
The next part is a bit of a hack. You need to assign a new frame to the containing UIView as well. However, the new frame CANNOT be the pre-existing size of your UIView. It must be a different size for this to work.
If you want the size contained on your UIView in InterfaceBuilder then you need to do something like this:
self.frame = CGRectMake(0,0,0,0);
self.frame = [put your desired rect size here];
Have you tried returning NO in touchesBegan if the touch falls inside your scroll view's frame?
Edit:
Make sure you set the scroll view's content size ([[self scrollView] setContentSize:CGSizeMake(320,480)]; - the values do not matter) and make sure you check "Bounce Horizontally" and/or "Bounce Vertically" (depending on which you want) as well as "Bounces":
Have you tried to set contentsize property of UiScrollView like this
self.scrollView.contentSize=CGSizeMake(320,860);

Resources