From 62aa580de7ea3c24b7ee7025f575d5da0007bbf5 Mon Sep 17 00:00:00 2001
From: axelherbstreith <75120552+axelherbstreith@users.noreply.github.com>
Date: Tue, 2 Feb 2021 16:17:14 +0100
Subject: [PATCH] Accessibility: Statistics Blocks Enhancements
 (EXPOSUREAPP-4845) (#2256)

* added announcements for individual statistics

* added speech output for individual information on key submission statistics card

* enhanced speech output for InfectionsCard

* updated speech output for statistics incidence card

* removed typo

* updated speech output for seven day r value card

* enhanced speech output to announce complete cord when focusing it

* linting

* fixed announcement issue on some phones

* linting

* removed test transations

* changed accessibility string creation to string builder

* changed terminology

* used extension functions for more comprehensive code

* linting max lines

* updated string on seven day r value card

* renamed extension method

* linting max lines

Co-authored-by: harambasicluka <64483219+harambasicluka@users.noreply.github.com>
Co-authored-by: BMItter <46747780+BMItter@users.noreply.github.com>
Co-authored-by: Ralf Gehrer <ralfgehrer@users.noreply.github.com>
---
 .../ui/homecards/cards/IncidenceCard.kt       | 33 +++++++++++++
 .../ui/homecards/cards/InfectionsCard.kt      | 46 ++++++++++++++++++
 .../ui/homecards/cards/KeySubmissionsCard.kt  | 47 +++++++++++++++++++
 .../ui/homecards/cards/SevenDayRValueCard.kt  | 33 +++++++++++++
 .../statistics/util/AccessibilityHelper.kt    | 15 ++++++
 .../util/StringBuilderExtension.kt            |  9 ++++
 ...home_statistics_cards_incidence_layout.xml |  3 ++
 ...ome_statistics_cards_infections_layout.xml |  5 ++
 ...statistics_cards_keysubmissions_layout.xml |  5 ++
 ...statistics_cards_sevendayrvalue_layout.xml |  2 +
 .../src/main/res/values-de/strings.xml        |  5 ++
 .../src/main/res/values/strings.xml           |  7 ++-
 12 files changed, 209 insertions(+), 1 deletion(-)
 create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/StringBuilderExtension.kt

diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/statistics/ui/homecards/cards/IncidenceCard.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/statistics/ui/homecards/cards/IncidenceCard.kt
index d5433c1fc..fafe09299 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/statistics/ui/homecards/cards/IncidenceCard.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/statistics/ui/homecards/cards/IncidenceCard.kt
@@ -3,10 +3,15 @@ package de.rki.coronawarnapp.statistics.ui.homecards.cards
 import android.view.ViewGroup
 import de.rki.coronawarnapp.R
 import de.rki.coronawarnapp.databinding.HomeStatisticsCardsIncidenceLayoutBinding
+import de.rki.coronawarnapp.server.protocols.internal.stats.KeyFigureCardOuterClass
 import de.rki.coronawarnapp.statistics.IncidenceStats
+import de.rki.coronawarnapp.statistics.StatsItem
 import de.rki.coronawarnapp.statistics.ui.homecards.StatisticsCardAdapter
 import de.rki.coronawarnapp.statistics.util.formatStatisticalValue
+import de.rki.coronawarnapp.statistics.util.getContentDescriptionForTrends
 import de.rki.coronawarnapp.statistics.util.getLocalizedSpannableString
+import de.rki.coronawarnapp.util.StringBuilderExtension.appendWithLineBreak
+import de.rki.coronawarnapp.util.StringBuilderExtension.appendWithTrailingSpace
 import de.rki.coronawarnapp.util.formatter.getPrimaryLabel
 
 class IncidenceCard(parent: ViewGroup) :
@@ -32,12 +37,40 @@ class IncidenceCard(parent: ViewGroup) :
         }
 
         with(item.stats as IncidenceStats) {
+
+            incidenceContainer.contentDescription =
+                buildAccessibilityStringForIncidenceCard(item.stats, sevenDayIncidence)
+
             primaryLabel.text = getPrimaryLabel(context)
             primaryValue.text = getLocalizedSpannableString(
                 context,
                 formatStatisticalValue(context, sevenDayIncidence.value, sevenDayIncidence.decimals)
             )
+
+            primaryValue.contentDescription = StringBuilder()
+                .appendWithTrailingSpace(context.getString(R.string.statistics_explanation_seven_day_incidence_title))
+                .appendWithTrailingSpace(getPrimaryLabel(context))
+                .appendWithTrailingSpace(formatStatisticalValue(context, sevenDayIncidence.value,
+                    sevenDayIncidence.decimals))
+                .append(getContentDescriptionForTrends(context, sevenDayIncidence.trend))
+
             trendArrow.setTrend(sevenDayIncidence.trend, sevenDayIncidence.trendSemantic)
         }
     }
+
+    private fun buildAccessibilityStringForIncidenceCard(
+        item: StatsItem,
+        sevenDayIncidence: KeyFigureCardOuterClass.KeyFigure
+    ): StringBuilder {
+
+        return StringBuilder()
+            .appendWithTrailingSpace(context.getString(R.string.accessibility_statistics_card_announcement))
+            .appendWithLineBreak(context.getString(R.string.statistics_explanation_seven_day_incidence_title))
+            .appendWithTrailingSpace(item.getPrimaryLabel(context))
+            .appendWithTrailingSpace(formatStatisticalValue(context, sevenDayIncidence.value,
+                sevenDayIncidence.decimals))
+            .appendWithTrailingSpace(context.getString(R.string.statistics_card_incidence_value_description))
+            .appendWithLineBreak(getContentDescriptionForTrends(context, sevenDayIncidence.trend))
+            .append(context.getString(R.string.accessibility_statistics_card_navigation_information))
+    }
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/statistics/ui/homecards/cards/InfectionsCard.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/statistics/ui/homecards/cards/InfectionsCard.kt
index c1fad337f..1e7f9bfc3 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/statistics/ui/homecards/cards/InfectionsCard.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/statistics/ui/homecards/cards/InfectionsCard.kt
@@ -3,10 +3,15 @@ package de.rki.coronawarnapp.statistics.ui.homecards.cards
 import android.view.ViewGroup
 import de.rki.coronawarnapp.R
 import de.rki.coronawarnapp.databinding.HomeStatisticsCardsInfectionsLayoutBinding
+import de.rki.coronawarnapp.server.protocols.internal.stats.KeyFigureCardOuterClass
 import de.rki.coronawarnapp.statistics.InfectionStats
+import de.rki.coronawarnapp.statistics.StatsItem
 import de.rki.coronawarnapp.statistics.ui.homecards.StatisticsCardAdapter
 import de.rki.coronawarnapp.statistics.util.formatStatisticalValue
 import de.rki.coronawarnapp.util.formatter.getPrimaryLabel
+import de.rki.coronawarnapp.statistics.util.getContentDescriptionForTrends
+import de.rki.coronawarnapp.util.StringBuilderExtension.appendWithLineBreak
+import de.rki.coronawarnapp.util.StringBuilderExtension.appendWithTrailingSpace
 
 class InfectionsCard(parent: ViewGroup) :
     StatisticsCardAdapter.ItemVH<StatisticsCardItem, HomeStatisticsCardsInfectionsLayoutBinding>(
@@ -31,11 +36,52 @@ class InfectionsCard(parent: ViewGroup) :
         }
 
         with(item.stats as InfectionStats) {
+
+            infectionsContainer.contentDescription =
+                buildAccessibilityStringForInfectionsCard(item.stats, newInfections, sevenDayAverage, total)
+
             primaryLabel.text = getPrimaryLabel(context)
             primaryValue.text = formatStatisticalValue(context, newInfections.value, newInfections.decimals)
+            primaryValue.contentDescription = StringBuilder()
+                .appendWithTrailingSpace(getPrimaryLabel(context))
+                .appendWithTrailingSpace(formatStatisticalValue(context, newInfections.value, newInfections.decimals))
+                .append(context.getString(R.string.statistics_card_infections_title))
+
             secondaryValue.text = formatStatisticalValue(context, sevenDayAverage.value, sevenDayAverage.decimals)
+            secondaryValue.contentDescription = StringBuilder()
+                .appendWithTrailingSpace(context.getString(R.string.statistics_card_infections_secondary_label))
+                .appendWithTrailingSpace(formatStatisticalValue(context, sevenDayAverage.value,
+                    sevenDayAverage.decimals))
+                .appendWithTrailingSpace(context.getString(R.string.statistics_card_infections_title))
+                .append(getContentDescriptionForTrends(context, sevenDayAverage.trend))
+
             tertiaryValue.text = formatStatisticalValue(context, total.value, total.decimals)
+            tertiaryValue.contentDescription = StringBuilder()
+                .appendWithTrailingSpace(context.getString(R.string.statistics_card_infections_tertiary_label))
+                .appendWithTrailingSpace(formatStatisticalValue(context, total.value, total.decimals))
+                .append(context.getString(R.string.statistics_card_infections_title))
+
             trendArrow.setTrend(sevenDayAverage.trend, sevenDayAverage.trendSemantic)
         }
     }
+
+    private fun buildAccessibilityStringForInfectionsCard(
+        item: StatsItem,
+        newInfections: KeyFigureCardOuterClass.KeyFigure,
+        sevenDayAverage: KeyFigureCardOuterClass.KeyFigure,
+        total: KeyFigureCardOuterClass.KeyFigure
+    ): StringBuilder {
+
+        return StringBuilder()
+            .appendWithTrailingSpace(context.getString(R.string.accessibility_statistics_card_announcement))
+            .appendWithLineBreak(context.getString(R.string.statistics_card_infections_title))
+            .appendWithTrailingSpace(item.getPrimaryLabel(context))
+            .appendWithLineBreak(formatStatisticalValue(context, newInfections.value, newInfections.decimals))
+            .appendWithTrailingSpace(context.getString(R.string.statistics_card_infections_secondary_label))
+            .appendWithTrailingSpace(formatStatisticalValue(context, sevenDayAverage.value, sevenDayAverage.decimals))
+            .appendWithLineBreak(getContentDescriptionForTrends(context, sevenDayAverage.trend))
+            .appendWithTrailingSpace(context.getString(R.string.statistics_card_infections_tertiary_label))
+            .appendWithLineBreak(formatStatisticalValue(context, total.value, total.decimals))
+            .append(context.getString(R.string.accessibility_statistics_card_navigation_information))
+    }
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/statistics/ui/homecards/cards/KeySubmissionsCard.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/statistics/ui/homecards/cards/KeySubmissionsCard.kt
index 08218528f..a722f23d2 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/statistics/ui/homecards/cards/KeySubmissionsCard.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/statistics/ui/homecards/cards/KeySubmissionsCard.kt
@@ -3,9 +3,14 @@ package de.rki.coronawarnapp.statistics.ui.homecards.cards
 import android.view.ViewGroup
 import de.rki.coronawarnapp.R
 import de.rki.coronawarnapp.databinding.HomeStatisticsCardsKeysubmissionsLayoutBinding
+import de.rki.coronawarnapp.server.protocols.internal.stats.KeyFigureCardOuterClass
 import de.rki.coronawarnapp.statistics.KeySubmissionsStats
+import de.rki.coronawarnapp.statistics.StatsItem
 import de.rki.coronawarnapp.statistics.ui.homecards.StatisticsCardAdapter
 import de.rki.coronawarnapp.statistics.util.formatStatisticalValue
+import de.rki.coronawarnapp.statistics.util.getContentDescriptionForTrends
+import de.rki.coronawarnapp.util.StringBuilderExtension.appendWithLineBreak
+import de.rki.coronawarnapp.util.StringBuilderExtension.appendWithTrailingSpace
 import de.rki.coronawarnapp.util.formatter.getPrimaryLabel
 
 class KeySubmissionsCard(parent: ViewGroup) :
@@ -31,11 +36,53 @@ class KeySubmissionsCard(parent: ViewGroup) :
         }
 
         with(item.stats as KeySubmissionsStats) {
+
+            keysubmissionsContainer.contentDescription =
+                buildAccessibilityStringForKeySubmissionsCard(item.stats, keySubmissions, sevenDayAverage, total)
+
             primaryLabel.text = getPrimaryLabel(context)
             primaryValue.text = formatStatisticalValue(context, keySubmissions.value, keySubmissions.decimals)
+            primaryValue.contentDescription = StringBuilder()
+                .appendWithTrailingSpace(getPrimaryLabel(context))
+                .appendWithTrailingSpace(formatStatisticalValue(context, keySubmissions.value, keySubmissions.decimals))
+                .append(context.getString(R.string.statistics_card_submission_title))
+
             secondaryValue.text = formatStatisticalValue(context, sevenDayAverage.value, sevenDayAverage.decimals)
+            secondaryValue.contentDescription = StringBuilder()
+                .appendWithTrailingSpace(context.getString(R.string.statistics_card_infections_secondary_label))
+                .appendWithTrailingSpace(formatStatisticalValue(context, sevenDayAverage.value,
+                    sevenDayAverage.decimals))
+                .appendWithTrailingSpace(context.getString(R.string.statistics_card_submission_title))
+                .append(getContentDescriptionForTrends(context, sevenDayAverage.trend))
+
             tertiaryValue.text = formatStatisticalValue(context, total.value, total.decimals)
+            tertiaryValue.contentDescription = StringBuilder()
+                .appendWithTrailingSpace(context.getString(R.string.statistics_card_infections_tertiary_label))
+                .appendWithTrailingSpace(formatStatisticalValue(context, total.value, total.decimals))
+                .append(context.getString(R.string.statistics_card_submission_title))
+
             trendArrow.setTrend(sevenDayAverage.trend, sevenDayAverage.trendSemantic)
         }
     }
+
+    private fun buildAccessibilityStringForKeySubmissionsCard(
+        item: StatsItem,
+        keySubmissions: KeyFigureCardOuterClass.KeyFigure,
+        sevenDayAverage: KeyFigureCardOuterClass.KeyFigure,
+        total: KeyFigureCardOuterClass.KeyFigure
+    ): StringBuilder {
+
+        return StringBuilder()
+            .appendWithTrailingSpace(context.getString(R.string.accessibility_statistics_card_announcement))
+            .appendWithLineBreak(context.getString(R.string.statistics_card_submission_title))
+            .appendWithTrailingSpace(item.getPrimaryLabel(context))
+            .appendWithLineBreak(formatStatisticalValue(context, keySubmissions.value, keySubmissions.decimals))
+            .appendWithTrailingSpace(context.getString(R.string.statistics_card_infections_secondary_label))
+            .appendWithTrailingSpace(formatStatisticalValue(context, sevenDayAverage.value, sevenDayAverage.decimals))
+            .appendWithLineBreak(getContentDescriptionForTrends(context, sevenDayAverage.trend))
+            .appendWithTrailingSpace(context.getString(R.string.statistics_card_infections_tertiary_label))
+            .appendWithTrailingSpace(formatStatisticalValue(context, total.value, total.decimals))
+            .appendWithLineBreak(context.getString(R.string.statistics_card_submission_bottom_text))
+            .append(context.getString(R.string.accessibility_statistics_card_navigation_information))
+    }
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/statistics/ui/homecards/cards/SevenDayRValueCard.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/statistics/ui/homecards/cards/SevenDayRValueCard.kt
index b21614ef3..cc384a068 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/statistics/ui/homecards/cards/SevenDayRValueCard.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/statistics/ui/homecards/cards/SevenDayRValueCard.kt
@@ -3,10 +3,15 @@ package de.rki.coronawarnapp.statistics.ui.homecards.cards
 import android.view.ViewGroup
 import de.rki.coronawarnapp.R
 import de.rki.coronawarnapp.databinding.HomeStatisticsCardsSevendayrvalueLayoutBinding
+import de.rki.coronawarnapp.server.protocols.internal.stats.KeyFigureCardOuterClass
 import de.rki.coronawarnapp.statistics.SevenDayRValue
+import de.rki.coronawarnapp.statistics.StatsItem
 import de.rki.coronawarnapp.statistics.ui.homecards.StatisticsCardAdapter
 import de.rki.coronawarnapp.statistics.util.formatStatisticalValue
+import de.rki.coronawarnapp.statistics.util.getContentDescriptionForTrends
 import de.rki.coronawarnapp.statistics.util.getLocalizedSpannableString
+import de.rki.coronawarnapp.util.StringBuilderExtension.appendWithLineBreak
+import de.rki.coronawarnapp.util.StringBuilderExtension.appendWithTrailingSpace
 import de.rki.coronawarnapp.util.formatter.getPrimaryLabel
 
 class SevenDayRValueCard(parent: ViewGroup) :
@@ -32,12 +37,40 @@ class SevenDayRValueCard(parent: ViewGroup) :
         }
 
         with(item.stats as SevenDayRValue) {
+
+            sevenDayRValueContainer.contentDescription =
+                buildAccessibilityStringForSevenDayRValueCard(item.stats, reproductionNumber)
+
             primaryLabel.text = getPrimaryLabel(context)
             primaryValue.text = getLocalizedSpannableString(
                 context,
                 formatStatisticalValue(context, reproductionNumber.value, reproductionNumber.decimals)
             )
+
+            primaryValue.contentDescription = StringBuilder()
+                .appendWithTrailingSpace(context.getString(R.string.statistics_title_reproduction))
+                .appendWithTrailingSpace(getPrimaryLabel(context))
+                .appendWithTrailingSpace(formatStatisticalValue(context, reproductionNumber.value,
+                    reproductionNumber.decimals))
+                .append(getContentDescriptionForTrends(context, reproductionNumber.trend))
+
             trendArrow.setTrend(reproductionNumber.trend, reproductionNumber.trendSemantic)
         }
     }
+
+    private fun buildAccessibilityStringForSevenDayRValueCard(
+        item: StatsItem,
+        reproductionNumber: KeyFigureCardOuterClass.KeyFigure
+    ): StringBuilder {
+
+        return StringBuilder()
+            .appendWithTrailingSpace(context.getString(R.string.accessibility_statistics_card_announcement))
+            .appendWithLineBreak(context.getString(R.string.statistics_title_reproduction))
+            .appendWithTrailingSpace(item.getPrimaryLabel(context))
+            .appendWithTrailingSpace(formatStatisticalValue(context, reproductionNumber.value,
+                reproductionNumber.decimals))
+            .appendWithTrailingSpace(context.getString(R.string.statistics_reproduction_average))
+            .appendWithLineBreak(getContentDescriptionForTrends(context, reproductionNumber.trend))
+            .append(context.getString(R.string.accessibility_statistics_card_navigation_information))
+    }
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/statistics/util/AccessibilityHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/statistics/util/AccessibilityHelper.kt
index 1c9bff679..ac2bc0881 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/statistics/util/AccessibilityHelper.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/statistics/util/AccessibilityHelper.kt
@@ -3,7 +3,9 @@ package de.rki.coronawarnapp.statistics.util
 import android.content.Context
 import android.text.SpannableString
 import android.text.style.LocaleSpan
+import de.rki.coronawarnapp.R
 import de.rki.coronawarnapp.contactdiary.util.getLocale
+import de.rki.coronawarnapp.server.protocols.internal.stats.KeyFigureCardOuterClass
 
 /**
  * returns localized spannable string so that screen readers read out decimal values appropriately
@@ -11,3 +13,16 @@ import de.rki.coronawarnapp.contactdiary.util.getLocale
 fun getLocalizedSpannableString(context: Context, source: String) = SpannableString(source).apply {
     setSpan(LocaleSpan(context.getLocale()), 0, this.length, 0)
 }
+
+fun getContentDescriptionForTrends(
+    context: Context,
+    trend: KeyFigureCardOuterClass.KeyFigure.Trend
+): String {
+    return context.getString(
+        when (trend) {
+            KeyFigureCardOuterClass.KeyFigure.Trend.INCREASING -> R.string.statistics_trend_increasing
+            KeyFigureCardOuterClass.KeyFigure.Trend.DECREASING -> R.string.statistics_trend_decreasing
+            else -> R.string.statistics_trend_stable
+        }
+    )
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/StringBuilderExtension.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/StringBuilderExtension.kt
new file mode 100644
index 000000000..e1ac8d8c2
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/StringBuilderExtension.kt
@@ -0,0 +1,9 @@
+package de.rki.coronawarnapp.util
+
+import kotlin.text.StringBuilder
+
+object StringBuilderExtension {
+
+    fun StringBuilder.appendWithTrailingSpace(str: String): StringBuilder = this.append(str).append(" ")
+    fun StringBuilder.appendWithLineBreak(str: String): StringBuilder = this.append(str).append(" \n ")
+}
diff --git a/Corona-Warn-App/src/main/res/layout/home_statistics_cards_incidence_layout.xml b/Corona-Warn-App/src/main/res/layout/home_statistics_cards_incidence_layout.xml
index de5b14693..a2bd07c8f 100644
--- a/Corona-Warn-App/src/main/res/layout/home_statistics_cards_incidence_layout.xml
+++ b/Corona-Warn-App/src/main/res/layout/home_statistics_cards_incidence_layout.xml
@@ -9,6 +9,7 @@
         android:layout_height="wrap_content"
         tools:layout_height="wrap_content"
         tools:layout_width="@dimen/statistics_card_width"
+        android:id="@+id/incidence_container"
         tools:showIn="@layout/home_statistics_cards_basecard_layout">
 
         <androidx.appcompat.widget.AppCompatImageView
@@ -16,6 +17,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:importantForAccessibility="no"
+            android:contentDescription="@null"
             android:src="@drawable/ic_statistics_incidence"
             android:paddingStart="0dp"
             android:paddingEnd="@dimen/spacing_small"
@@ -47,6 +49,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:includeFontPadding="false"
+            android:focusable="true"
             tools:text="98,9" />
 
         <TextView
diff --git a/Corona-Warn-App/src/main/res/layout/home_statistics_cards_infections_layout.xml b/Corona-Warn-App/src/main/res/layout/home_statistics_cards_infections_layout.xml
index 5d227e91f..f44904922 100644
--- a/Corona-Warn-App/src/main/res/layout/home_statistics_cards_infections_layout.xml
+++ b/Corona-Warn-App/src/main/res/layout/home_statistics_cards_infections_layout.xml
@@ -9,6 +9,7 @@
         android:layout_height="wrap_content"
         tools:layout_height="wrap_content"
         tools:layout_width="@dimen/statistics_card_width"
+        android:id="@+id/infections_container"
         tools:showIn="@layout/home_statistics_cards_basecard_layout">
 
         <androidx.appcompat.widget.AppCompatImageView
@@ -16,6 +17,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:importantForAccessibility="no"
+            android:contentDescription="@null"
             android:src="@drawable/ic_main_illustration_infection"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintTop_toTopOf="@id/flow_layout" />
@@ -42,6 +44,7 @@
         <TextView
             android:id="@+id/primary_value"
             style="@style/StatisticsCardPrimaryValue"
+            android:focusable="true"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:includeFontPadding="false"
@@ -58,6 +61,7 @@
         <TextView
             android:id="@+id/secondary_value"
             style="@style/StatisticsCardSecondaryValue"
+            android:focusable="true"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             tools:text="11.981" />
@@ -81,6 +85,7 @@
 
         <TextView
             android:id="@+id/tertiary_value"
+            android:focusable="true"
             style="@style/StatisticsCardSecondaryValue"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
diff --git a/Corona-Warn-App/src/main/res/layout/home_statistics_cards_keysubmissions_layout.xml b/Corona-Warn-App/src/main/res/layout/home_statistics_cards_keysubmissions_layout.xml
index 44b537c35..781e99cdf 100644
--- a/Corona-Warn-App/src/main/res/layout/home_statistics_cards_keysubmissions_layout.xml
+++ b/Corona-Warn-App/src/main/res/layout/home_statistics_cards_keysubmissions_layout.xml
@@ -9,6 +9,7 @@
         android:layout_height="wrap_content"
         tools:layout_height="wrap_content"
         tools:layout_width="@dimen/statistics_card_width"
+        android:id="@+id/keysubmissions_container"
         tools:showIn="@layout/home_statistics_cards_basecard_layout">
 
         <androidx.appcompat.widget.AppCompatImageView
@@ -16,6 +17,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:importantForAccessibility="no"
+            android:contentDescription="@null"
             android:src="@drawable/ic_main_illustration_warnende_personen"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintTop_toTopOf="@id/flow_layout" />
@@ -42,6 +44,7 @@
         <TextView
             android:id="@+id/primary_value"
             style="@style/StatisticsCardPrimaryValue"
+            android:focusable="true"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:includeFontPadding="false"
@@ -58,6 +61,7 @@
         <TextView
             android:id="@+id/secondary_value"
             style="@style/StatisticsCardSecondaryValue"
+            android:focusable="true"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             tools:text="1.812" />
@@ -83,6 +87,7 @@
             android:id="@+id/tertiary_value"
             style="@style/StatisticsCardSecondaryValue"
             android:layout_width="wrap_content"
+            android:focusable="true"
             android:layout_height="wrap_content"
             tools:text="20.922" />
 
diff --git a/Corona-Warn-App/src/main/res/layout/home_statistics_cards_sevendayrvalue_layout.xml b/Corona-Warn-App/src/main/res/layout/home_statistics_cards_sevendayrvalue_layout.xml
index d32cc6021..feca8a674 100644
--- a/Corona-Warn-App/src/main/res/layout/home_statistics_cards_sevendayrvalue_layout.xml
+++ b/Corona-Warn-App/src/main/res/layout/home_statistics_cards_sevendayrvalue_layout.xml
@@ -9,6 +9,7 @@
         android:layout_height="wrap_content"
         tools:layout_height="wrap_content"
         tools:layout_width="@dimen/statistics_card_width"
+        android:id="@+id/seven_day_r_value_container"
         tools:showIn="@layout/home_statistics_cards_basecard_layout">
 
         <androidx.appcompat.widget.AppCompatImageView
@@ -44,6 +45,7 @@
         <TextView
             android:id="@+id/primary_value"
             style="@style/StatisticsCardPrimaryValue"
+            android:focusable="true"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:includeFontPadding="false"
diff --git a/Corona-Warn-App/src/main/res/values-de/strings.xml b/Corona-Warn-App/src/main/res/values-de/strings.xml
index 6ea990311..8e5b4abf7 100644
--- a/Corona-Warn-App/src/main/res/values-de/strings.xml
+++ b/Corona-Warn-App/src/main/res/values-de/strings.xml
@@ -1368,6 +1368,11 @@
     <!-- XACT: Statistics explanation illustration description -->
     <string name="statistics_explanation_illustration_description">"Abstrakte Darstellung eines Smartphones mit vier Platzhaltern für Informationen"</string>
 
+    <!-- XTXT: Statistics Card Announcement -->
+    <string name="accessibility_statistics_card_announcement">"Statistikkarte"</string>
+    <!-- XTXT: Statistics Card Navigation Announcement -->
+    <string name="accessibility_statistics_card_navigation_information">"Wische horizontal zwischen den Karten für weitere Statistiken"</string>
+
     <!-- ####################################
           Button Tooltips for Accessibility
     ###################################### -->
diff --git a/Corona-Warn-App/src/main/res/values/strings.xml b/Corona-Warn-App/src/main/res/values/strings.xml
index e1bda105d..5e67caee4 100644
--- a/Corona-Warn-App/src/main/res/values/strings.xml
+++ b/Corona-Warn-App/src/main/res/values/strings.xml
@@ -1377,11 +1377,16 @@
     <string name="statistics_explanation_trend_stable_title">"Trend: Steady"</string>
     <!-- XHED: Explanation screen trend description -->
     <string name="statistics_explanation_trend_description">"The assessment of the trend for warnings by app users changes depending on current infection levels, which is why this trend is always displayed as neutral."</string>
-    <!-- XTXT: Explains user about statistics: URL, has to be "translated" into english (relevant for all languages except german) - https://www.coronawarn.app/en/faq/#further_details -->
+    <!-- XTXT: Explains user about statistics: URL, has to be "translated" into english (relevant for all languages except german)0 - https://www.coronawarn.app/en/faq/#further_details -->
     <string name="statistics_explanation_faq_url">"https://www.coronawarn.app/en/faq/#further_details"</string>
     <!-- XACT: Statistics explanation illustration description -->
     <string name="statistics_explanation_illustration_description">"Abstract picture of a smartphone with four placeholders for information"</string>
 
+    <!-- XTXT: Statistics Card Announcement -->
+    <string name="accessibility_statistics_card_announcement">""</string>
+    <!-- XTXT: Statistics Card Navigation Announcement -->
+    <string name="accessibility_statistics_card_navigation_information">""</string>
+
 
     <!-- ####################################
           Button Tooltips for Accessibility
-- 
GitLab