Autolayout - practical layout of complex screens and a conceptual hole - ios

I'm trying hard to drink the Autolayout KoolAid in Xcode 6. I understand the fundamentals. It's solving a set of linear equations for the coordinates and sizes for all on-screen objects. I've watch the videos and read the tutorials. I've gotten it to work.
With all the different devices and screen sizes out there, it seems like a great solution.
So here's a mock-up of my screen:
When I create this simple layout of 5 labels (just the yellow ones for now), I need 20 constraints, right? Height, width, X position and Y position - for each one.
So my constraint list ends up looking like this:
First, I don't see the what that sort order is there, which makes it hard to find things. Worse, that's already a massive number of constraints to look through to find problems.
This can't be a very complex screen in the big scheme of things. What concept am I missing here? What organizational method would help me? If people are doing large screens with many elements, how are they managing the dozens and dozens of constraints?
Note: I don't want to use a table because that seems like overkill - I don't need to scroll, I don't need buttons in cells, and I don't really want to bother styling a table and cells to look like what I've got there in the mock up. This is really just an example of 5 elements on a screen (15 on that screen, actually).

Related

Best Swift/iOS practice for changing speed/movement of objects based on device or screen size?

My question would be best asked with a simple example:
If I have a game where a ball is near the bottom of the screen, and the goal of the game is to dodge objects scrolling down towards it, I am having trouble figuring out the best method to make the game "fair."
If the game screen is larger, then that player has an advantage because they see the scrolling objects at the top of the screen with more time to move away from it.
I'm wondering...what is the best practice to "scale" the game to where regardless of the size of the screen, the rate at which the scrolling objects move towards the ball, and eventually reach it is exactly the same?
My first instinct is to scale how fast the objects scroll with the size of the frame the game is in. But for some reason that feels clunky to me, or that if I just scale all the objects relative to the size of the screen, that is enough and I'm worrying over something minimal at best.
Anybody ever had a same kind of issue? What is the best means to have a things "behave" the same if the size of the screen/frame plays a key role in your game?
I am open to general Swift and SpriteKit, as I am just in early stages of thinking how to accomplish it.
For SpriteKit, you'll normally design the game, including the sizes and speeds of objects, with some particular logical frame size. That will then get scaled to fill the screen in some appropriate way. How the scaling should be done depends on the game though. Usually you don't want to have different scalings for width and height, so the issue boils down to how to handle different aspect ratios. There are two main possibilities:
Make sure there's a certain minimum amount of the game area shown, and show a bit more either horizontally or vertically depending on aspect ratio. Potentially unfair if you don't do anything else, but as you mentioned something like scaling object speeds can compensate.
Pad out the game area with some non-playing area parts (perhaps decorative, or containing parts of the controls, score display, etc.) Depending on device aspect ratio, different parts of this get cut off or shown. The real playing area is exactly the same dimensions on all devices.

Before diving in, is this possible with Awesome WM?

I've been trying different tiling WM's to see which one best fits my needs. Every time I try a new one, it looks good but I find other things that don't quite work the way I like. My requirements have evolved as I go. Initially, I didn't want to get into Awesome because having to learn Lua is not on my wish list but maybe I should give it a try IF it can do what I want better than the other tiling WM's out there.
I'm going to as specific as I can about what I want. I am running a 3440x1440 monitor. I want to use as much vertical space as possible (meaning, a full width, persistent but mostly empty status bar is not an option, but I do like the notification area and a date/time).
I understand it may not do everything exactly the way I want, which is oke. If it does more or less most of what I want I can weigh my options between Awesome and other tiling WM's (actually, only i3 which is what I'm using now but I'm open to better suggestions). I would very much appreciate it if people don't just say no to something it can't do, but say "no, but it can do ...". In other words, feel free to suggest alternatives that might be helpful as well.
Divide the screen in 3 columns, initially 30/45/25, with the right column split horizontally; Fully adjustable and resizable as needed during my work session;
Persistent layout; when closing the last application in a tile, I don't want that tile to disappear and the remaining tiles to resize. Just show an empty space and leave all tiles as they are.
tabbed tiles, so I see which applications are running in a tile (similar to i3).
Resizable tiles with the keyboard into 1 direction; When making the middle column/tile wider, I want that into a specific direction into another tile and leave the other side alone.
Certain applications I want to always launch into a specific tile. For instance, terminals always go into the right-most column top/bottom, browser/spotify always into the middle, atom/IDE always into the left. Some applications should always be floating. Obviously I want to be able to send them to a different tile after launch.
I don't want a 100% width status bar. It will be mostly empty which is a waste of screen estate. Preferably, I'd like a statusbar part of a tile, for example in the right-most tile, resizing with it. Otherwise I'd like it to be fixed to 30% and allow tiles which are not beneath it to use the full height of the screen. My reason for a statusbar is mute; I actually only want a notification area and a date time permanently visible. I don't need a "start menu", dmenu or similar is perfect, which I believe it has integrated.
Many thanks in advance!
The general answer is "Awesome configuration is code and it can do whatever you want". But there is a catch. Can Awesome be configured like you describe? Yes, totally. There is at least 2 distributions coming close enough (mine[1] and worron[2]) (at least for the tiling workflow, not the look).
The "catch" is that the workflow you describe isn't really the "Awesome way". Awesome is usually used as an automatic tiler. You have layouts that describe a workflow (code, web, internet) and manage the clients according to their programming. Manual tile management is rarely necessary once you have proper layouts. That doesn't mean you can't, I did, but it might be worth thinking outside the box and see if you can automate your workflow a bit further.
Also, the default layout system isn't very modern and makes it hard to implement the features you requested. My layout system (see link below) can be used as a module or as a branch and supports all features described above. Awesome is extremely configurable and it's components can be replaced by modules.
https://github.com/awesomeWM/awesome/pull/644
The layout "serialization" documentation is here:
https://elv13.github.io/libraries/awful.layout.html#awful.layout.suit.dynamic.manual
It is similar to i3 but has more layouts and containers. As for the "leaving blank space" part, it is configured using the fill_strategy:
https://awesomewm.org/doc/api/classes/wibox.layout.ratio.html#wibox.layout.ratio.inner_fill_strategy
As a word of conclusion, I would note that what you ask is "work exactly like i3". If you want such thing, well, use i3. Awesome is a window manager framework. Its goal and purpose is to create a customized desktop shell / WM. If it's what you want, then go ahead and learn it, nothing else can come close to the possibility and the level of control you can get out of it. However it takes time and effort to get to the point where you have "your own perfect desktop". Our users perfect desktops:
https://github.com/awesomeWM/awesome/issues/1395
[1] https://gfycat.com/SmallTerribleAdamsstaghornedbeetle
[2] https://www.youtube.com/watch?v=-yNALqST1-Y
The WM your are looking for is herbstluftwm (hlwm). Its a manual tiling window manager. The tiles which you are talking about are called frames in hlwm. Each frame can contain multiple windows. A frame can also be empty. Only if you kill a frame the other frames will automatically resize. You can add new frames vertically and horizontally and resize them. Each frame can also have a different layout to organize the windows inside. The layout you are looking for is max. This will stack the windows inside a frame on each other. It doesn't show you tabs like i3 however. hlwm allows you to create rules to open certain applications always in certain frames and workspaces. hlwm doesn't have a statusbar buildin. I personally like to use tint2. It can be used as a replacement for your requirement to see running applications as tabs.

Building for multiple screen sizes without size classes

I am currently writing an iPhone app (my first one) and never used
Size Classes
Auto Layout
Stack Views
To set the views/images/labels etc. on the screen. didn't use storyboard as well,
Every thing that is shown is coded.
I didn't start using these tools because back at the time (a couple of months ago) they seemed to be more of a pain than a true gain for my development process,
But looking back i feel i made a mistake and now I'm way too deep in code to start it all over again with the traditional/designated tools.
So, Having said that, are there any known frameworks and/or best practices to make sure that all that's printed are scaled exactly the same and have relevant ratio for each device size?
Something like: calculating the height/width ratio and somehow applying it to all the views/images etc?
is there any good way to get out of this mess?

Need to make a Gantt chart like control in iOS, to draw or to subview?

I'm about ready to begin to create a Gantt chart like control in iOS for my app. I need to show a timeline of events. Basically a bunch of rectangles, some lines/arcs for some decoration, possibly a touch point or two to edit attributes. It will basically be a "full screen" control on my phone.
I see two basic paths to implement this custom UIView subclass:
Simply implement drawRect: and go to town using CoreGraphics calls. Most likely split over a bunch of private methods that do all the drawing work. Possibly cache some information as needed, to help with any sub region hit detection.
Rather than "draw" the graphics, add a bunch of UIViews as children using addSubview: and manipulating their layer properties to get them to show the different graphic pieces, and bounds\frame to get them positioned appropriately. And then just let "drawing" take care of itself.
Is one path better than the other? I may end up trying both in the long run just to see, but I figured I'd seek the wisdom of those who've gone before first.
My guess is that the quicker solution would be to go the drawRect: route, and the subview approach would require more code, but maybe be more robust (easier hit detection, animation support, automatic clipping management, etc). I do want to be able to implement pinch to zoom and the like, long term.
UPDATE
I went with the UICollectionView approach. Which got me selection and scrolling for free (after some surprises). I've been pretty pleased with the results so far.
Going with CoreGraphics is going force you to write many more lines of code than building with UIViews, although it is more performant and better on memory. However, you're likely going to need a more robust solution for managing all of that content. A UICollectionView seems like an appropriate solution for mapping your data on to a view with a custom UICollectionViewCell subclass. This is going to be much quicker to develop than rolling your own, and comes with great flexibility through UICollectionViewLayout subclasses. Pinch to zoom isn't supported out of the box, but there are ways to do it. This is also better for memory than using a bunch of UIViews because of cell reuse, but reloading can become slow with a few hundred items that all have different sizes to be calculated.
When it comes to performance, a well written drawRect: is preferred, especially when you would potentially have to render many many rects. With views, an entire layout system goes to work, much worse if you have autolayout, where an entire layout system goes to town and kills your performance. I recently upgraded our calendar views from view-based to CG-based for performance reasons.
In all other aspects, working with views is much preferred, of course. Interface Builder, easy gesture recognizer setup, OO, etc. You could still create logical classes for each element and have it draw itself in the current context (best to pass a context reference and draw on that), but still not as straight forward.
On newer devices, view drawing performance is quite high actually. But if you want these iPhone 4 and 4S devices, if you want these iPad 3 devices, which lack quite a lot in GPU performance, I would say, depending on your graphs potential sizes, you might have to go the CG way.
Now, you mention pinch to zoom. This is a bitch no matter what. If you write your drawRect: well, you could eventually work your way to tiling and work with that.
If you plan on letting the user move parts of the chart around I would definitely suggest going with the views.
FYI, you will be able to handle pinch to zoom with drawRect just fine.
What would push me to using UIView's in this case would be to support dragging parts of the chart, animating transitions in the chart, and tapping on elements in the chart (though that wouldn't be too hard with drawRect:). Also, if you have elements in your chart that will need heavy CPU usage to render you will get better performance if you need to redraw sub portions of your chart with UIView's since the rendering of the elements is cached to a layer and you will only need to redraw the pieces you care about and not the entire chart.
If you chart will be VERY big AND you want to use drawRect: you will probably want to look at using CATileLayer for you backing so that you don't have the entire layer in memory. This can add added challenges if you only want to render the requested tiles and not the entire area.

Do I still need to pad images in a CSS Sprite?

In CSS Sprites you will often find padding between each image. I believe the idea is so that if the page is resized then one image won't bleed into another.
I think this depends on the different types of browser zoom (best explained by Jeff).
However, I haven't been able to see this behaviour in my tests. Is this only a problem with older browsers? (I havent been able to test with IE6 at the current time so I'm counting that as 'old').
Should I still worry about leaving space? Its kind of a pain.
For instance :
A CSS Sprite I found for AOL has
padding between each image : VIEW
but The Daily Show decided not to
bother : VIEW
It shouldn't need to be padded, but when zoomed, especially in IE8 (betas more than the RC), there is image bleeding if there is no padding.
Best example is to go to Google.com -> Search, and zoom... you'll start to see "underlines" at the bottom right of the image as the zooming rounds up/down.
In theory, a 1px padding on all sides of a sprite should be fine.
Here's the sprite from Google (images)...
But when zoomed, the +,-,x icons bleed into the main Google logo.
Basically the answer is yes. Two years to the day after I asked this question will see the release of IE9. IE9 has this problem just as much - if not more than any other browser...
It's pretty infuriating because it's such a simple thing to fix.
With iPads increasing in marketshare - its's pretty essential to at least have a half decent experience with zooming un-uniform amounts.
I am going to have to put a single pixel border around every image to match the background color of the adjacent element (potentially different on each side). Fortunately I auto-generate all my csssprites based on an .xml file - so I can do this programatically without too much hastle. It's still a huge pain though...
Simon - My experience is that this is certainly still a problem.
In response to your second question, why not use transparent padding? (Perhaps you are still supporting ie6 and this is non-trivial, in which case, I'm really sorry).
Speaking of the older browsers (those using text zoom), you don't always need padding.
The main difference between your two examples is that the Daily Show sprite already includes the menu item's text in the image itself.
When using text zoom, the AOL menu items could stretch out vertically due to the larger font size, and the menu text might even wrap to two lines. To accommodate for such eventualities, those icons need a little padding to ensure they don't bleed. Typically, you'd just try to make sure it doesn't bleed on any of IE6's five text sizes.
Since The Daily Show's menu doesn't contain any (visible) HTML text its size won't be affected by text zoom (though you might need a line-height: 0; or so to be sure), so it doesn't need any padding.
As scunliffe already showed, browsers using page zoom may need sprites to have a little padding due to rounding errors.

Resources