Dynamic height UITextView inside scrollView - ios

I'm working on a detail view for my app that lets people discover movies. I set up my detail view in interface builder by first adding a contentView to which I added my other views. I understand from previous topics that the contentView should dictate the contentSize of the scrollView. I also understand that the views inside the contentView should have auto layout constraints that enable the contentView to calculate its full size (in my case the height). I haven't been able to get this to work perfectly. I suspect that this is because I have a textview that displays the movie description and because some of these are long and some are short I don't know how to set its size. I want the textView to display the full text and I want to disable scrolling. In the current situation when the text is long the labels or the buttons get compressed. When I add height constraints to the labels and other views the textview gets compressed. Could anyone guide me in the correct direction/ let me know what I'm doing wrong?
This is how I set up the view hierarchy:
UIScrollView
UIView (trailing, leading, top & bottom = 0, centerY & centerX)
UIImageView (trailing, leading, top to contentView = 0, aspectRatio)
UILabel (centerX, top to ImageView & bottom to label = standard)
UILabel (centerX, top to label & bottom to label = standard)
UILabel (centerX, top to label & bottom to label = standard)
UILabel (centerX, top to label & bottom to textView = standard)
UITextView (leading, trailing & bottom horizontalScroller = standard)
HorizontalImageScroller (leading, trailing & bottom to UIButtons = standard , Height of contentView == height of scroller to disable vertical scrolling)
UIButton (leading, bottom to contentView = standard)
UIButton (leading, bottom to contentView = standard)
Solution:
Instead of a textView I used a UILabel with number of lines set to 0 and line breaks set to word wrap. After that I still didn't get the results that I was looking for. Then I had to change some auto layout constraints after which it finally worked.
The following articles where helpful to me while solving this issue:
Article about content sizing priorities
Article about Debugging AutoLayout

Related

UITextView inside UIScrollView does not display long text

I have a UITextView inside a UIScrollView. if I try to display a long text with a certain font size, the text is not showing. With shorter text or decreasing the font size the text shows up again. What am I doing wrong?
Screenshot of the autolayout here (the item selected is the textview):
The UITextView is inherited from UIScrollView
open class UITextView : UIScrollView, UITextInput, UIContentSizeCategoryAdjusting
So it is a bad practice to put ScrollView inside scrollView.
The reason why you don't see a long text in UITextView is that UITextView became scrollable. Also you didn't specify your scrollView content width so the with is calculated is as one line of your long text. But you can scroll it because you will scroll scrollView. Better way is to set label inside scrollview and set the label numberOfLines = 0. Make the label bottom padding to the bottom of your scrollView and top to some items in top of label and you will get a scrollable text.
I've just understood that you don't need a scrollView to place your long text.
You can use just a UITextView for your needs.
Remove your scrollView.
Add a UITextView.
Set constraints as described and math them with screenshot
Top Space to ReadingTimeLabel
Align Bottom to Superview / Bottom Layout Guide
Leading space to Superview
Trailing space to Superview
And you will get the result like on the screenshots
Scroller top:
Scrolled bottom:
Note: You can disable UITextView editing in attribute inspector.
But if you for some reason need a scroll view:
Set constrains as described, also match them as shown on screenshots.
Add scrollView constraints (Superview is the view where the scrollView is placed in):
-Top space to ReadingTimeLabel
-Align bottom to Superview/Bottom Layout Guide
-Align leading to Superview
-Align trailing to Superview
Please a UIView inside scrollView. Use it as container.
Add constraints for container. (Superview is scrollView)
-Align Leading to Superview
-Align Trailing to Superview
-Top Space to SuperView
-Bottom Space to SuperView
-Equal Width to SuperView
Add a UILabel inside container. (Superview is container).
Add constraints for UILabel.
-Align Leading to Superview
-Align Trailing to Superview
-Top Space to SuperView
-Bottom Space to SuperView
For the label set Lines = 0 in Attribute inspector or use the code
label.numberOfLines = 0
And you will get the result like on screenshots
Scrolled top
Scroller bottom
Try the below code:
textView.sizeToFit()

Setting top constraint on UIImageView causes UILabel to be fixed height

I'm having this weird issue with my constraints which causes the UILabel (Caption Label) to be a fixed height instead of dynamically changing height depending on the text.
I have a view (Vertical View) with a top constraint on the label above it. The Vertical View contains a view (called View) which I'm using as a divider that is centered from top to bottom with a width of 1. On the left of the divider is a UIImageView (Left Image View) with constraints leading, top, bottom equal to superview and trailing equal to View. I want to do the exact same thing to the UIImageView on the right of the divider but here is where my issue comes up.
If I use a fixed height as seen below, the UILabel above Vertical View dynamically changes its height like I want but this is obviously not how I want the UIImageView on the right to appear. I want it to be similar to the UIImageView on the left of the divider with equal height and width.
If I set the top constraint of the UIImageView on the right to the superview Vertical View, similar to the UIImageView on the left of the divider, the UILabel above Vertical View doesn't dynamically change height anymore. The UILabel now has a fixed height which I believe comes from the fact that UILabel has a height of >= 14.
How can I properly set the constraints so that I can have both UIImageViews next to each other with equal and height contained within the Vertical View and still have the UILabel above Vertical View dynamically change height depending on the text that I set the UILabel to?
On the RightImageView, you first need to get rid of the "Height = 50" constraint. This is what is causing it to be small.
Next, if that alone doesn't fix you, can you try setting the following constraints instead of using the superview for the constrains (instead make it mirror the LeftImageView):
Left: Leading spacing to divider view
Top: Align top edges to LeftImageView
Right: Horizontal space to superview (your vertical container view)
Bottom: Align bottom edges to LeftImageView
This should allow the views to remain the same height and width (assuming your distances between left/right edge of vertical container view are the same, and the distances between divider are the same).
Now, ensure the size constraint for width of the divider is set to 1 and not >= 1. Also, ensure the vertical container view has a Compression lower than the Label.
One final note--your screenshot shows the result that IB is showing you (with the dotted yellow box) on the LeftImageView. One you update your constraints correctly, this yellow box should go away.
Regarding the UILabel - if you want this to grow dynamically, you need to do the following:
myUILabel.numberOfLines = 0;
myUILabel.text = #"Enter large amount of text here";
[myUILabel sizeToFit];

ScrollView not resizing properly

I have a ScrollView embedded in my ViewController. Inside the ScrollView I have embedded a content view (UIView) which has a UIImage set to match the left, top and right of the ScrollView with a dynamic height that changes depending on the aspect ratio of an image that the user can load after the ViewController loads. There are three buttons all horizontally aligned in the content view and spaced evenly apart from each other.
When the user loads in a photo that is too big for the screen it should just resize the ScrollView and the content view appropriately to allow scrolling to see the buttons but instead it just bunches up the buttons at the bottom of the screen.
Here is how the buttons should look:
Here is what happens when the photo is too big:
Here are the constraints of the ScrollView:
Here is my resizing code:
let img : UIImage = info[UIImagePickerControllerOriginalImage] as! UIImage
let screenSize: CGRect = UIScreen.mainScreen().bounds
let multiplyNum = screenSize.width / img.size.width
imageViewHeightConstraint.constant = (multiplyNum*img.size.height)
imageView.image = img
Even when I try and change the ScrollViews height programatically to a very large number it still won't get any larger than the ViewController (no scrolling).
Constraints of ContentView:
Constraint of ImageView:
Constraints of first 2 buttons:
Constraints of last button:
Make sure to set all the constraints that completely define the vertical layout of all elements (top constraint for image, vertical space between elements and bottom constraint of last element), and try changing the priority of the content hugging or compression resistance of the elements.
Edit:
You can achieve that behaviour with this view hierarchy:
- UIView
- UIScrollView
- UIImage
- UIButton
- UIButton
- UIButton
There is no necessity to add a container view if you set the constraints like this:
scrollView:
Leading, trailing, top and bottom constraints to view (all 0)
inner views (horizontal):
Leading constraint from imageView to scrollView
Trailing constraint from imageView to scrollView
Equal width from imageView to view
inner views (vertical):
Top constraint from imageView to scrollView
Height constraint of imageView (this constraint constant will change depending on the size of the image)
Horizontal space from imageView to button1
Horizontal space from button1 to button2
Horizontal space from button2 to button3
Bottom constraint from button3 to scrollView
There is no necessity to change the priority of the content hugging or compression resistance of the elements.
I already check that it works in a project.

iOS UIView size

I have a Controller with 4UILabels that are constant height throught all the iPhones, below the lastUILabel there is aUIView with a page controller(with aTableView inside that page controller).
What I want is that theUIView take all the height that he cant :
example: Screen of 600 height
4UILABELS = 200 height
TableView = it should get 400 height
Screen of 800 height
4UILABELS = 200 height
TableView = it should get 600 height
I need 1 constraint more to set the height of the view,What I have defined is :
EqualWidth constraints to superView
LeadingSpace to SuperView
Top Space to super VIew
The following constraints should align everything for you so that the UILabels stack vertically, each have height 50, and stretch to the edges. The UIView will take up the remaining space regardless of the screen size.
All UILabels
Pin leading edge to superview
Pin trailing edge to superview
Add height constraint set to 50.0
UILabel 1:
Pin top edge to superview top
UILabel 2:
Pin top edge to UILabel 1 bottom
UILabel 3:
Pin top edge to UILabel 2 bottom
UILabel 4:
Pin top edge to UILabel 3 bottom
UIView
Pin leading edge to superview
Pin trailing edge to superview
Pin top edge to UILabel 4 bottom
Pin bottom edge to superview
UITableView
Pin leading, trailing, top and bottom to its container view so it fills the area.
I assume that you are creating this UIViewController in a Storyboard.
You should be able to put all the labels in a container view which you give the constant height of 200 points, as you specified. Make a vertical constraint from "Top layout Guide" to said container view, maybe with the value 0. Drag an UITableView and place it below the container view. Dont give it any constraint regarding height. Make a vertical spacing between the (bottom of) container view and the (top of the) UITableView with value 0 and a vertical spacing between the (bottom of the) UITableView and the Bottom Layout Guide with value 0.
So it will be (V:0 means vertical spacing, constant 0):
Top Layout Guide
V:0
Container View - Height: 200
V:0
TableView (dynamic height)
V:0
Bottom Layout Guide
This should work.
(And then of course you need to create constraints regarding width and also internal constraints for each UILabel inside the container view. Let me know if you need help with that.)

How to make uiscrollview only vertical scrolling for ios?

I'm trying to make layout inside scrollview using this one tutorial link
And get the following result link
It will be appreciated for any advices or tutorial links. It needs only vertical scrolling
I am sure there must be other ways to do this but a quick fix is :
1.) Create a width constraint on ContentView in Storyborad.
2.) IBOutlet that widthContraint and set its value to the view frame width in viewDidLoad.
Suppose the name of the constraint outlet is contentViewWidthContraint.
contentViewWidthContraint.constant = self.view.bounds.size.width;
Another alternative to do so from Storyboard, is to fix the Contentview width to the view's width from the storyboard or to the Scrollview, if Scrollview already has a Equal width contraint with superview . Add the "Equal Width" contraint from Contentview to either self.view or to Scrollview (if scrollview, already has the width contraint)
Have you set up the "ContentView" width to match with the scroll view width? I had the same problem and I fixed with "Equal Widths".
"Equal Widths" will tell to your "ContentView" to use the same width of the "Scroll View", which should be fitting the screen if you have set up the constrain properly.
You can do this easily on the storyboard.
Drag and drop, with right click (important!!!), from "ContentView" to "ScrollView"
Release the click, you will be prompted with a menu, select "Equal Widths".
This should fix your problem using the scrollview with AutoLayout from Storyboard editor.
You can find a full tutorial how to use ScrollView with Autolayout and Storyboard here.
I hope this is useful for you :)
In the Storyboard set the width of the elements contained in your UIScrollView equal to the width of this UIScrollView (by selecting all elements and the UIScrollView holding in the panel on the left of your Storyboard and then setting the 'Equal Widths' constraint under 'Pin' on the bottom of your Storyboard). Just pinning the right sides of the elements to that of the UIScrollView won't work as it will adjust the size of its "display view" to the width of the largest element and if this is smaller than the width of the UIScrollView all elements will just appear aligned to its left side.
There is also another possibility that offers a very good result.
You can mark a checkbox:
O programmatically:
scrollView.alwaysBounceVertical = true
Try to set it's width to 0 & height equal to content size like this:
self.scrollView.contentSize = CGSizeMake(0, self.scrollView.contentSize.height);
This will work as you want. Try it & tell if still facing any issue.
For disabling the horizontal scroll, you can set the content size in the -(void)scrollViewDidScroll method.
[self.scrollView setContentOffset: CGPointMake(0, self.scrollView.contentOffset.y)];
self.scrollView.directionalLockEnabled = YES;
This is because scroll view have no idea where your content should end.
But when at least one item inside your scroll view has its "trailing space" constraint attached to a view outside the scroll view (usually a view the scroll view is sitting in or some other view of a higher level, which "knows" its width) - the scroll view will automatically get an idea about your wanted width and won't scroll horizontally (unless that trailing constraint implies having your content outside the screen).
Better if all items inside scroll view have their "trailing space" constraints connected either to each other or to a view outside the scroll view. But not the scroll view itself.
No additional code or extra constraints needed for this to work.
Too set UIScrollView constraints as like below code so it will occupied whole screen.Not exceed the screen size.
Leading Space = 0 from mainView
Top Space = 0 from mainView
Bottom Space = 0 from mainView
Trailing Space = 0 from mainView
You need to set the width of UIScrollView equal to or less than the width of your Parent View. Two ways to do it:
1) You can do this in Storyboard via layout constraints
2) You can do this programatically:
self.scrollView.contentSize = CGSizeMake(self.view.frame.size.width, self.scrollView.contentSize.height);

Resources