How can I add space above and below an ImageView in a row in a TableView? - alignment

The row height in this table view is 54. The ImageView Height is 44. I'd like 5 above and below the ImageView (some spacing the image so that they aren't touching each other). Basically, centering the ImageView, vertically, in the row (or ContentView). No matter what I've tried, the image is always anchored in the top left corner of the row (since its a music app, it has to run on a phone, so I don't have an image for the result). I'm embarrassed to say that I've spent hours trying to accomplish this. I'd appreciate any help. Thanks.

If I were you, this is how I would set up my constraints. First, I would set the width constraint on the image view to be 44. [Note: I set my row height to be 54 just like yours.] Then I would set the aspect ratio constraint on the image view to be 1:1 (assuming you want a square image). Then, I would put the image view and the label to be in a horizontal stack view. If you bundle everything up in a stack view, I find that you have to worry about less constraints (the stack view will take care of the spacing between the image view and label although you can adjust accordingly if needed). Then I would add leading and trailing constraints to the stack view. And then finally, center the stack view vertically in the container.
Hope this helped. Good luck!

I was right, there was another place that was forcing the image into the top left corner. It was in the code when setting the contents of a row as shown below. I wrote that part a long time ago when I knew even less about Swift (the goal was to make sure the image gets scaled. It may not be necessary though. I'll test the code without it. Still, thank you Zaya for taking the time to help!
let albumArtwork = rowItem.representativeItem?.artwork
let tableImageSize = CGSize(width: 10, height: 10) // This doesn't matter, it gets resized below
let cellImage: UIImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 44, height: 44)) // The albumImageView is 44 by 44

Related

Design UIView so that it can dynamically change its height based on the content height

In a XIB file I have a CustomView related to a class with the same name.
The view content is quite simple.
There are a vertical stackview and inside the stackview there are two labels. The stackview is vertically aligned to the view that contains it:
The first label (title) contains a static text (always a few characters).
The second label (subtitle) can have variable length text.
I add this CustomView with other similar views as a subview of a Content View, as it was a “row”.
for i in 0...aViews.count {
var v = CustomView(frame: CGRect(x: 0, y: _y, width: 320, height: 100))
v.labelText = "my long label text ..."
contentView.addSubview(v)
// ...
}
As you can imagine, the title label should have a fixed position (top and left), that is, there cannot be a row with the title starting at 10 points and another at 14.
I must admit I naively thought the position of the label would have been automatically managed by the same fact that I aligned vertically the stackview. I was wrong and I noticed no problem at all, until they told me the second label, the subtitle, could contain more than one line.
I added lines to the label directly in the storyboard, and found out that:
the container of the stackview doesn’t change its height based on the height of its content;
the position of the “fixed” elements is maybe vertically centered but not fixed;
What I need is the following:
the labels should be “grouped” and aligned vertically: there should be the same amount of space from the top of the first label to the upper border of the container and from the bottom of the second label to the bottom border;
when the second label has to display more than one line, the container view should change its height accordingly;
Is this possible? How should I design my view?
OK - looking at your project, you're not far off... just a couple key items.
In your CustomView.xib, you had no constraint between Fixed Label and Date Label. The result is that the Date Label grows up from the bottom of the view, with nothing to stop it.
Also in your CustomView.xib, you had the Fixed Label constrained to the trailing edge... I assume you want it left-aligned with Date Label
When creating your CustomViews, you were setting a height constraint of 100 -- which defeats the purpose of allowing the content to determine the size.
In CustomView class, you had contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight] commented out. That line should be there.
In your view controller, you added a height constraint to contentView with a low priority. Best option is to make that a Placeholder constraint (double-click the constraint, and select the Placeholder checkbox). That way the constraint is removed at run-time, but is there during design (and Storyboard doesn't complain).
You were doing a few other un-necessary things - likely you were trying different stuff to get it to work.
The view setup (adding your views) is best done in viewDidLoad() -- definitely not in viewDidLayoutSubviews()
I'm guessing that, in your CustomView, instead of an explicit width of 200 you probably want to constrain the Date Label leading and trailing, allowing it to horizontally stretch based on the device width... but I left it at 200.
If you can follow that information, you should be able to fix the issue(s). But, I put the project up as a GitHub repo for you, so you can get it in a "working" state, and so you can see the changes.
Here's the link to the repo: https://github.com/DonMag/ATester2
Here is the result:
And scrolled up a bit:
I think you are mixing absolute positioning of outer views (i.e. manually setting frames) and using autolayout constraints for their inner components, and wrongly expect the dynamic autolayout part to somehow "reach all the way up" to the outer views. For autolayout to do that, you'll need to use autolayout all the way up, including the way CustomViews are positioned in your contentView.
If for whatever reason you do not want to use a TableView or CollectionView for this you could also, for example, try adding your CustomViews as arranged subviews to a vertical stackview that has top/bottom/leading/trailing constraints to contentView, then replace the "Align Center Y" constraint of your CustomView with "Align Top" and "Align Bottom" constraints to actually allow your labels to "push" from the inside if they need more vertical space.
Edit here's a quick sketch to illustrate that setup:
Edit 2 here are a couple of screenshots to clarify further. With a basic layout like this:
the result will look like this at runtime:
Note that the UIStackViews use the "Equal Spacing" Distribution in this example. If you want to create and add your CustomViews programmatically, use the StackView's func addArrangedSubview(_ view: UIView).
Good luck!

Why do my controls get squished inside a scroll view?

I'm building an iOS app and every time I use a scroll view and put other views and controls inside of it this happens:
How do I prevent this from happening? I tried putting the scroll view in a UIView and putting a UIView inside a scroll view and putting other controls inside of the nested views but the same thing still happens. Any ideas on how to fix this?
After you add something inside scrollView, it doesn't know what width and height it will have. Thus, it is unable to correctly display its subviews.
There are some major solutions:
You need to specify correct sizes AND distances both vertically and horizontally.
E.g. scrollView will have 1 label. Then you should specify something like this:
label 1:
leading = 20, trailing = 20, width = 100 (this will solve horizontal dimension)
top = 20, height = 100, bottom = 20 (this will solve vertical dimension)
Of course, labels are self-sizing. So if you specify the text/font/number of lines, you don't need to set fixed width and height.
You can add some view (if your layout allows that) which will take the whole width of the screen. In this case you set leading and trailing to 0, and instead of setting fixed width (which varies on different screen sizes), you need to center that view horizontally inside the scrollView.
This will solve the horizontal dimension.
Instead of using constraints use the autoresizing feature. The controls resize depending on the way they were placed on screen and what the settings on the Autoresizing is.
Autoresizing

Scroll view white space in the bottom ios

Hello i am working on the scrollview followed many tutorials found on stack overflow and youtube but facing same problem in the all tutorials , i want that if there is no content in the bottom there should be no white space whatever the view size is, in this pic you can see there is no content in the bottom many so much white space there are two labels in this image one is on footer and second is in the center i want that if there is nothing after the center there should be no more scrollview how to rid of this please guide me
this is my storyboard
Firstly, The problem is that if you want to the scrollview to be just the size of the content you have then you need to have to set
scrollView.ContentSize = CGSize(width: view.frame.width, height: view.frame.height)
If the problem is not solved with this then you have to check your constraint that must be incorrect.
Also to get the correct height you must have added bottom constraint to last element i.e footer i.e footer.bottom = safeArea.bottom (in storyboard inspector)
Hope this solves your problem.

UIScrollView with Autolayout Ambigous height

I've read a lot of manuals/tutorials on ScrollViews with vertical scrolling, but havent figured out how to solve my problem so far.
You can see my ScrollView visual plan here:
ScrollView plan
The most helpful answer was here, on StackOverflow:
https://stackoverflow.com/a/30282707/3718319
Accodring to it, I made the following:
My ScrollView(makred red on my screenshot) has got 0,0,0,0 constraints and equal width to ViewController's view. Inside my ScrollView I made a ContentView(makred orange on my screenshot), that contains (makred green on my screenshot):
1) ImageView with constant height and pinned top/left/right to ContentView.
2) View with constant height and pinned top to ImageView, left/right to ContentView.
3) View with constant height and pinned top to the View above it, left/right to ContentView.
4) TextView pinned top to the View above it, left/right to the ContentView and pinned bottom to the ContentView.
So, all the vertical constraints are set, and my scrollable content height should change according to height of text view. That's what is my goal.
But I got error from storyboard, telling: Need constraints for: Y position or height.
Could you please help me solve this problem?
Thanks!
The reason storyboard throws those warning is because it cannot calculate the scroll view's content size. With your first set of constraint in content view, it has an ambiguous height.
lets say for example that you set each height constraint to 100 and pinned constraint have 20 space value, the frame for each subview inside content view would be like this:
ImageView (20, 20, view.Width, 100)
View (20, 140, view.Width, 100)
View (20, 260, view.Width, 100)
TextView (20, 380, view.Width, ??)
since your textView have top and bottom constraint, the height of it will vary, and content view's height will also vary according to textView height.
However, textView also have scroll feature, which will make it difficult to calculate its height related to content view without additional constraint.
Since you disable its scroll function inside textView, storyboard no longer have any difficulty calculating each subview frame which is why the warning is gone.
optionally, you can enable textView's scroll function and giving height constraint to it which will give enough info for storyboard to calculate each subview frame.
I've just figured out, that I had to uncheck "Enable scrolling" on my textfield. That makes sense.
I've already tried it before, but it didn't help me before I've made this storyboard ViewController from a scratch.

How to use Xcode auto layout with these Uiimage View?

I'm trying to use auto layout,to make these UiImages views like in the image below, but its always in a mess in one of these devices screens 3.5", 4", 4.7"
so what I have to do to make it like this ?
If you want equal width and equal height of each image then you can add the constraints as shown in below image and if you want to use whole screen space (i.e. height and width of image will be different) then select all the four pins and select Equal Widths and Equal Heights check box (keep Aspect Ration check box unselected)
I think you are missing some constrains, you can do step by step.
Lets number the imageview for easy reference
imgv1 imgv2 imgv3
imgv4 imgv5 imgv6
imgv7 imgv8 imgv9
imgv10 imgv11 imgv12
Drap and drop imgv1, 2 , 3 to the storyboard and place them adjacent to each other. cmd+right click on the three imageview and set constrains(it should be to the nearest neighbour do not forget to untick the checkbox for "from margin"). Based on the figure in the question constrains should be
top - 40, left - 20, right - 20. I am assuming that all imageview are of equal height and equal width, in that case select the three imageview and select equal width and equal height constrain. Dont update the frames yet. It will show error dont worry we will solve it.
Now for 2nd, 3rd, 4th row.
Drag and drop the imageview to storyboard and place them as you want ie.
imgv4,5,6
imgv7,8,9
imgv10,11,12
then select all these imageview(4-12) and add constrains to it. The constrains should be
top - 20, left - 20, right - 20
and as all the image view are equal in height and width, select all the imageview that is imgv(4-12) and imgv(1,2,3) and add the constrain equal height and width.
There is one more thing missing that is we have to add bottom constrain to the last row ie.(imgv10,11,12) for that select these three imageview and add bottom constrain(remember all constrains are from the nearest neighbor).
Then at last update the frames in the controller. It should look like the image in the question.

Resources