Incorrect or Missing Role Declaration

Id IncorrectorMissingRoleDeclaration
Summary Elements expose wrong or absent roles, misrepresenting their function
Severity Warning
Category Assistive Technologies / Semantic Roles and States
Affects Resource files and Kotlin and Java files
Implementation Custom lint rule – for missing roles, detect when interactive views (e.g., TextView or ImageView with clickable="true" or with an OnClickListener) do not use appropriate widget types (Button, CheckBox, Switch, etc.) or lack explicit semantic role assignments (setAccessibilityClassName, AccessibilityNodeInfo.roleDescription, Modifier.semantics { role = … }); has limitations for incorrect roles since developer intent is often ambiguous, so manual testing is still required to validate semantic accuracy in custom or dynamic cases.

Symptom

UI elements are implemented using wrong semantic components (e.g., ToggleButton instead of Button) or lack proper semantic role definition through AccessibilityNodeInfo.className, AccessibilityNodeInfo.roleDescription, View.setAccessibilityClassName(), AccessibilityAction, Modifier.semantics { role = Role.Button }, Role.Button/Role.Checkbox/Role.Image, or other accessibility attributes, causing screen readers to announce incorrect interaction patterns, states, or generic element types.

Rationale

Misleads assistive technology users about expected behavior and available interactions, as screen readers announce the wrong element type and associated states or fail to identify the element's function, leading to confusion and failed interaction attempts when the actual behavior doesn't match the announced semantics.

Examples

XML Layout Example

<!-- Button functionality implemented with TextView -->
<TextView
    android:layout_width="wrap_content"
    android:layout_height="48dp"
    android:text="Submit"
    android:background="@drawable/button_background"
    android:clickable="true"
    android:gravity="center" />
<!-- Missing: android:accessibilityClassName="android.widget.Button" -->
<!-- Or use Button for correct semantic role -->

Kotlin Code Example

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val customView = findViewById<View>(R.id.custom_view)
        customView.setOnClickListener {
            // Click functionality without Role.Button
        }
        // Missing: customView.accessibilityClassName = Button::class.java.name
    }
}

GitHub issues under this tag