Myth of the One-Day App, Week 2

Honestly, I never really considered ffmpeg. That would have been a fair bit easier. I was still reeling from the iMovie 1080p betrayal (see previous post), but also the reality that I was still three videos short – I did, after all, need to make promos for the other language-versions my app was supporting. I would need to translate, then duplicate the project, and then do a fair bit of copy/pasting. On top of which, if I needed to change one video, I’d need to apply the same change to the others, effectively quadrupling my workload.

Well, I wasn’t having that. I had a crazy idea to solve all my problems in one fell swoop, and it was this:

I was going to code my own iMovie, and I was prepared to spare myself a week to do it.

One Week Project!!

Now, titter ye not! Hear me out:

iMovie hasn’t really changed in years. And – sorry, Apple, you know I’m saying this out of love – it’s really showing its age. The effects are simple; most look downright amateurish through my 2023-goggles. While they may be great for impressing young kids, they don’t pass any muster compared to other (expensive) software. I’m sure this is by-design. Free software from big corporations is usually only there to whet appetites for their better, expensive software.

Fantastic transitions, McFly… for 1985 daytime TV!

Meanwhile, the ability to generate video from code is straightforward enough, using the likes of AVAssetWriter. If I could generate the frames, making the video would be trivial. And I’ve been writing code to create/edit images for years.

So, I needed three things:

  • a plain-text script
  • code to read the script
  • code to generate any particular frame, and thus assemble the video

No GUI needed. Keep things simple. Then, generating different versions, with resolutions/frame-rates/languages would be a snap.

What effects would I need?

Well:

  • fade/dissolve (the only transition you ever really need)
  • “typing” text
  • backgrounds (preferably, moving ones)
  • object positioning, scale & alignment

That’s not a lot to do, really. A week sounded fair (he said, optimistically).

Yes, I was doing it again: starting a new project to complete an old one. But this one would be genuinely useful for future promos, and who knows what else?

In case you’re curious how my week went:

Week 2, Day 1: (Wednesday 15th February)

  • Code to create a video from images
  • Code to create a short video moving background

Week 2, Day 2:

  • Transfer iMovie project to a plain-text script
  • Setup data structures for objects, effects & transitions

Week 2, Day 3:

  • Code to load from the plain-text script
  • Sequencer to organize which objects are shown in which frames

Week 2, Days 4 & 5

  • Weekend, but I did do a little sequencer work to get fade transitions working

Week 2, Day 6:

  • Code to extract images from videos
  • Code to make images from PDF files

Week 2, Day 7

  • CoreText work to offset individual character y-positions
  • Typewriter effect

Oops, there went my week, and still a fair chunk more to go… But, realistically, my one-day app was already two weeks overdue, so did you really expect me to replicate iMovie functionality in just one week?!

Advertisement

Legend/Myth of the One-Day App, Day Seven

So, I prevaricated enough and the time was nigh to venture forth onto the developer site and get my app submitted for release. It was Valentine’s Day, a day that I loathe on principle, but, for the sake of my long-suffering wife and my own crumbling sanity, I needed to seize the nettle by the horns before I succumbed to my own madness and mixed metaphors.

The first thing I found out (as mentioned back in the original post, with all that future knowledge) was that my app’s name was already taken. I couldn’t call it Sleep Tight. So, after much petulant stomping about and hissing, I renamed it Sleep Well and tried to ret-con that title within my brain. Almost two months later, I am only just getting used to it.

Sleep Well is an app I use everyday and I love it, but I had no clue how desirable the great Not-Me might find it. After all, it was an app that fixed a problem that might only be peculiar to my Mac. And, as an app with just one button, were people going to chance their spare coffee money on it after glimpsing one screenshot?

No way in hell, I thought.

But imagine if they could see it in motion…

A little less of a long shot?

Yes: what this app needed was… a promo video!

Video Killed The iMovie Star

Yes, a promo video! I could waste days more on that…!

Oi! No! That’s not what I wanted! I resolved that I could come up with a perfectly serviceable video in just one remainder-of-a-day, render it and be done. Day 7, then. Finished in a week, and only the Almighty could say better that that!

Now, I don’t own any fancy software for videos or video-capture. But MacOS has inbuilt video capture (Cmd-Shift-5), and I remembered using iMovie in the dim-and-distant, so I would use those two tools.

Cmd-Shift-5 (what else shall I call it?) is a lovely little app. And it seemed to be just the ticket for me: I could place my app window over the desktop, select a region for capture and just hit the record button.

Unfortunately… it pretty much fails to capture when a Mac goes to sleep. Not so unsurprising, that. But since Sleep Well‘s #1 task was to put the Mac to sleep, getting a “good” recording, especially for those precious moments after the Mac wakes up, proved impossible. Would any other software work any better? Probably not. There was only one thing for it: Sleep Well needed a “fake sleep” mode.

This “fake sleep” would simply involve hiding the Sleep Well window behind its black screen when asleep, and show it again on waking up. It was a “feature” needed only for the sake of the promo video, and wouldn’t show up in the submitted version.

That worked. Cmd-Shift-5 offered up no more protests. My only problem was moving my mouse cursor properly. I’m serious: as soon as I hit record, my hand started becoming extremely mal-coordinated and jittery. I needed several takes to get it right. This is why I could never be a stage actor: I’d trip over my own face standing still.

I also needed to generate several other “screens” to stitch together for the video. It wasn’t too much of a hassle. I imported everything into iMovie, added some text, jiggled it all about a bit until it was “that’ll do” quality, and then hit the render button…

The magic of iMovie…

…And it turned out okay, so I attempted to upload it to Apple and then…

“Resolution not supported!”

I had rendered it in 720p. In my defence, my app has one button and a tiny window, so why did it need to be 1080p? Well, it just did need to be, didn’t it! So I went back to iMovie and then I noticed something horrible: iMovie wouldn’t let me render it above 720p.

what a lovely “feature”

It seems to be a rather-well-known bug in iMovie. Unless you have 1080p video “pieces”, it won’t scale up to 1080p. Why? Don’t ask me why! It seems absolutely nuts. But what do I know? Perhaps Apple want every bit of output to be crisp and un-blurred so, rather than have people complain about their mildly-blurry renders, they cheerfully disable the 1080p option for a video that might be better suited to 720p, no matter what the user wants…

Was there a workaround for this bug? Well, the solutions described after a long web-search did not fix it for me. Had I wasted my day on this? As I saw it, I now had three options:

  1. chalk the day off to experience, and submit the app without a video; or
  2. buy some better movie-generating software; or
  3. use ffmpeg or similar to up-convert the already-generated 720p.

I engaged Hubris Mode and chose option 4.

(to be continued…)

Legend of the “One Day” App, Days Four to Six

A graphical representation of how interesting Days 4-6 were…

Days 4 & 5 (11th & 12th February) were a weekend. I code/do different things on weekends to avoid coding fatigue on my main project. So, already, that’s the best part of a week gone on my “one day” app.

Monday, Day 6, then, was spent on more unpleasant things: tidying & documenting code, and finding energy enough to write some of the blurb I imagined I would need for submitting Sleep Well to the App Store. Yes, Day 6 was Procrastination Day.

I did run into one rather annoying coding headache: how to close a window properly. I have several windows, you see, and, at various times, I need to close them. You might imagine the best way to do this is with [window close]; …well, it isn’t. If you do that you’ll get crashes. Clearly, the solution is to use [window orderOut:nil]; Clearly!!

The problem I have with App Store submissions is that I know they are the single most draining part of the whole project. I need to feel rested and full of vim to even open up the developer website. So Monday would be ideal, no? Well, no. By now it was Monday afternoon and I was cranky from the time spent on tidying code, that Window-close “feature” and my rather-horrifically-moribund attempt at a description (which I still needed to “translate” into three more languages).

So, instead, I worked on one of my other “almost done” big projects and prayed for more energy to find me on Tuesday…

(spoiler: I would have that energy and, by Jingo, I’d need it…)

Legend of the “One Day” App, Day (Part) Three

Now, the problem with doing your own multilingual code is: you need to “fix” things which are designed to work with the “normal” way of doing things. A case in point: menus. Since I was doing my own on-the-fly translations, I needed to update menus on-the-fly too.

Now, Apple’s menu coding is confused. Or, rather, it confuses me deeply. I’m a simple sort of fellow, so when I see NSMenu and NSMenuItem, I wonder: are they views/windows/abstract? Why do they both have title properties? If I can set the title, why doesn’t it always reflect that on screen?

Of course, I can get them working, but IMHO it’s not intuitive. It’s the Item that has a title which I can edit – unless it’s an item along the top of the screen, then it’s another Item’s submenu, which is a Menu. Not at all confusing.

The other problem is that, if you want to update a menu, you can’t do that when you need to, i.e. when the menu sends you an Action. So, if I have a menu to change a display language to German, I can’t set the title of menu-items to their German equivalents straight away – but 20ms later is fine.

The 20ms-later trick is also good for adding emojis to menus. If you don’t do that, the emoji doesn’t get displayed. Is that really by design?

So, this sort of confusion is not good for a Friday, and that’s where Day 3 went. Along with researching which English words should be translated and which shouldn’t. For example, “Quit” doesn’t seem to be translated in other apps but “Window” does. This is why English is the easiest language to learn, because of all the English words that lazy gits/sheep like me couldn’t be bothered to translate…

Legend of the “One Day” App, Part Two

After Day 1, this is probably what my one-button, one-label app looked like.

Basic. So, Day 2 was all about tarting it up a bit. Getting it a bit more like this:

In other words, I needed to:

  • create background windows to fade the desktop to black;
  • add a background gradient;
  • animate the button and gradient.

Actually, the button doesn’t animate, I have two labels over it, one sun, one moon, and I animate them instead.

The background started life a quick “painting” I made in krita.

This looked quite nice – at first – until I realized the brush strokes made me imagine my screen was dirty. It also clashed a bit with my “clean” sun and moon emojis. So, rather than painting new celestial bodies, I used Inkscape to generate a gradient for me, referring to images of scenic sunsets for colour inspiration. This gradient only needed to be one-pixel-wide, as it could be horizontally stretched, thus saving me a bit of space.

A couple of neat extras:

  • the window goes from “light mode” to “dark mode”;
  • the icon goes from an empty bed to an occupied one.

Don’t mind him – he’s from Barcelona…

On the Model side of the app, Day 2 involved:

  • ensuring that clicking or “typing” on one of the background windows should also cancel auto-sleep;
  • I wanted to be able to cancel auto-sleep by pushing a key modifier like “shift” – for this, keyDown: is no good; I needed flagsChanged: too;
  • I wanted to support German, French & Spanish.

Why German, French & Spanish? Well, I am very curious to find out whether going to the effort of translating text makes any sort of difference to sales. For a tiny app like Sleep Well it is not a massive amount of work to add a few translations.

But why German, French & Spanish? Well, I’m as English as Queen Victoria (I’m half-German, my father is German and I married a German). French and Spanish meanwhile are much-used around the world, I know some French from school, and Spanish also has Latin roots, so I have some tiny idea if the online translation tools I’m using aren’t just spouting gibberish at me.

As far as I am concerned, Apple’s approach to multilingual apps leaves a lot to be desired. It involves having all the translated text in one place with no context to it, and a lot of gobbledegook IDs. From such “localizable.strings” pages, how can I tell – for example – whether “Sleep” is meant as a noun or a verb? No, no, no, not for me! 🙂 I like to have text where the relevant code is. For instance:

char const * txt_hello = @”Hello|de Hallo|fr Bonjour|es Hola”;

That’s how I roll. Country codes and pipes, and let the smart labels work out which one to use. No need to restart the app or any such malarkey, just refresh some objects’ draw routines.

So that’s two days of the “one day” app. Reasonable so far? Good. It won’t stay that way… More soon…

Philip

Legend of the “One Day” App, Part One

Is it possible to code a good, useful app – and something that’s not been done before – in just one day? Spoiler: yes, of course it is. But the coding is the easy part – getting the app to the point of release can take considerably longer.

So, in this new series of blogs (yes, I’m not dead yet) I’ll be talking through the pitfalls I faced just to release one very simple app. An app with a single button – and how many apps are that simple?!

Background

For the past too-long-to-admit, I have been working on several medium-to-large-sized apps. About three of them are “very-almost” ready for release. The last thing I needed to do was begin work on something new. But I felt I had to code it for the sake of my sanity and, once I did, I wondered whether I could also get it onto the App Store. A small appetizer before the feast to come.

So, here was the problem: my Mac had developed a nasty habit of waking up from sleep mode by itself. Mostly this happened a second or two after I pressed “Sleep”, other times it would wait till a particularly irritating moment (once it actually woke me up while I was asleep).

My options, as I saw them, were:

  1. use a screensaver instead (wastes power, keeps the monitors on);
  2. turn the Mac off (inconvenient to do for short periods of time; often I have tasks running in the background, and I also like to use a RAM-disk);
  3. code an app to put the Mac back to sleep automatically. 🙂

Why do Macs sometimes wake up randomly? Well, my research points to a malfunctioning USB device being the usual suspect, but who knows? I don’t want to replace my devices if they are otherwise-working. So, option 3 it was.

App specifics: the app must send the computer to sleep, monitor it if it wakes up, and put it back to sleep unless told not to do so.

Goodnight, Sleep Tight, Don’t Let The App Title Bite You In The Backside

My first mistake (not realized till many days later) was in the naming of my app. I called it Sleep Tight. Why was that a problem? Well, someone else had already coded an app called Sleep Tight. So Apple wouldn’t let me submit my app with that name. I’d have saved myself the hassle of a lot of renaming if I’d registered the app title with Apple in the first instance.

Above are my (slightly-redacted) work-progress notes from 8th February which, as of writing this now, is a month and eight days ago. In fact, I started mid-afternoon, as a last minute addendum to my working day. That lunchtime my Mac had auto-woken several times, and enough was enough. I was done with the app a couple of hours later. So just how does a two-hour app balloon into a five-week app? I’ll start that explanation next time… 😉

n.b. I do want to keep these blog posts brief (both for me to write and you to read), but if you want to skip to see screenies of my finished app you can visit the product support page for Sleep Well. And, if you’re interested in buying it, here’s a link to Apple’s app store page for Sleep Well. Cheers! 🙂

Philip G, 16th March 2023

Back to Apping: Creepy Hands, Part 2

So, my task was to code a hand: one that could point and tap the index finger.

I suspect that, when large companies are given this task, they just send it over to the 3D graphics departments, whose cheerful minions happily generate a fifty thousand triangle mesh, manipulate it in cutting-edge software, then spit out some beautifully-rendered video files. Which is all well and good if you have that option.

But video files won’t cut it for me. If I’m future-proofing (like I always aim to do), then the number of video files needed would be ridiculous. The digit combinations alone must be 120 or so – and that’s just for opening and closing; still not enough to greet Mr Spock.

So: a 3D mesh. Is it doable? Well, yes, but 3D object construction is not exactly my forte, and it does seem a bit like overkill to add all those triangles for one little hand.

Hello, Hack-imation

Time is always an issue so I decided to do what I do best when faced with thorny coding problems: I cheat. Realizing that I only needed to see the back of the hand, I decided to go 2D. Yes, some of the movements are 3D, but smart animation can compensate for that.

First step: trace my hand on squared paper.

I traced the open hand, and also a a fist, and then tried to work out where the joints were. I like coding in circles, so each point of interest is a circle. I chose a scale such that I could type in ratios. The y-axis goes to 100, which is obviously 1.0f as a ratio, and makes scaling that much easier.

Yes, this will be a glove, which means I don’t have to worry about drawing fingernails!

If I had had the time, I might have chosen to render the hand in Metal. But I picked plain old Quartz for convenience and expediency.

I originally wanted to do the entire outline as one shape, but quickly decided against it, due to fingers and thumb sometimes hiding behind other digits (and the palm). So I draw the thumb, then little, ring, index and middle fingers in that sequence, because that’s usually the z-order.

The main part of the hand has to be drawn twice. Once at the back, and once more without borders, to erase the lines at the base of all the fingers. This is the “hack” part of the hack-imation, along with the right-hand-side, which I decided was most easily simulated with a Bézier curve.

How to draw a finger? Well, if you can work out where the outer tangent lines meet for two circles, that’s most of the job done. After that it’s just straight lines and arcs.

I treated the thumb like a finger, with the same number of joints. Yes, the base joint is just above the wrist!

One funny thing: if (as my picture shows above) you have the wrist curve dipping down, then your hand will quickly resemble a foot with spidery finger-toes! I strongly advise to flip that smile upside-down to avoid that!

Animating in Code

The maths required for animating a finger or thumb is refreshingly simple. Each joint moves from angle A (zero) to angle B in a linear fashion. You can eyeball the end angles. Just a few cos and sin functions required.

There are one or two sticking points, for example when a fingertip passes below a knuckle. That case is simple enough to simulate from a top-down perspective, however: simply, by drawing to the knuckle and no further.

There are always the odd graphical glitches that crop up, but these can be dealt with – either cleanly or with special-case hacks.

Using as a Cursor

When the hand is finished, the next step is to use it with the cursor. This is easy enough to do with your input code in OSX. The trouble (as usual) lies with iOS: there’s still no way of working out where your finger-tip is until it presses the screen.

What you can do is show the cursor when you tap the screen. You can add a small delay to have the hand fade in and then, when you tap-up, the hand can glide serenely away, fading out as it does so. But this is not ideal. I needed the hand to know where I was going to press for the product video.

I had a brainwave to connect a mouse to my iPhone and have a cursor show up at all times. Well, this works nicely on Android but not on iOS. On iOS, you can’t even connect an Apple mouse or trackpad to an iPhone! You can connect a third-party mouse, but nothing further: there’s no cursor.

Yes, I could have simply cheated and used OSX for all my product videos. But I didn’t want to do that. So I had to think again.

Automating

I thought, what if the hand did know where I was going to press? Rather: the hand could be coded to move, click, rotate, fade in and out, and so on. What I needed was a class to automate this.

Then it occurred to me: this wouldn’t just be useful for product videos, but for inline help.

The automation class here goes hand-in-hand with the calling class. At each indexed stage, the calling class should update such details as duration-of-action, hand-state, action-type, alpha, angle etc, and, as necessary, supply destination co-ordinates relative to a view it also supplies.

Finally you get something like this. Still not perfect, but it’ll do. 🙂

Back to Apping: Creepy Hands, Part 1

Once your masterpiece app is finished, there remain some irritating stumbling blocks on your way to the App Store. One of these is the product video.

A screenshot may tell a thousand words, but a good video can replace a fair few screenshots, and won’t require your potential beloved customers to scroll. Did I mention I hate scrolling?

You might suppose that the only challenge in the creation of a product video is to find software to record your screen. Unfortunately, this is the easy part. The difficult part is finding software that will also record your hand movements while your finger is still hovering above the screen.

Solution 1: use another device to take a video of yourself actually using the app!

This is a messy solution at best. Good luck to you if you want to do this. If you don’t have creepy hands, if you can eliminate reflections, sort out the lighting and background, and if you have good video after-effects software then this might work well enough.

Solution 2: Add a virtual finger (or hand) afterwards with after-effects software!

This may be a bit easier than Solution 1, and it should look neater. I almost researched this idea but decided that, if I were to make dozens of videos, it would take too long. In addition to the potentially prohibitive cost of after-effects software.

Solution 3: Draw the actual finger (or hand) in-app!

This was my favoured solution, because it’s more of a coding challenge. It does not require learning any other skills, or purchasing any other fancy software.

I tried to remember how I solved this problem before, years ago, for my previous apps (which are now lost in time). I had a vague memory of taking a photo of my hand and employing that as a makeshift cursor. Then using the simulator to record everything.

Why didn’t I take a look at my old code? Well, because coders like me really don’t like doing that. Nobody should want to peruse the horrible code of our less-experienced selves. We much prefer writing shiny new code.

But anyway, the first step was to photograph my hand. I wanted two top-down shots of a pointing index finger, with one of them simulating the tap motion.

You won’t believe how wretchedly difficult this is to do. Because, the thing is, I needed to have a background which I could magic away quickly in software. Yet no matter what colour card I had underneath my hand, masking this out in one go proved extremely difficult, due to shadows and skin reflections and weird optical illusions like this one.

In the end, I thought back twenty-five years. My preference back then was never to use photo-manipulation software. It was to use vector software and manually mask out the image, using straight lines and Bézier curves. This is what I did (thanks, Inkscape).

So, coding a hand for a cursor is trivial. It’s not a proper cursor, of course, rather it’s an image that has its origin at the pad of the index finger and follows the mouse around. But here was my new problem:

My hand looked extremely creepy as a cursor.

Yeesh. I’ve spared you the two other colours I used as backgrounds. Notice the shadows above the knuckles? That’s where bitmap software fails. Vector software meanwhile loses hairs, but that’s the least of things, as far as creepiness is concerned.

I had to ask myself: was my hand always this creepy? I know I’m no spring chicken but that thing was like something out of Tales of the Crypt. Does my hand really look like that in real life?!

Well, it wouldn’t do at all, and I didn’t want to go through that whole process again with someone else’s hand. What if their hand turned out to be just as creepy as mine? On the other hand (ahem), what if it looked great and I ended up with a complex about my own general hideousness.

So, my next thought was to draw a cartoon hand. Well, actually, not a hand: a glove. If it’s good enough for Bugs Bunny then it’s good enough for me. Now, I could draw this with pencil on paper and then scan it in and that would surely have been the best solution.

But then (unfortunately) I had another idea, and it was this: I should really draw this hand in code…

The Problem With Buttons

I have a problem with buttons (small b, it’s not about the pantomime character, so sorry if you thought it was). To “click” (or, as the youngsters among us say, “tap”) on a standard button, you have to be accurate. If three buttons are side-by-side and you want the middle one, and you hit one of the buttons on the side, you’ve failed. Go straight to Jail. Or, rather: you now have to slide your finger away and try again.

Using a mouse, this isn’t a problem. Mice are accurate beasties. With a touch-screen, though, especially when your screen is small, it becomes an issue.

The standard solution for an iPhone? Make your buttons much bigger.

Needless to say, I hate this solution:

  • the app now looks less like Technic Lego, more like Duplo;
  • it takes valuable screen-space away from other things.

So, how do I deal with it?

I allow the user to slide from one button to the next. If buttons are adjoining, that is then one control, not many. In the input_down code, work out which button you’ve hit. In the dragging code, calculate again. The input_up code is what matters for the “click”.

Additionally, if there’s a natural margin around the buttons, register a hit on this margin as a hit on the button (the margin also becomes a part of your control).

If you want to keep your buttons small, there’s one more problem to deal with: the user’s fingers. How do they know which button they’re over if their whopping-great sausage finger is obscuring their view of the screen? Well, standard keyboard displays do this with a pop-up key display. This works fine for a keyboard but won’t be much good it your button is at the top of the screen.

Once upon a time, a status bar at the bottom of the screen would be the solution. 9 times out of 10 this is all that’s needed. But, um, what if the keyboard is being displayed?

Well, in addition to a status bar (which I still think is very useful) alongside a replacement (or reframed standard) keyboard, the solution I favour is to use the middle of the screen. OSX often uses what I imaginatively call a “grey square control”, which is semi-transparent, non-interactive and fades away by itself before it wears out its welcome.

Is there a problem with using the middle of the screen? What if I were to have a button there? Well, no, that’s actually a silly place to put a cluster of small buttons!

So, to sum up: for frustration-free small buttons, you might feel you need to:

  1. code a multi-button control & handle the input and drawing yourself (the easy part);
  2. code a status bar;
  3. deal with the on-screen keyboard (or code your own) to accommodate said status bar;
  4. code a grey square control (because, if nothing else, they look cool).

Alternatively:

  1. be lazy, save yourself a fair bit of time, and use big buttons.

I don’t blame you if you opt for big buttons. Because it’s not just buttons, it’s lots of controls. They’re simply not designed to work well with one another when they’re in proximity. As soon as there are multiple views involved, the standard input process fails. To fix this one problem, you’ll soon find yourself fixing similarly-irritating other ones. It’s less of a rabbit-hole, more like those caves in The Descent. And that’s where I’ve been, thankfully with the American ending and not the UK one. 😉

Keyboard Worrier

When the iPhone first arrived, I didn’t get one. I wanted an iPod Touch instead, which was great for music, not so good for calls.

As amazing as it was at the time, the iPhone software was missing something, and it’s something that’s been bugging me ever since. Here’s the on-screen keyboard, as it appears now on my iPhone:

And here’s the landscape variant:

What’s wrong? Well, mainly the absence of beloved keys. Where’s my tab key? Where’s escape? Forward delete? The cursor keys?! Dare I even ask about Command, Option and Control?

Why cannot such buttons at least be put on the landscape mode view, instead of elongating the portrait layout like silly putty?

There is no getting around it: I often feel hamstrung having to use this simple keyboard.

Yes, I do understand the thinking that such keys would just clutter and confuse and that, with a touch-screen, they might also be superfluous.

Well, boo to that with knobs on!

  • Placing the typing caret down between the two letters I want is an exercise in frustration;
  • Tabbing now requires tapping – plus sometimes scrolling – different areas of the screen instead of one key;
  • As for dumbing down for the masses, why not supply two modes with a keyboard, the same as for a calculator: basic and advanced?

For the app developer wanting to reimplement what was lost, the documentation suggests that such missing buttons should be placed (awkwardly) in a row above the other keys. It’s a bit of a hack in my humble opinion, and can look pretty nasty.

So, one of the things I wanted to work on for my software library was a decent keyboard control. If I needed to fit extra keys to my keyboard in portrait mode, I’d clearly need some sort of zoom (I also do for the iPhone keyboard, as I’m always hitting the wrong key at the edges).

Here’s my SuperKeyboard, as it appears on my iPhone:

(the bezel shape was added afterwards by me, since it doesn’t appear in the screenshot!)

Coding your own keyboard has its small challenges, including:

  • dealing with the peculiar way iOS handles rotation (i.e. when it’s rotated landscape but the frame still thinks it’s in portrait mode);
  • the carriage-return key, which has to be drawn separately due to its odd shape;
  • dealing with bezels and safe areas (I would love to be able to access the shape of the screen programmatically; instead I am provided with four margin values).

My layouts are all very simple text files, which are then read into the SuperKeyboard, with the code working out the relative sizes for the keys depending on their types. As such it is now relatively trivial to modify any layout, or create a new one as desired.

Oh, and one last thing I wanted: a smiley keyboard with a spacebar, arrow keys etc.

Shifting does this:

That’s one more control down. 😉