After two days stuck on this problem I've very close to solving it. What's happening is I have a view that holds buttons/score/best score (labels and buttons). That view is centered horizontally, and it's near enough perfect--it's actually perfect on the iPhone 5 (as shown below).
As you can see from the screenshot I want the score/best score just under the stars, in the storyboard that's the case and on the iPhone 5 it works like that, yet on every other device it doesn't!
Constraints are the bain of my life, any help is greatly appreciated. I will legitimately PayPal you coffee money if you can help me with this.
Why is it that the iPhone 6 is different? I have a feeling it's because the screen size?
I've posted all my constraints and there's actually a lot...mostly auto-generated by Swift.
http://postimg.org/image/efwie4kxl/
Letting Xcode auto-generate those constraints is likely your problem - it'll end up doing whatever it thinks is best, though it is rarely correct. If the part that's bothering you is that you want the score/best score a certain distance from the stars you should be able to fix that by getting rid of the auto-generated constraints for score/best score, and add a new one that constrains the top of score to the bottom of the stars, and if you have an exact distance you want it to sit you can set the constant to that many points. Without getting into the storyboard and seeing the details of your constraints it's not possible to give you a more exact reason as to why it's not looking the way you want.
Try to use the multiplier instead of absolute constraints at the messed up constraints.
Xcode Example
Calculation : spacer.height = 0.1 x window.height
That way it won't mess up your layout. At least thats my experience.
For further information: Apple iOS Developer Library
Related
Looking for a clean solution to laying out UI programmatically and having it look right on every device. I've tried extending CGFloat to scale numbers depending on the device
extension CGFloat {
func scale() {
// Modifies self by multiplies by the ratio between the initial screen size and the desired screen size
}
}
// usage
view.widthAnchor.constraint(equalToConstant: 20.scale())
I've also tried just creating two different sets of constraints for iPhone and iPad and activating them depending on which device the app is being run on, but this seems unnecessarily verbose.
How can I layout my UI so that it will work on all devices without hacky workarounds. Are there certain types of constraints I should be avoiding? (for example, instead of setting width/height constants, set them to a multiple of the screen's (or some other view's) width/height?)
EDIT: I don't want to over-explain my own situation, so let me re-ask the question. What are some best practices for setting constraints in an application designed for both iPhone and iPad. Is it bad practice to just check if the device is an iPad, and if it is, have constraints just for iPad, and, if not, have constraints for just iPhone.
Your question, as-is, cannot be answered...
Wha does your app do? If it's a photo slide-show, constrain an imageView to the full view and set its content mode to scale-fit. Voila! It "looks good" on all devices!
If your app is more complex than that, you will likely need to make use of all the types of constraints: elements relative to each other; equal to each other; relative/equal with constant adjustments; relative/equal with multiplier adjustments; etc. And you may want different layouts (not just different sizing) based on device+orientation, in which case you'll also want to take advantage of size-class-variations.
In addition, getting an app to "look right on every device" involves much, much, MUCH more than applying constraints.
Should the app use a Tab Bar?
A Navigation Bar?
A combination of them?
Neither?
Should it use text-buttons or image-buttons?
Should it adjust for accessibility and dynamic fonts?
Might it even have different functionality when running on a small screen vs a large screen?
In general, your first step should be hand-drawing every screen and UI element you expect to have - including the activity "flow" - with variations for sizes and orientations, so you are designing the best UI/UX from the beginning. At that point, you begin actual UI construction.
Keep in mind, there are people who can't produce a "Hellow World" app but make a very good living as "App Designers."
Having said all that, though... one approach you almost certainly should not take is:
view.widthAnchor.constraint(equalToConstant: 20.scale())
EDIT
Here is a quick example - based on this article: https://www.raywenderlich.com/1343912-adaptive-layout-tutorial-in-ios-12-getting-started
A simple weather app - constraints set so it looks similar on all iPhone and iPad models:
But, what happens when you rotate the phone?
Little, tiny cloud doesn't look so good. Add trait-variations / size-classes, and we can get:
And, to try and answer your edited question of: "Is it bad practice to just check if the device is an iPad..."?
Yes. It's recommended to design for trait-variations / size-classes so your app will look the way you want in all configurations (hopefully future-proof for the next device that comes out as well).
Is it bad practice to just check if the device is an iPad, and if it
is, have constraints just for iPad, and, if not, have constraints for
just iPhone.
If you're planning for Split-View support, that is definitely a no-go. The code for achieving and handling this is always going to be slightly verbose. There are no one-liners here to achieve what you want.
In your -[UIViewController viewDidLoad] method, you'd want to setup your views with the base trait collection available to the controller's view. This is your starting point.
As and when your App's windows are resized by the OS (imagine going for a fullscreen app in landscape mode to a split-sized app, occupying one-third of the screen): the -[UIViewController traitCollectionDidChange:] method is called on your View Controller. This is where you update your layout constraints.
You can, and should, encapsulate your layout logic in a single method and call it from -[UIViewController viewDidLoad] as well as -[UIViewController traitCollectionDidChange:].
In such a method, I do not recommend checking if the host device is an iPad. You specifically want to look at the active trait collection's horizontalSizeClass & verticalSizeClass properties to determine the values for your layout constraints.
For further information, I suggest you go through the following documentation:
1. https://developer.apple.com/documentation/uikit/uitraitcollection?language=objc
2. https://developer.apple.com/documentation/uikit/uitraitenvironment/1623516-traitcollectiondidchange?language=objc
The 2nd link has a simple example on how to check if you need to update your constraints.
I usually first get the size of the screen and then use percentages of the width/height for the frames
height = view.bounds.height
width = view.bounds.width
mybutton.frame = CGRect(x: width * 0.05, y: height * 0.02, width: width * 0.3, height: height * 0.1)
I'm posting here because I'm completely lost on this one.
I've searched all over the web, tried a lot of things myself, and searched weeks on this bug, but I can't find it.
So ever since iOS 11 (doesn't happen on iOS 10), everytime I press a button that activates the "show" segue in a UINavigationController the animation shows some weird padding at the top.
This padding disappears when the animation is finished.
I've changed the backgroundcolor of the superview to a red color, and the space you can see is indeed from the superview itself, so my guess is the whole UITableView is being moved down for some reason, although I'm not sure what exactly is the cause here.
(I'm using storyboard and AutoLayout constraints)
Another thing I noticed is that the spacing/padding you see is different on the iPhone X compared to the other devices (my guess is that it's the same height as the (non)safe area at the top? Again, not sure.
I don't think code is necessary to be provided here, as I wouldn't really know which part causes this behaviour (and there's a lot of code that I can't share for reasons..).
Any suggestions/help on how to fix this would be deeply appreciated!
Here are some examples:
iPhone X running iOS 11.1 (also happened on 11.0)
iPhone 8 gif
EDIT: I should add, some things I already tried:
tableView.contentInsetAdjustmentBehavior = .never
Setting headerviews to 0
tableView.setContentOffset(0, animated: false)
Playing with the translucency settings of the UINavigationBar
AutomaticallyAdjustContentInsets is set to false
So, as suggested by Spenser-Arn, I played around with the constraints and the Safe Areas, turns out, the safe areas where the cause of the issue.
Hope this helps other people as much as it helped me, and a big thankyou to Spenser-Arn!
When my app launches, I see a white screen, instead of my launch image. I am using a storyboard, as required, and everything was working fine for about 2 months before this. I didn't change anything related to the image or storyboard either, it just started happening. I should mention that this started happening sometime after my first time uploading to TestFlight...but I doubt that is relevant. I have tried changing the constraints of the image to make it smaller than the bounds, and it still doesn't show up, so it isn't the size of the image. Again, I seemingly did nothing to have this start happening. Most of the questions related to my problem on stackoverflow have to do with the user not using a storyboard as required with iOS 9. Please help. Thanks.
UPDATE
I launched it on the simulator (iPad2) and the launch image for that was too small...there was white exposed above and to the right, I'm guessing I need to fix something in the storyboard but I'm not sure what.
UPDATE
I made a new storyboard and assigned the launch-screen config to it, and there is still a white screen.
I deleted the UIImageView and then inserted a new one with dimensions 200 x 200.
I added the image to the UIImageView.
I adjusted the constraints to the same values that I was using before.
Adding the image to the 200 x 200 UIImageView, before adding the constraints, seemed to be the key.
Make sure that one of the view controllers has the Is Initial View Controller checkbox checked in the Attributes Inspector in the right sidebar, that got me.
In project by default you LauchScreen.xib. Put your launch image there and set it’s top, bottom, leading, trailing constraints. Tap your project file and scroll down. There you will see: LauchScreen option and MainStoryboard. Set LauchScreen to your LauchScreen.xib. That’s it))
I have searched it out, but not gotten any fruitful answers. I want to set different constraints for all different screen size in a single storyboard itself (Not programmatically).
How can I resolve this?
Thanks in advance !!
Please see this useful link it helps you.
http://www.raywenderlich.com/83129/beginning-auto-layout-tutorial-swift-part-1
In this tutorial you can find "A quick note on Size Classes" section in that section you can find the solution of your problem :)
Also see following the tutorial for the constraints hope it will help you.
https://www.youtube.com/watch?v=G53PuA_TlXk
Without writing a single line!
No need to write device based conditions these :-
if device == iPhoneSE {
constant = 44
} else if device == iPhone6 {
constant = 52
}
I created a library Layout Helper so now you can update constraint for each device without writing a single line of code.
Step 1
Assign the NSLayoutHelper to your constraint
Step 2
Update the constraint for the device you want
Step 3
Run the app and see the MAGIC
I am new to IOS development. I am developing an app for IOS 8 devices. I used storyboard for my design yesterday my storyboard showing all UI design but today morning it show blank UIViewController no UI element vision please see in screen shot and very strange thing is that when i run my app all ui element visible in my device. I google but dont find any solution please help me out. Thank you in advance.
It looks to me like you are using size class and you went into a particular size class and added these views. Now you are back in Any size class, so the views are not there (that is why they are greyed out in the document outline at the left). They are available only for that particular size class. If you switch back to it again, whatever it was, you will see them again. Basically, you have created conditional views - the condition being that they are present only when that particular size class situation is the case.
In other words, if you want your layout to apply in the general case, you want to start by creating and editing it under Any size classes. Only then do you switch to a particular size class and modify the layout for that particular size class.
when i run my app all ui element visible in my device
Yes, because on your device the particular size class situation matches the size class you were editing when you added those views. So there they are. That seems to me to prove my guess is right.
I have the same issue while copy a ViewController to another storyboard.
Fixed by following steps:
1: Select the viewController
2: Click on 5th Tab
3: Set the simulated size to Fixed.
Select install:
Since all components [like label,textfield,buttons] are in disable mode, one select Installed check mark its will be enable again adjust constrain accordingly.
The size must be the same, in all xcode storyboard
In my case, it was due to me setting alpha to 0.0 and forgetting it.