When is it safe to retrieve image height in iOS - ios

I've got a table cell. Within it I've got an image that has a height constraint of 25% of the screen size.
When is the proper time to retrieve the image height using
imageView.frame.height
to make sure that it has been resized according to the constraint? In general i am a little confused as to when the time to retrieve the element heights (images, labels ) is in the lifecycle. I need this information to add up with all the other element heights for a cell so i can tell a table what the row size is using the heightForRow method.
P.S: I cannot use UITableViewAutomaticDimension as one of the elements is a webview and i can only retrieve its height after the webview delegate method completes and has loaded a webpage.

If you are using autolayotus, you can get imageView or any other UIElements frames in viewDidLayoutSubViews or in viewDidAppear. These life cycle methods will be called while/after applying constraints.

You can always subclass UIImageView and override methods setFrame and setBounds to met your needs.

Related

Correct autolayout width not being returned on iOS 8

I'm trying to get the width of a UIView inside a custom UITableViewCell, in order to make some changes to it's appearance. I'm using autolayout, however, the width of the view returned is that which is defined in the xib file. This is different to its actual width once autolayout has laid out the cell.
My code is in layoutSubviews():
override func layoutSubviews() {
super.layoutSubviews()
print(backgroundView.frame.width)
}
This works in iOS 9, but not in iOS 8. Calling self.setNeedsLayout() and self.layoutIfNeeded() has no effect. Where can I move the code so that it displays the correct width?
Thanks.
I've had this problem before, and if I recall correctly it had something to do with iOS not knowing the actual size until after the view has been drawn the first time. We were able to get it to update by refreshing after viewDidAppear (like you mentioned it's the appropriate size after refreshing), but that's not exactly the nicest solution.
Something else you could try is adding constraint outlets to the cell that you manipulate wherever you do your cell setup. For example, if you needed a UI element to be a certain width in some cases but not others, you could add a width constraint that you change the value of. This lets your other elements resize themselves based on the other constraints in the view. The limitation here is that you need to know the width of one of your elements beforehand.

UICollectionView clipsToBounds is not working properly with paging

I am using UICollectionView with horizontal paging enabled. My collectionView frame is less than the screen size.
I used the following code :
myCollectionView.clipsToBounds=FALSE;
Still I am not able to see the views outside the bounds of my collectionView.
I am using custom UICollectionViewLayout
If the size of each page is greater or equal to your collectionView's frame size, you will not be able to see the content outside the frame even clipToBounds is disabled.
In order to save the memory, the cells in the collectionView are reusable and will be removed if they are out of the frame (i.e. only shows the visible cells).
To recreate the effects like the one seen on the App Store:
Try to set the frame of the collectionView as large as your collectionView's superView, and specify proper minimumLineSpacing for your UICollectionViewFlowLayout.
You may like to take a look at this post about targetContentOffsetForProposedContentOffset:withScrollingVelocity which gives you controls to decide the contentOffset of a given page.
I'm not sure but may be the problem when you init your collectionView it's initializing with the some default settings like clipToBounds. Try this method to layout subviews:
-(void)layoutSubviews{
[super layoutSubviews];
myCollectionView.clipsToBounds = FALSE;
}
Hope it works.

Calculate UICollectionView contentSize in tableView's heightForRowAtIndexPath

I have a collectionView inside a UITableViewCell. The collectionView's content is dynamic, hence, its height is dynamic too and the tableView cell's height depends on the collectionView's height. The collectionView cells have different sizes. The collectionView's height is always set to fit its contentSize height.
My problem is that the tableView's function heigthForRowAtIndexPath, is called before the collectionView is created (in cellForRowAtIndexPath) so, to return the height that fits the collectionView, I need to calculate it manually (which doesn't seem like a good idea for a collectionView with cells of different sizes).
I tried to use autolayout in order to use UITableViewAutomaticDimension but it didn't work (maybe I did it in a wrong way).
What is the best aproach to make a UITableViewCell consider the height of its subview in heightForRowAtIndexPath? Can I know a collectionView's estimated size without creating it?
Use self sizing, which is available in iOS 8. There are plenty of good tutorials online, like this one: http://www.appcoda.com/self-sizing-cells/.
The idea is that you can use auto layout and a few lines of code in viewDidLoad to render a table view cell that dynamically fits the content in it.
Some more tutorials:
http://useyourloaf.com/blog/2014/08/07/self-sizing-table-view-cells.html
https://github.com/smileyborg/TableViewCellWithAutoLayoutiOS8

Autolayout scrollview with collectionview

I have been struggling with this for a few days now, and I am looking to see if someone can help me with this AutoLayout problem.
In my iOS7 application, I have a UIView that has a UIScrollView and inside it a UIView(container) with some elements positioned. I have in there, a UIImageView, UITableView, UICollectionView, UITextView and a MapView. There is no height constraint on the UIScrollView and the container UIView. There are no height constraints on the UICollectionView and the UITextView.
What I want to accomplish is
The UITextview should expand to the content size as in all the text should appear without any vertical scrolling enabled for the UITextView.
The UICollectionView should always show all items and there should not be any scrolling enabled there as well.
Overall, I want a UIScrollView with items in it, that scale based on content. I have tried numerous things, but failed.
If anyone has pointers or suggestions on how to go about doing this, it would be very helpful.
OK, I would go about this in a completely different way.
First, get rid of the scrollView completely.
Just use a UICollectionView for this entire interface.
The UICollectionView can take a UIView for a section header. Make this UIView with your UITextView inside. You will need to manually calculate the correct height for your UITextView (and UIView).
Something like...
CGSize size = [theText sizeWithFont:<the font used> constrainedToSize:CGSizeMake(desiredWidth, CGFLOAT_MAX)];
Then just populate your collection view.
By doing this your collection view will control all the scrolling. Because you have set the textview to the correct size in the header you will have all the text there.
This is how I would go about it:
I assume your issue is with the height of the views, that affect the scrolling.
In the textViewDidChange: I would set the frame of the UITextView same as it's contentSize. When they are both the same, scrolling gets disabled.
After populating your UITableView and calling reloadData, I would set it's frame same as it's contentSize.
The mapView (MKMapView, I suppose) has the same frame throughout, I suppose. So you just use it's fixed height. If it changes height, you must store it's changing height each time it changes.
Once you have all the heights, add them up, and set the frame of the outer view same as then combined height of the inner view. Iterate this to all nested views, beginning from innermost views, and moving to outer views.
The catch here is, every time your content changes, the frames have to be resized. Hence changing the frames in textViewDidChange:, after reloadData, etc makes sense.
EDIT : One thing you might want to do first is, getting rid of redundant views. Your view hierarchy seems Rube Goldberg to me. The lesser views you have, the lesser work you will have to do.
Ok.. so I solved this problem by creating a IBOutlet for my NSLayoutConstraint on the UITextView in question.
I simply computed the height and then applied it on the constraint and it worked..
#Fogmeister - Your solution will also work, but it would require me to rewire a whole UI page.. Your approach is definitely a feasible one and shall keep in mind for future iOS apps..

UITableViewCell - How to handle dynamic sized content views from Nibs

When I want to have a custom cell, I generally add a UIView subclass to the cell's content view. For the layout of my subviews I use a nib. Then I wire up the nib to my UIView subclass. My issue is how to dynamically size content. Say my view has a lot UILabels inside it. I use layoutSubviews to position all the subviews - but it is only until that is done that I truly know the height of my cell. So currently in tableView:heightForRowAtIndexPath I setup my subview and call layoutIfNeeded so everything is positioned properly. Now I know the height of my cell and return it in the tableView:heightForRowAtIndexPath method. But now when tableView:cellForRowAtIndexPath is called the cell that I am given has a height of 44.0. When I added my subview to it - my subview is outside of its parent's bounds. Then when the cell is later resized in iOS to the height that I said I needed, my content is thrown off because of my autoresizingMask. Just trying to figure out if this is an issue others deal with or if I'm approaching it completely wrong. It just seems backwards that we ask for the height, then create a cell that is not that height.
Unfortunately, this is how UITableViews work: You need to provide the heights before the UITableViewCells are actually rendered.
And yes, everyone has to deal with it. :)
You could create an NSArray, add all your custom contentViews, set their frame according to the expected contentView bounds and then use this array as data source in tableView:heightForRowAtIndexPath: and tableView:cellForRowAtIndexPath:. While this isn't exactly efficient, it works fine for small data sets.
Also, here's a nice tutorial with this topic:
UITableViewCell Dynamic Height (by Matt Long)
A similar question on SO:
How can I do variable height table cells on the iPhone properly?

Resources