diff options
3 files changed, 39 insertions, 4 deletions
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/AccessibilityDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/AccessibilityDetector.java index 6162c38..3572e89 100644 --- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/AccessibilityDetector.java +++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/AccessibilityDetector.java @@ -18,12 +18,14 @@ package com.android.tools.lint.checks; import static com.android.SdkConstants.ANDROID_URI; import static com.android.SdkConstants.ATTR_CONTENT_DESCRIPTION; +import static com.android.SdkConstants.ATTR_HINT; import static com.android.SdkConstants.ATTR_IMPORTANT_FOR_ACCESSIBILITY; import static com.android.SdkConstants.IMAGE_BUTTON; import static com.android.SdkConstants.IMAGE_VIEW; import static com.android.SdkConstants.VALUE_NO; import com.android.annotations.NonNull; +import com.android.annotations.Nullable; import com.android.tools.lint.detector.api.Category; import com.android.tools.lint.detector.api.Issue; import com.android.tools.lint.detector.api.LayoutDetector; @@ -37,6 +39,7 @@ import org.w3c.dom.Element; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; /** * Check which looks for accessibility problems like missing content descriptions @@ -53,7 +56,18 @@ public class AccessibilityDetector extends LayoutDetector { "Non-textual widgets like ImageViews and ImageButtons should use the " + "`contentDescription` attribute to specify a textual description of " + "the widget such that screen readers and other accessibility tools " + - "can adequately describe the user interface.", + "can adequately describe the user interface.\n" + + "\n" + + "Note that elements in application screens that are purely decorative " + + "and do not provide any content or enable a user action should not " + + "have accessibility content descriptions. In this case, just suppress the " + + "lint warning with a tools:ignore=\"ContentDescription\" attribute.\n" + + "\n" + + "Note that for text fields, you should not set both the `hint` and the " + + "`contentDescription` attributes since the hint will never be shown. Just " + + "set the `hint`. See " + + "http://developer.android.com/guide/topics/ui/accessibility/checklist.html#special-cases.", + Category.A11Y, 3, Severity.WARNING, @@ -78,6 +92,22 @@ public class AccessibilityDetector extends LayoutDetector { } @Override + @Nullable + public Collection<String> getApplicableAttributes() { + return Collections.singletonList(ATTR_CONTENT_DESCRIPTION); + } + + @Override + public void visitAttribute(@NonNull XmlContext context, @NonNull Attr attribute) { + Element element = attribute.getOwnerElement(); + if (element.hasAttributeNS(ANDROID_URI, ATTR_HINT)) { + context.report(ISSUE, element, context.getLocation(attribute), + "Do not set both contentDescription and hint: the contentDescription " + + "will mask the hint", null); + } + } + + @Override public void visitElement(@NonNull XmlContext context, @NonNull Element element) { if (!element.hasAttributeNS(ANDROID_URI, ATTR_CONTENT_DESCRIPTION)) { // Ignore views that are explicitly not important for accessibility diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/AccessibilityDetectorTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/AccessibilityDetectorTest.java index 9f8d13d..b78455d 100644 --- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/AccessibilityDetectorTest.java +++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/AccessibilityDetectorTest.java @@ -33,8 +33,10 @@ public class AccessibilityDetectorTest extends AbstractCheckTest { "res/layout/accessibility.xml:5: Warning: [Accessibility] Missing contentDescription attribute on image [ContentDescription]\n" + " <ImageButton android:importantForAccessibility=\"yes\" android:id=\"@+id/android_logo2\" android:layout_width=\"wrap_content\" android:layout_height=\"wrap_content\" android:src=\"@drawable/android_button\" android:focusable=\"false\" android:clickable=\"false\" android:layout_weight=\"1.0\" />\n" + " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - "0 errors, 2 warnings\n" + - "", + "res/layout/accessibility.xml:9: Warning: Do not set both contentDescription and hint: the contentDescription will mask the hint [ContentDescription]\n" + + " <EditText android:hint=\"@string/label\" android:id=\"@+android:id/summary\" android:contentDescription=\"@string/label\" />\n" + + " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + "0 errors, 3 warnings\n", lintProject("res/layout/accessibility.xml")); } diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/layout/accessibility.xml b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/layout/accessibility.xml index c00a880..3f45c26 100644 --- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/layout/accessibility.xml +++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/layout/accessibility.xml @@ -1,9 +1,12 @@ <?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/newlinear" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/newlinear" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:text="Button" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> <ImageView android:id="@+id/android_logo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/android_button" android:focusable="false" android:clickable="false" android:layout_weight="1.0" /> <ImageButton android:importantForAccessibility="yes" android:id="@+id/android_logo2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/android_button" android:focusable="false" android:clickable="false" android:layout_weight="1.0" /> <Button android:text="Button" android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> <Button android:id="@+android:id/summary" android:contentDescription="@string/label" /> <ImageButton android:importantForAccessibility="no" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/android_button" android:focusable="false" android:clickable="false" android:layout_weight="1.0" /> + <EditText android:hint="@string/label" android:id="@+android:id/summary" android:contentDescription="@string/label" /> + <EditText android:id="@+android:id/summary" android:contentDescription="@string/label" /> + <EditText tools:ignore="ContentDescription" android:hint="@string/label" android:id="@+android:id/summary" android:contentDescription="@string/label" /> </LinearLayout> |