After an extended amount of time searching for an answer and fidgeting within my project, I have decided to come here.
The issue: I have created a UITableView in which the cells expand when a user taps on them. This part is perfect, however, I can not seem to get either the constraints or heights correct. The cells are each 1/3 of the TOTAL screen (including status & navigation bar) before they are tapped, and then they expand to be 1.75 times that size. Originally there is just a UIImageView that takes up the unrevealed cell and once it is taped it is supposed to reveal a UIScrollView (of which contains static data.) However, I can not seem to get this to happen, when I add constrains I either get overlapping ImageViews that opens to a part of the ScrollView, squished images, or a properly working expanding cell but once the cell opens the image expands with it (which I do not mind) but the ScrollView is not there.
I have attached a screenshot of a reconstruction of the interface builder. The UIImageView is set to 300, the ScrollView to 215. Screenshot of Interface
Try to check content hugging priority and content compression resistance priority of your image view and scrollView.
func checkHeight() {
levelsView.hidden = (frame.size.height < P1Cell.expandedHeight)}
you should check this return no or yes,
and how about change frame to bounds.
Related
I have a TableViewController and custom cell. Inside of the cell i have an ImageView. Xcode 9.4
*I do not have enough reputation - so provide links.
Click for image
I have constraints settled to superview Leading-Trailing: 20, Top-Bottom:10, clip to bound enabled, Scale to fill.
When i launch application, i oversee this:
Click for image
Image shrinks down. If i change to Aspect Fit/Aspect Fill the image becomes smaller(image view is not filled) or zoomed(not all image is available).
How to fix this issue? I do not want to give it specific width/heigh for compatibility.
Maybe i should change my constraints? I have watched several tutorials, where these constraints work, even did step by step, however it does not work as supposed to.
All constraints are settled for ImageView to superView (that is cell itself).
Thanks.
Set estimated height for your cell self.tableView.estimatedRowHeight = CGFloat(44) and also tableView.rowHeight = UITableViewAutomaticDimension so that it will grow according to your content inside. the problem here is with your image your cell getting height from your image you provided if you give fix height for your image your problem would be solved.
to adapt height for imageView according to iPhone and iPad.
First way is to get superView height and give your image height according to that programmatically.
Second you can get current device type and give your image you height to that UIDevice.current.userInterfaceIdiom == .pad. you can't do it in storyboard because you don't have access to superView in custom cell.
The layers: UITableViewCell -> UIStackView -> UILabel, table height is set to automatic dimension.
Run it, everything is fine
After some scrolling, the bottom of the multiline label gets cut off
UILabel and stack view settings:
lay out constraints for the stack view:
I've tried to set the line break to word wrap, call sizeToFit on the label, neither of them works for me. Any clues?
Since the problem occurs because of scrolling, this seems to be the problem related to TableView reusing the cells on scrolling. Hence reset all the values of cell that you are using (which includes dimensions as well if any). On scrolling, the current cell content gets displayed in some other cell which is being reused.
One way I have solve that kind of problems in the past is to put the UILabel inside a UIView as a container view. Then put this container inside the UIStackView instead of putting the label directly in the stack view.
You can also try to play around with compression resistance priority because the label seems to be shrinking because its compression resistance is not high enough.
I've designed a ViewController with an ImageView, 3 Label-TextField combination, one single Label and one Toolbar at the bottom of the view. All of these view elements are inside a Stack View. The design is like below:
The contentMode property of the ImageView is set to Aspect Fit in the Attributes Inspector.
Now when I run the app and select different size of photos, the ImageView seems to be inconsistent different times. Like:
The teal color background the ImageView is set to distinguish the difference between the ImageView and the original Background.
This is okay. But when I choose a large size photo it seems to be inconsistent as the ImageView is overlapping the Toolbar below and this time the Camera button is no more clickable. Here is the image:
And the design gets more broken when I choose another photo. The view is showing up differently in different times. Screenshots are: and
Now what to do? I haven't done any of these design from the code side, all from the Interface Builder.
Any help will be appreciable.
I have these options in the Drawing section of Attributes Inspector:
And this is my Stack View's attributes:
Well it seems everything is fine. Just add height constraint in your Toolbar. The problem will be fixed.
First, make sure you've checked Clip To Bounds property of UIImageView in Attributes Inspector.
Second, set your constraints and / or Stack View's Distribution property in such way that all your views fits within available height.
Here's a sample: https://www.dropbox.com/s/5a7r0oz1v8vclgz/AspectFitImageView.zip?dl=0
By searching a lot of ways around, I finally was able to sort out the issue. Setting the content hugging priority(don't want to grow) and content compression resistance priority(don't want to shrink) helps a lot. Basically I needed to adjust the elements vertically. So tuning the vertical priorities for each element solved my problem. As I have to keep the size of the ImageView to be changed from time to time I've made it's vertical hugging and compression to lower than the other elements of the Stack View. Other priorities are kept as they were by default.
To visualise the situation, here is attached images. Color combinations are used here to distinguish among the elements of the Stack View.
Hope this helps.
I have a simple screen, with a slider and a label positioned next to each other horizontally. I have embedded these inside a UIScrollView (I set this to fill the screen and used 'Add missing constraints'), because I will need vertical scrolling later down the line. I don't however, want horizontal scrolling. I have seen numerous posts on here and other sources about people wanting to disable horizontal scrolling, however I'm not sure that's what I want to do, I think I need to restrict the UISlider from causing the horizontal scrolling; I think it is trying to take up more width than the screen. I have added what I think are the necessary horizontal constraints:
Leading space to container for the UISlider
Horizontal spacing to the UILabel, and
Trailing space to container for the UILabel
But this still causes horizontal scrolling, and the UISlider's are the cause, they are taking up more room than I want, as seen below:
I have tried disabling horizontal scrolling in the code using a few techniques, one being:
func scrollViewDidScroll(scrollView: UIScrollView) {
if scrollView.contentOffset.x>0 {
scrollView.contentOffset.x = 0
}
}
but this does not seem to stop the horizontal scrolling.
Can anyone offer any suggestions?
Thanks in advance.
My suggestion is to never use Add missing constraints. It never does what you really want.
Here's the problem. You are laying out your UI on a ViewController in the Storyboard that is square. Apple did this to remind you that you need to be flexible in your design, but it doesn't match the size of any device. When you Add missing constraints, it uses the absolute dimensions of that square to create the constraints which are certainly wrong.
In your specific case, it is giving the slider a width that is too wide, which is why the slider goes off the right side of your screen.
Here's the trick about scroll views. If the contents inside of a scroll view are wider than the scroll view itself, then that content will scroll. The same applies vertically: if the contents inside of a scroll view are taller than the scroll view, then the contents will scroll.
In order to design this to work on all phones, you need to make sure that the contents of the scroll view are laid out correctly for each phone size. Which certainly means you don't want to use specific widths for both the label and the slider because you'll end up with the wrong width for some device, if not all of them.
The best way to do this is to:
Drag out the scroll view and add it to your ViewController. Add constraints to make sure it is properly sized on all phones, such as attaching it on all sides to its superview with a fixed distance.
Drag out a new UIView and drop it on the scroll view. Drag its edges until it exactly matches the size of the scroll view. This will be your content view. Pin all four edges of this content view to the scroll view with offsets of 0.
Here's a tricky bit. Even though you've pinned the content view to the scroll view, its size of free to grow because that is what allows it to be bigger than the scroll view itself and allow there to be content to scroll over. To keep your scroll view from scrolling horizontally, you need to make sure the content view has the same width as the scroll view on all devices. To do that, find the scroll view and the content view in the Document Outline to the left of the Storyboard. Control-drag from the content view to the scroll view and select Equal Widths from the pop-up.
You still haven't told your content view how tall it should be. For now, give it an explicit height constraint of 1000. That will be enough to scroll.
Now, add your label and slider to the content view. In addition to constraining them to each other and to the edges of the content view, you will need to give your label a width constraint. Then Auto Layout will have all of the information it needs to compute the width of your slider. Auto Layout knows how wide the content view is (which will be different on different devices), it knows how wide your label is, and how far everything is from everything else, so it will just stretch the slider to fill in the rest.
If you do all of this, you will have a UI that is properly sized for all devices in all orientations that scrolls vertically.
Just embed all view in your UIScrollView in a UIView, give it the required constraints then the slider and label will stay.
That worked for me just now.
UIScrollView is special when you want use AutoLayout with it, subviews can not be added directly, it needs a container view to constraint the contentSize of UIScrollView, Auto Layout Guide:Working with Scroll Views explains the detail reason, and you can find many solutions to solve UIScrollView's auto layout on Google, Such as this answer.
To be honest, it's confused and complicated to understand UIScrollView's auto layout, but if you overcome this, others auto layout question is easy to resolve.
I have a layout as follows(Using AutoLayout,iPad):
The UIScrollView has Top,Bottom,Leading,Trailing space to the superview as 0. The UIView also has all four similar constraints. The second UILabel has its height set to 0 programmatically (since more than a screenful of text is shown here). Also, these four pin constraints have also been set up from the UIView to UIScrollView.
When the XIB is loaded, this UILabel shows long lines of text correctly. But scrolling does not work. This is a screenshot of the running app on an iPad:
The yellow background is set for the outermost view and the grey one for the UIView. If you see carefully at the end of the screenshot, the UILabel's text seems to overflow past the UIView.
I suspect that because the UIView cannot "capture" the size of it's subviews, the UIScrollView cannot calculate it's contentsize too(there's no reason for the scrollbar to work if its content view is only equal to one screen). Why is this happening even when the UILabel is clearly a subview of the UIView? If my suspicions are right, how do I set the UIView's height equal to the actual content size so that my UILabel is properly "contained" in it?
(Setting the UIView's height,width statically is not an option) .
NB: Tested the XIB without the UIView and only a single UILabel (with long text) inside a UIScrollView. Now scrolling works(since, I presume, the scroll view can calculate its content size).
NB2: I also tried the answers in this SO question and this post but my UIView simply wont extend beyond the dimensions of the screen. (I only care about horizontal scrolling)
AutoLayout issues are very hard to explain with text. I was having the same problem. I found the solution in this video. hope this will help you too.
https://www.youtube.com/watch?v=UnQsFlMGDsI
This video demonstrates how to create a UIScrollView which has some
views on the top of the screen and a view on the bottom of the screen
in Autolayout. UIScrollView content size is automatically adjusted to
the size of the screen or to the size of the content in such way that
on smaller devices scrolling is active and on larger devices scrolling
is not active because it is not needed. UIButton below UITextFields
always stays on the bottom of the screen and everything works on all
iPhone resolutions (iPhone 4 / 5 / 6 / 6 Plus).