| 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. |
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.
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.
<!-- 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 -->
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
}
}