Case Study: Building a Multi-Platform Accessible Solitaire Game
Guy Barker
Exploring how to make apps more accessible to more people, and sharing all I learn.
A while ago I built a solitaire app for Windows, specifically to explore game-playing experiences involving a variety of ways people interact with their devices. Part of my motivation for doing this was that I’d tried a number of existing solitaire games and found some significant accessibility issues with them, such as not supporting players who use screen readers, or always showing fixed colours and sizes of content.
I shared my learnings in a collection of articles, including The Sa11ytaire Experiment - End of Part 1, discussing input methods such as keyboard, touch, speech, switch, and eye control, and The Sa11ytaire Experiment - End of Part 2, where I started incorporating Azure AI into the mix, first with Language Understanding and later with playing card image recognition.
I was recently asked whether I’d be making that solitaire app available for Android, and this got me wondering about what it would take to build a .NET MAUI version of the app. Hopefully this would make it practical for me to release a version of the app for both Android and iOS.
Here I’ll share some of my experiences as I started out on that journey, having just released a new app, Accessible Solitaire for Android. Some details on how to play the game, and its accessibility-related features, can be found at Accessible Solitaire ReadMe.
Porting the app from UWP to .NET MAUI
Already having a XAML-based, C# UWP Windows app gave me a great starting point for a .NET MAUI app. After all, lots of the XAML and C# will be unchanged in the new app. Rather than trying to port the original Visual Studio Solution over to .NET MAUI, I decided to create a new .NET MAUI app and copy in all the XAML and C# content. It was then just a case of updating the places where it didn’t build, to use equivalent .NET MAUI content. For example, replacing a Page with a ContentPage, and a StackPanel with a StackLayout. Overall, this was pretty straightforward.
One very important area which I chose not to port over at this time related to the keyboard experience. The most exciting aspect of my original Windows solitaire game was exploring a variety of new ways to make playing the game with the keyboard as efficient as possible. I’ll look forward to exploring that again at some point, but initially the new app would not focus on the keyboard experience.
The Initial accessibility of the Accessible Solitaire game
When building a new app, I always use semantic controls that come with the UI framework. By doing so, I’m getting a good head start on serving all the game’s players well, regardless of how those players interact with their devices. For example, players who use screen readers will be informed of the state of toggleable buttons or selectable list items. If instead I was to only convey such information through visuals associated with custom controls, a player using a screen reader might not be made aware of the information required to play the game.
That said, I couldn’t get the Android TalkBack screen reader to announce the selection state of CollectionView items, or the position of those items in their container, regardless of TalkBack’s verbosity settings. So given that that information is so important, I incorporated it into the items’ names. I hope to remove that at some point if I can get TalkBack to announce it automatically.
Providing a usable screen reader experience was made practical thanks to the features described at Build accessible apps with semantic properties. The app made good use of SemanticProperties.Description, SemanticProperties.Hint, SemanticProperties.HeadingLevel, AutomationProperties.IsInAccessibleTree, and very importantly, also used SemanticScreenReader.Default.Announce() to have helpful custom announcements made following specific actions taken in the game.
Note: Careful consideration is required around making custom announcements, as too many of those can render an app very difficult to use.
Given that the playing cards’ suit symbols are so small, and in some cases so similar between suits, it is essential for players to be provided with a means to make everything shown in the game bigger. While Android itself provides helpful magnification, I felt it was important for the solitaire app to provide more options.
As such, the game’s Settings page provides a zoom level, to magnify everything in the game across two independently scrollable areas. This means that the target card piles can be kept in view while portions of the dealt card piles are scrolled around to bring whatever is of most interest in those dealt card piles into view.
Reacting to player feedback
In order to have the new Accessible Solitaire game published at the Google Play Store, I needed to find at least twenty people who would be prepared to test the app for a while, and to provide feedback. This turned out to be far more helpful to me than I anticipated. The players’ feedback included many great suggestions, some of which related to the general solitaire game-playing experience, and some being specific to the accessibility of the game. I did update the app during the testing period a number of times based on feedback, and I’m tracking the suggestions I’ve yet to get to at Accessible Solitaire feature suggestions.
I am extremely grateful to all the people who devoted their time and effort in order to help me make the game available to everyone.
One of the most important areas of feedback related to the in-app zoom feature. A number of people raised concerns that while the feature technically worked, many players would not enjoy having to perform the significant amount of scrolling required to play the game.
One person suggested perhaps a long-press gesture might be added to zoom in on a card. That really did seem like a great idea, and one that turned out to be quite interesting to explore. While trying out various touch gesture options, I found a pinch gesture on a card quite difficult to perform, and a double-tap gesture introduced a slight delay when selecting a card with a single-tap gesture, so perhaps a long-press gesture really was the best choice. In the end I found I couldn’t get the .NET MAUI binding for a long-press gesture to work reliably once cards had been moved between CollectionViews, so I didn’t end up going with that. Rather I added an option to have a Zoom Card button shown on each card. I realise that that approach has accessibility issues of its own given the size of the button, but at least it’s accessible to the TalkBack screen reader, and all the app’s features must be accessible to TalkBack. I’m sure I’ll be revisiting this Zoom Card feature in the future.
Another interesting topic to explore was around the contents shown on a card. Rather than only having one representation for a card’s details, perhaps in addition other representations might be helpful. To get the ball rolling on this discussion, I added an option to not show the traditional collection of small suit symbols, and instead, show one large suit symbol and one large number or letter representing the rank. I’m looking forward to receiving more feedback in the future around other helpful representations of the card.
While I was adding the above feature, I took the opportunity to have the app support the Android Dark Mode setting. So now if the app’s started while the Android Dark Mode feature is on, it will show light-on-dark versions of the cards rather than dark-on-light.
Am I ignoring Google’s reports relating to the accessibility of the app?
Whenever I submit an update of the app to be published, Google helpfully provides me with a report detailing potential accessibility issues with the app. The issues reported by Google fell in the following three areas.
Content labelling
The report suggested that the game’s Menu button and Next Card button might not have labels readable by screen readers, yet I’d specifically given them localisable accessible names, and tested them with the TalkBack screen reader. So, until I learn otherwise from players, I’m going to assume those buttons are satisfactorily labelled.
Touch target size
This issue related to the size of interactable elements, and is a fair point given that some elements do have very small hit targets. Some of those element sizes are the defaults provided by the combination of the .NET MAUI framework and Android, for example, the size of a switch, a picker, and a button on the Settings page. Typically I do not try to override the framework’s default sizing.
Other controls with hit target issues are very much under my control, for example, a partially obscured card in a dealt card pile. One player testing the app raised a very interesting idea of having a tap in any of the face-down cards in a dealt card pile select the nearest face-up card in that pile. This is something I intend to explore further, but for this first release of the app I do acknowledge that hit targets will be problematic for some players.?
Low contrast
Most of the low contrast issues reported related to visuals shown in the main area of the game, once it had become very dark (and low contrast) because the app’s menu flyout had appeared. I’m not planning on making changes to the app in response to this reported issue.
The only other low contrast issue reported related to the empty area where upturned cards will be placed, and now that this has been highlighted for me, I do consider it a bug. I’ve logged this bug at GitHub to help me track fixing that.
So what happens now?
With the help of the people who’ve already tried out the app and provided feedback, I feel I’m now at a point where I can reach out to organisations and individuals who are familiar with various accessibility-related features and invite more feedback on how I should prioritise the improvements that I make to the app. I’m sure many improvements are necessary, but I do hope this first release of the app will demonstrate its potential for providing an accessible and fun solitaire game-playing experience for all.
I’m also intending to explore other interaction experiences, such as controlling the game through speech and a switch device. This first release of the app did not explore those experiences, but I am pleased that having run the app with both the Android Voice Access and Universal Switch Access features turned on, the results seem encouraging.
And of course, very importantly, I’d like to start exploring the possibility of releasing a version of the game for iOS. Out of curiosity, I did build my new app for iOS and found it started up fine, which is another very encouraging development.
So if you, or someone you know, might be interested in the potential for the app to provide fun game-playing experiences that aren’t available through other apps, please do try out the app and send feedback my way. I’ll do my best to update the app in whatever ways might be helpful.
And of course – please do spread the word!
The app’s available at Accessible Solitaire for Android.
All the best,
Guy
Exploring how to make apps more accessible to more people, and sharing all I learn.
3 个月Thanks for sharing the post @tomreemer. Since I wrote the article, I've been exploring what it would take to get the .NET Maui app running on iOS. Overall it was fairly straightforward, but I couldn't get the same code to work for both the Android and iOS screen readers. So the only platform #if now in the app relates to the screen reader experience. The images here show the iOS version of the app with its in-app zoom, VoiceOver screen reader caption, Voice Control showing element names, and Switch Control scan moving through the cards. For the first time this afternoon I completed a full game using only the iOS Switch Control feature, which really was rewarding. Next week I might look into what it would take to get the iOS version of the app published. The app's perf leaves a bit to be desired at the moment, but I'd like to start getting feedback on the iOS version to help me learn where to focus next.