Does Cursor Generate Accessible Android Apps?

Reading time: about 6 minutes

Published

Does Cursor Create Accessible Android Apps?

Testing Accessibility of AI-generated Apps (3 part series)

  1. 1. Does Gemini Generate Accessible Android Apps?
  2. 2. Does Junie Create Accessible Android Apps?
  3. 3. Does Cursor Generate Accessible Android Apps?
  1. The App
  2. Testing Process
  3. The Problems I Found
  4. In Summary
  5. Links in Blog Post

I've been testing the accessibility of Android code created by different AI tools, and this time, it's time to test Cursor. I know it's not the most ideal tool for Android development, but I still wanted to test it.

If you've read the previous posts in the series, you know the drill - I'll generate the app code and then test it. There are links to the blog post at the top of this post if you want to refresh your memory or if you haven't read the previous blog posts. In them, I also explain why I'm doing this.

So, let's get to the actual thing we're here for.

The App

This time, I did only one round of tests. It's not that I got lazy or anything - using Cursor was just so annoying that I decided to do only one test.

I used a combination of Android Studio and Cursor editor to construct the app. I created the project with Android Studio, opened it in Cursor, and wrote the app prompt. Then I moved to AS, tried to build the project, fixed issues with dependencies, and built it again. Then I realized it didn't have proper navigation, so I moved back to Cursor and did some additional prompting. After several similar rounds, I finally got the app to my phone and the testing phase.

There were some good and not-so-great sides to using Cursor from an Android development point of view. The setup was smooth, but once I got to do some actual work with Android, the code had many problems. For example, it didn't add dependencies at all, and I had to add them by hand. It also added some non-existent parameters to Composable functions.

So yeah, compared to Gemini and Junie (tools I've tested so far), I would go with either of those for Android development instead of Cursor.

Prompt

The prompt I gave to Cursor was:

Can you generate UI screens for an app, in which user can keep track of their yarn stash and knitting needles per size and type? It should contain the following screens: Home screen, where user can add both yarn and needles, a list screen for yarn, a details screen for individual yarn, a list screen for knitting needles, a details screen for knitting needles.

The information to store about yarn consists of following: Brand name, yarn name, colorway, yarage in meters, weight of skein, amount of skeins, picture. Information for knitting needles consists of the following: Brand name, knitting needles size in mm, type (single pointed, double pointed, circular). The type should be a dropdown.

The app screens should be accessible for users with alternative navigation (switch device, keyboard, voice navigation), as well as screen readers, and it should work well in both vertical and landscape orientations, as well as with larger font sizes.

It should follow all Material3 best practices.

I also asked for a summary of how accessibility was considered. Here's a short version without every example it gave.

  1. Content descriptions:
    • All interactive elements have descriptive content descriptions
  2. Semantic Information
    • In detail screens, we use semantics modifier to provide additional context. This helps screen readers understand the relationship between labels and values in detail items.
  3. Material 3 Design
    • Using Material 3 components ensures proper contrast ratios
    • Surface colors and text colors follow Material 3 guidelines for readability
    • Proper spacing and touch targets for interactive elements
  4. Navigation
    • Clear navigation patterns with back buttons
    • Consistent navigation structure
    • Auto-mirrored icons for RTL support
  5. Text Hierarchy
    • Using appropriate typography styles
    • Clear visual hierarchy helps users understand the content structure
  6. Interactive Elements
    • All clickable areas are properly sized for touch targets
    • Cards are used to group related information
    • Clear visual feedback for interactive elements

I don't agree with all of them being something that improves accessibility, as we'll see later in the blog post, but most are legit things - both from accessibility and this app's code point of view.

The UI

Here's a short video of how the app turned out:

Testing Process

After building the app, I ran a limited set of manual accessibility tests on the app. I used my Pixel Fold, as I have everything for testing set up on it. The tools, assistive technologies, and accessibility settings I tested the app with were:

The Problems I Found

Once again, there were some accessibility problems. Many of them were similar to what Gemini and Junie created. Let's look at the accessibility problems more closely.

Content Descriptions Are Not Going Anywhere

As with Gemini and Junie, Cursor also added extra content descriptions. While in this case, the content descriptions were the same as the text content, grouping the text with mergeDescendants would have accomplished the same result without adding two ways of going through the content: First as the content description, and then as separate texts.

In practice, that means that the user with a screen reader first navigates through the following texts (content descriptions): "Brand: Brand A", "Yarn name: Yarn 1," and so forth. The next round would be "Brand", "Brand A", "Yarn name", and "Yarn 1", which adds redundant information to the screen. With this amount of information, it would probably be just annoying, but it would become frustrating with more details on screen.

Let's look at the code behind this problem. This code snippet is from the list screen for different yarns. I've omitted irrelevant parts:

Column(
  modifier = Modifier
    .semantics { 
      contentDescription = "$label: $value"
    }
) {
  Text(
    text = label
  )
  Text(
    text = value
  )
}

Better code would be:

Column(
  modifier = Modifier
    .semantics(mergeDescendants = true) {} <-- Change to this
) {
  Text(
    text = label
  )
  Text(
    text = value
  )
}

Scrolling is Not Supported

Increasing font size reveals that the screens don't support scrolling if the content doesn't fit into the view. That's not optimal for the app, as its sole purpose is to list data. These problems become apparent when scaling font size up even sooner than with the default font size, as the content takes more space.

Surprisingly, the app doesn't prevent landscape orientation. However, as scrolling is not supported, every single screen is unusable, as there is less vertical space when orientation is horizontal.

So, the solution here is to add scrollability to all screens - even those that don't require it with the default font size most developers use when developing an app.

Font Scaling Causes Further Problems

When increasing the font size, fonts scale appropriately. However, as usual, the top app bar doesn't stretch to accommodate a big font size with two lines of text. This is a common issue, and it's more of a problem with the TopAppBar-component's default values.

One way to fix the issue would be using TopAppBar's expandedHeight-property together with different heights for smaller and bigger font scales. For this simple app, the straightforward solution could look like the following:

@Composable
fun NeedlesDetailScreen(...) {
    val fontScale = LocalConfiguration.current.fontScale
    val topAppBarHeight = if (fontScale < 1.5)
      TopAppBarDefaults.TopAppBarExpandedHeight
    else 
      TopAppBarDefaults.TopAppBarExpandedHeight * 1.5f
  }

  Scaffold(
    topBar = {
      TopAppBar(
      ....
        expandedHeight = topAppBarHeight
      )
    }
  ) {...}
}

This problem with TopAppBar not scaling with bigger font sizes is not visible with every phone, so in general, this issue might be missed when testing, and thus, there are not many fixes for AI to learn from. For example, with this test app, I could see it with the Pixel 8 Pro emulator but not with the Pixel Fold I'm using.

In Summary

While using Cursor was a pain, the code was somewhat ok. And when I say ok, I mean that it had the usual suspects, so, accessibility problems, but nothing major or additional.

As I mentioned in the previous blog post, it's already starting to paint a clear picture of the accessibility of AI-generated Android code. Still, I will do one more test with Claude Code before writing a summary post.

If you want to see the app code, it's available on Github: Cursor Test App.

Links in Blog Post