UITextView dynamic width according to text inside in UITableViewCell - ios

I'm working to make a chat bubble like in iMessage. I have to use UITextView to get advantage of DataDetectors to detect urls, phone numbers and addresses automatically. My view hierarchy is like;
-UITableViewCell
-ContentView
-ChatBubbleContainerView
-UITextView
ChatBubbleContainerView have constraints of
10-pt left, right, top and bottom margins --> ContainerView
UITextView have constraints of
10-pt of left, right, top and bottom margins --> ChatBubbleContainerView
I want to achieve a behaviour to make the text view automatically expand its height and width according to its content inside e.g. text. But the text view has no intrinsic content size.
These are what i have tried and got wrong results
Overriding the intrinsicContentSize property of text view but it's
not working too.
Giving a width constraint to the ChatBubbleContainerView and changing it to result of sizeThatFits() method
Giving a width constraint to the ChatBubbleContainerView and changing it to result of text.boundingRect method
These are the results i've got
It's not working properly and the cell is not laying out as expected as i scroll the table view
It's working but the initial width of cell in the nib is 375-pt which is good for 4.7 inch devices but when i switch to devices like iPhone SE which has 4 inches at the initial table view load or cell insertion, the cell's width is calculating according to 375-pt not 320-pt. After scrolling cell, the layout is laying out as expected.
Same with 2.
When i try same layout with UILabel it's working as expected. As you may know UILabel has intrinsic content size.
Thanks

TextView Contraints are good you need to made some changes on ChatBubbleContainerView constraints.
ChatBubbleContainerView constraint:
top, leading, bottom -> 10 pts
MaxWidth(GreaterThanOrEqual) to contentView, for instance 0.85 or you can set TrailingConstraint with maxConstant(GreaterThanOrEqual to contentView.
you need to set the maxWidth then only ChatBubbleContainerView will be responsive.

Related

Autolayout Issue with Multiple Button Aligned Horizontally & Vertically with a Label

Please look at the ScreenShot attached for wCompact|hRegular for different screens, I am trying to make it working since hours but not getting any success. My requirement is that at the top there would be a label with some predefined margin. Although the Label content would render at the runtime, but I know the content size, so resizable label isn't needed actually I think. Now there would be three row at equal distance. In first and third row, there would be two buttons with equal height and width and in second row there would be button aligned horizontally. I have set the buttons image and text in storyboard. Control Alignment are set to Horizontal | vertical. Constraints for label are:
Pinned top space to superview, leading and trailing space equals to:8(superview), height equals:90.
Constraints for Button(View Transactions) are:
top space to label, bottom space equals to:8(New Launches Button) leading and trailing space equals to:8(superview) and 8(Place Request Button) respectively, and equal width and height for all buttons.
Looks fine for 4.7 and 5.5 But not satisfied with the output for smaller screens. As u can see resizing of buttons image not working properly(Larger space between button's image and text). One more thing is I don't wanna set the height of the label, cause it seems like a wrong practice in AutoLayout. Any help would be much appreciated.
You should set the Aspect Ratio for the Buttons, not just the equal width and height. In that case auto layout wont shrink the images.
Really you should put this into a scroll view so that if the height is too great the user can still see everything by scrolling. You should also not set static heights on labels, you should allow the intrinsic content size to apply.
Add a subview to your new scroll view. Pin the width of this subview to the width of the scroll view. Do not pin the height.
Add all of your buttons and labels to this new subview. Pin them to the edges of the view and allow the intrinsic content sizes to apply limits. Set various items to have equal widths and heights. Do not set explicit heights or widths (do everything by proportion or equality so auto layout can choose good sizes).

iOS auto layout centering view with leading and tailing margin issue

I have a subview that contains UIImageView and label where label can be changed dynamically. I set this subview on storyboard with auto layout align vertical center and top/bottom space. So when its label get changed, margin between image and label remains same and subview maintains its align to vertical center as it grows horizontally. But I also want to this subview not to change its width when it hits certain margin (leading and tailing space) respective to its superview. I tried to add auto layout programatically once it reaches to certain point but removing its layout once its get shirked didn't work (i.e. label didn't get change its width even though I called [label sizeToFit]). One thing that came up on my mind was set leading and tailing layout on storyboard and change its constant value properly as label size changes. I would like to know if there is better solution to solve this layout issue. Thanks

Auto layout for uicollectionview

I have a UILabel in my storyboard which i want to align from bottom and whose width and height want to get adjusted in portrait and landscape.
For this, i dragged in a UILabel pinned its leading space, trailing space, bottom space to its superview.
I did not pin its width and height since i wanted its width and height to be changed during its landscape rotation.
With this i got a warning in story board where i have selected to update frame, which automatically adjusted the frame and made it work correctly.
Now i am trying to achieve same kind of behaviour with UICollectionView but this is not working as expected, instead it is giving out some errors saying 'misplaced view' and 'missing constraints'.
I am aligning buttons in 2 rows and 3 columns in the collection view in portrait mode and want to align all the 6 in single row in landscape mode, so if i pin the height here.
The problem is it will go good for portrait mode but in landscape the height will seem higher. Any help on how this could be achieved.?
You got errors because you did not added the constraint for the collection view top layout or height or aspect ratio. it is necessary to assign all side constraint so the view will automatically layout according to the constraint. if you miss one it will give you error or warning. Look you want dynamic height for collection view. If you want to achieve this for all the devices like for all iphones then you need to pin the height and make a outlet of the height constraint and change it in your viewDidLayoutSubviews method. select the collection view then go to size inspector and double click the height constraint. this will show you the constraint on the document outline. make outlet of that and change that constraint according to your need like on portrait or landscape you can calculate with logic. you might need to change the constraint according to the orientation change. follow https://stackoverflow.com/a/24072010/4030971
i know that will be great if all those stuff work only with some constraint but i found this way easier for me.

UIScrollView content size fixed to 600x600(Main.storyboard size)

I've been facing this issue from past 2 weeks and not yet got a solution.
I'm using UIScrollview in my application where the problem exists.
Generally in my app, there is dynamic text and images with different sizes will come from webservices. For example, imagine the Facebook Newsfeed. My application is similar to the Facebook newsfeed. Sometimes, there will be only text, sometimes there will be text and images. And comments for that post.
As i've seen in many links, the heirrarchy i'm following is SuperView-->UIScrollView-->Content View and the elements are placed in that content view. I'm assigning the constraints from the elements in the contentview to the Superview (ContentView --- constraints -- SuperView). When the content in the view exceeds the size of the superview, it has to scroll. But the scrollview content size is limited to the size of 600x600 i.e., in main.storyboard, when we design for W any x H any size. I've seen many tutorials and searched many sites. But following them gives me no luck.
Any help is appreciable.
Here is how to set up a scrollView in Interface Builder from scratch that works with Auto Layout.
Start with a new ViewController. Drag out a scrollView such that it fills the view. Untick Constrain to margins and constrain the left, top, right, and bottom edges of this scrollView to the left, top, right, and bottom of its superview with offsets of 0. This allows the scollView to fill the screen on any device in any orientation. You can make your scrollView take up less of the screen if you like, just make sure it is fully contrained.
Add a view to your scrollView. This should be the only top level view on your scrollView and it will serve as your contentView.
Constrain the left, top, right, and bottom edges of this contentView to the left, top, right, and bottom of the scrollView with offsets of 0. At this point, you will see warnings about ambiguous content size. That is because you haven't told it yet how big your content view will be.
To size the contentView, add width and height constraints to the contentView. If you want it to scroll, the width and height must be larger than the width and height of the scrollView itself. If you only want to scroll vertically, set the width of the contentView to be equal to the width of the scrollView. To do this, in the Document Outline view, control-drag from the contentView to the scrollView and select Equal Widths from the pop up.
If you want to be able to change the height of your contentView from code (to account for dynamic content), first create a height constraint for your contentView by control-dragging within the contentView and selecting Height from the pop up. Create an IBOutlet to the height constraint by control-dragging from the height constraint (found in the Document Outline view) to your ViewController's code. Give the outlet a name like scrollViewHeight then set the height with a value like scrollViewHeight.constant = 2000 when you need to change the scrollView's height.
Simply add your UIScrollView to your UIViewController's view in the storyboard and add the appropriate constraints in the interface builder.
Then, build your content view in the code and give it any frame you want, now start adding your controls to this content view and calculate the size of each one (especially the height), and at the end you have the total height of your controls.
Now set the frame of the content view to match that height and add it as a sub view to your scroll view, then set the content size in the code like this:
_scrollView.contentSize = contentView.frame.size;
Another note, do this changes to the sizes in the viewDidLayoutSubviews to avoid any problems with different screen sizes but be careful, this event is called many times so have a BOOL or something to ensure that the code that creates the view and add it to the scroll view is executed once, e.g. like this
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
if (! built) {
// Do everything I explained above here
built = YES;
[self.view layoutSubviews];
}
}

Auto layout constraints - Vertical spacing with one item of variable height

I have 2 UILabels above 2 UITextFields.
I would like the first UITextField to expand when the screen size allows it.
I set vertical spacings between each elements, and fixed height constraint for the UITextField at the bottom and a >= height constraint for the first one.
Below is a screenshot with what it looks like with the retina 3.5 form factor (<= iPhone 4).
But, it just doesn't work. Below is a screenshot of the storyboard with the retina 4 form factor (>= iPhone 5). The first UITextField overlaps the second one.
What constraints should I set ?
If i had it in front of me I'd play around with the compression resistance properties, which would be more elegant than fixed heights... however....a crude way of doing it that would work is:
You could have fixed height labels.
Fixed height bottom text view.
Pin the top text view to the bottom of the label. Pin the top label to the top of view.
Pin the bottom text view to the bottom of the view, pin it's label above it.
Pin the bottom of the top text view to the label below it.
The orange (-78) is Xcode's way of telling you you have a conflict between the frames of your layout and the autolayout constraints. Try looking at the storyboard warnings and fix the frame or fix the layout constraint.

Resources