For the past week I’ve found myself focusing heavily on the mobile version of Lagrange.
For me staying in “heads down” mode is nothing new. Since 2020 it’s certainly been a nice respite, but after discovering BASIC on the C64 in the late 80s, deep focus in front of a computer has been my favorite pastime.
Immersing oneself into a coding project certainly helps ease the stress of dealing with a toddler, the ongoing pandemic, increasingly tangible climate change, growing inflation, and a not-too-distant war. Still, I count myself immensely lucky for not having actual problems to worry about right now, just the potential of future calamities.
The biggest remaining work item in the mobile UI design has been dialogs. Mobile variants of all dialogs already existed, but they were using a fullscreen mode intended only for the Settings UI.
Most dialogs are simple enough to not require the full screen, especially on a tablet. A few design variations were needed for non-fullscreen phone and tablet layouts. These follow the general “card” behavior where stuff pops up from the bottom of the screen, near your hands/fingers. It wasn’t that much work to tweak how the mobile dialogs behave, but a few quirks once again surfaced in the UI toolkit with things like keeping input fields visible when the software keyboard appears.
With this finished, I’m feeling pretty good about the mobile UI. Sure there are small tweaks needed here and there, and visual polish and small animations would be nice, but overall it now feels cohesive.
An odd quirk in the iOS version has been that scrolling a page sometimes gets extra stuttery. After a closer look, the problem appears to be that even though the UI refresh is super quick, scroll events sometimes bunch up and start arriving in pairs every second frame. This leads to 30 Hz scrolling, which looks rough to say the least. This was ultimately the reason why scrolling felt slugging on an iPhone 7, a device quite capable of rendering the app’s simple UI.
I haven’t found the ultimate cause for this seemingly iOS-only glitch. It could simply be some SDL bug since the app doesn’t exactly behave like a typical SDL app would, i.e., it isn’t running at a fixed frame rate.
For now I’ve opted for a simple workaround. There is a small buffer of scroll events that gets taken into use if the events start clumping up, so each frame will get to have its own event even though some of the scrolls have to be delayed by one frame. This keeps scrolling smoother without fixing the lag. It would be possible to predict the “missing” scroll values per frame, correcting when the real events arrive, but I’d rather find and fix the root cause.
I then decided it was time to figure out the native text input situation on Android.
Just like on iOS, on Android you can programmatically create and place EditText controls over the SDL canvas, and it works quite well. The biggest hurdle was that one needs to use the Java UI thread to handle these UI views, which means that the C code and the UI run in separate threads and must communicate asynchronously. This caused a few tricky crashes that I hopefully managed to work around.
Now all input fields get the full benefit of autocorrect and other keyboard features, like having Send/Go instead of a simple return key. This should make it much nicer to type in the app.
Another new platform adaptation is changing the color of the system UI elements: status bar and the device navigation bar. These now get switched to the UI or page background color, depending on the app’s UI layout. The way this needs to be done via the Java APIs is a little eyebrow-raising, but apparently StackOverflow is full of tips about this kind of things.
I also took a stab at emulating the Android scrolling behavior that has a different friction model compared to iOS. In practice, swipes will stop scrolling a lot faster than before. It isn’t yet 100% correct, but now it’s a lot closer to system behavior.
All this means the alpha phase is over. There are a few issues still to investigate, but the first Beta should be available in the near future.
📅 2022-03-27
CC-BY-SA 4.0
The original Gemtext version of this page can be accessed with a Gemini client: gemini://skyjake.fi/gemlog/2022-03_heads-down.gmi