I've been playing around with the auto-layout feature of XCode 6 in developing a Swift application for the iPhone.
It works well for a small number of controls but I now find myself with a section on the screen which will consist of a matrix of eight by eight small text controls (in portrait mode) of the form 7☐ and 42☑ (all three characters), each which can be selected by the user (toggling the checkbox).
I'm wondering what's the best way to handle this. I started by simply laying out all sixty-four text controls but this quickly became a nightmare in trying to join them all together with constraints.
I then wondered whether it would be easier to have one text control in a fixed-width font (or in a font where all digits are the same width and a space character of that width is also available) so I could control the layout manually (with newlines). The downside of that is that I'll then need to perform hit-testing on the control to see which item should be toggled.
Both these approaches have the downside that they don't adjust well when switching to landscape mode or to other resolution changes.
So my question is, how do I handle this in a way that can take full advantage of auto layout (i.e., minimal work for the developer). Ideally what I'm looking for is something like the Java Swing FlowLayout container, to which I can just insert those text controls in order, and it will fill it out as if it's a book (populate top line, left to right, then next line and so on).
If you have a matrix like layout and you want it to flow like the FlowLayout from Swing, you can use a UICollectionView.
I think that matches best what you are trying to achieve.
Related
I'm working on a MacOS application that needs to display large images. if I naively set the ImageView to be the full size image, the application's window can be forced to become larger than the screen size. What I'd like to be able to do is work out how large I can make the image while keeping the entire window (which also contains other UI elements) on screen.
I know I can query the amount of available screen space using NSScreen:visibleFrame() but that does not seem to be much help since unless I make a whole load of assumptions about how much space the rest of the UI will take up which then defeats the point of having constraint based UI layout.
The other approach could be to find a way to constrain the window size and then let Cocoa work out the sizes of the views. However, it looks like the UI editors in Xcode only allows static sizes to be specified which is not much help.
It looks like this is possible in SwiftUI (https://www.hackingwithswift.com/quick-start/swiftui/how-to-adjust-the-way-an-image-is-fitted-to-its-space)
Image("example-image")
.resizable()
.aspectRatio(contentMode: .fit)
However, the application I'm working on needs to run on older versions of MacOS than supported by SwiftUI so I need to know how to do this in swift but using plain Cocoa.
The first thing I would try is to modify the priority of the constraints that make the image view large enough to accommodate the image. That would be its content compression resistance priority. I think if you set it to .dragThatCanResizeWindow then you might get the behavior you want for free. That's because the system already constrains a window to the screen size when you drag its edges. So, presumably, that implicit constraint has a higher priority than .dragThatCanResizeWindow.
If that doesn't do it, you can programmatically set a window's maximum frame size by setting its maxSize property. You'll want to set that each time the screen configuration changes or the window moves to a different screen. For the former, you can observe NSApplication.didChangeScreenParametersNotification. For the latter, your window delegate can implement windowDidChangeScreen(_:) or you can observe NSWindow.didChangeScreenNotification.
I am having severe difficulties finding a clear working world example of auto layout on multiple screen sizes. Most tutorials have basic stuff like a button thats centralised and then after adding constraints in Interface Builder it scales with the device. One button is simple but in my example for the iPhone 4:
There are quite a lot of labels / buttons and some that are not central. The above screen shot is exactly how I want it to look on all devices.
The app is for portrait only but I want to target all devices. I tried slowly adding constraints to items from the bottom up using a multiple of the superview to position and size items and then applying aspect ratio to UI Objects (got as far as the got it button but not the red arrow buttons) but as you can see in the next picture for the iPhone 8 plus... the white space isn't going to perfectly fill like in the iPhone 4 which will leave me with a big gap at the top.
Is there a way I can change just the iPhone 8 plus layout in Interface Builder to build a layout that caters for the extra screen size?
The iPhone 8, SE and X layouts are equally awkward with extra white space.
I tried size classes but that changes it for all phones.
Is there a way to centre what I have done so far?
How do you guys position objects in auto layout that are not centred?
Am I going about it the wrong way by applying X / Y constraints using a multiple of the superview? - same for the width. I'm only specifying widths as a multiple of the superviews width then adding aspect ratio.
I just need a real world working example I can learn the basics from or a system to create for multiple devices that I can follow. I don't want to use a 3rd party library.
I really hope someone can help point me in the right direction!
Krivvenz.
I am currently trying to get the hang of Auto-layout in Xcode, and with it, i have found some problems.
Now, i don't have a 100% grasp on how auto-layout works exactly, so as i learn on it might become easy, but i think it is very hard to be honest. I am usually making games, and of thus, i programmatically add a lot of views to the screen. Now, auto-layout seems to mess everything up when i do this, so i constantly have to make sure that every single auto-layout feature is just right, and there are a bunch!
So, if you do not want to support other orientations, is auto-layout really needed? i mean, if i am making a game for the iPad and using landscape mode only, is there any reason for me to use auto-layout?
Thanks on advance
A couple of thoughts:
Auto layout is not mandatory.
But auto layout provides a mechanism for dealing with situations when views change sizes and/or locations:
changing orientation, as you pointed out;
supporting different screen sizes (e.g. iPhone 3.5" screen vs 4.0" screen);
controls whose size changes based upon content (e.g. a UILabel whose width expands to fit the text or whose lineCount is set to zero, meaning that its vertical will grow based the number of lines needed to fit all the text); with auto layout you can establish dependencies between controls so that, for example, as one control changes its own size/location, others can move/resize accordingly (e.g. to stay aligned with or make room for the other control); and
automatically update contentSize for UIScrollView objects.
Auto layout requires a little time to gain proficiency, but for dynamic, complex user interfaces, it can save you from having to write code to manually change layouts of views programmatically. But if you don't find yourself doing this sort of code, then you don't necessarily have to use auto layout.
I should acknowledge that there are some tasks that are trivial in a non-autolayout environment (e.g. animation of moving views), doing the same task in auto layout can be frustratingly complicated. But if you have complex interdependencies between views (either between the superview and its subviews or between sibling views), auto layout can be useful.
Autolayout simply provides rules for the views how they appear in all orientation.It is upto the user to define how to use it or you may follow the struct and spring model .
The major difference between the two is that there no dimensions involeve in the struct and springs while autolayout says the dimensions and values in whch views should be rearranged
An excellent beginner tutorial fo autolayout
I'm using the workaround described here to vertically align text in a multiline UILabel to the top. Unfortunately that solves only half of the problem because I also want to collapse the remaining space and move other labels below the label to move up and consume the space.
Is there anyone way to achieve this without having to resort to calculating the Frame's of the other views yourself and thus taking over the layouting?
Here's a screenshot of my problem. To make it easier I've colored the background of the relevant labels. The Blue label is supposed to move up and consume the unused space of the red label. The Red Label is configured for 3 Lines and Font-Autoshrink is off.
You must re-calculate your label frames and then rearrange your labels in the view.
Or you can try to use CoreText to make more complex layouts without the need to cope with these frames rearrangement. On GitHub there is a nice work BSD-licensed, called NSAttributedString+HTML: https://github.com/Cocoanetics/NSAttributedString-Additions-for-HTML which tries to port in the iOS the same methods already available in OSX. It is based on CoreText and with this class you can write your page as html and render it on screen without using UIWebView (and without its limitations). Based on your screenshot, it would be easy to achieve the wished result with simple html.
I'm working on a Perl/Tk GUI. It will have three main areas. Two of them side by side on top and then another one below the two.
I could just use grid geometry management. The upper two would have a row weight of 2. The lower one would have a weight of 1.
This would be good for the starting position, but the user needs the ability to adjust the sizes.
Looking at the Tk documentation, PanedWindows can also have a weight, but I can't figure out how to access it.
As I have it now, with my Paned frames, the upper and left children are minimum size, everthing else fills the area below and to the right. If I adjust the main window. only the lower and right windows are resize. Worst of all, I can resize the window and make some of the children disappear.
I want to maintain the current relative sizes.
How do I do this? I'm not tied to paned, grid, pack. Whatever works.
Sounds like you are using frames in Tk. While I have never used Perl/Tk, I am kind of savy html which Tk is probably based on html. So, you might want to look into frames and framesets at Frames in HTML documents on the W3C site.
It sounds like you need 1 frameset with 2 frames for the top and another frame for the bottom.
I hope that this helps.