From 168e0249049c3fa2a4bc2c9caabcc26365d5c256 Mon Sep 17 00:00:00 2001 From: Ishan Joshi Date: Thu, 9 Jul 2020 14:04:05 +1000 Subject: [PATCH 1/6] fix: enable being detected by screenreader --- .../java/com/github/mikephil/charting/charts/Chart.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index b104935d30..0ac15052d9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -237,6 +237,9 @@ public void onAnimationUpdate(ValueAnimator animation) { if (mLogEnabled) Log.i("", "Chart.init()"); + + // enable being detected by ScreenReader + setFocusable(true); } // public void initWithDummyData() { @@ -1818,4 +1821,9 @@ private void unbindDrawables(View view) { public void setUnbindEnabled(boolean enabled) { this.mUnbind = enabled; } + + // region accessibility + + + // endregion } From 98bfae050d081663186afdedd9b95cb74ca41622 Mon Sep 17 00:00:00 2001 From: Ishan Joshi Date: Thu, 9 Jul 2020 14:54:53 +1000 Subject: [PATCH 2/6] add: stub message and verified it is read by screenreader --- .../mikephil/charting/charts/BarChart.java | 5 +++++ .../mikephil/charting/charts/BubbleChart.java | 5 +++++ .../charting/charts/CandleStickChart.java | 5 +++++ .../mikephil/charting/charts/Chart.java | 22 +++++++++++++++++++ .../charting/charts/CombinedChart.java | 4 ++++ .../mikephil/charting/charts/LineChart.java | 5 +++++ .../mikephil/charting/charts/PieChart.java | 5 +++++ .../mikephil/charting/charts/RadarChart.java | 5 +++++ .../charting/charts/ScatterChart.java | 5 +++++ 9 files changed, 61 insertions(+) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java index 2ba15c9118..3988fbf8e2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java @@ -255,4 +255,9 @@ public void groupBars(float fromX, float groupSpace, float barSpace) { notifyDataSetChanged(); } } + + @Override + public String getAccessibilityDescription() { + return "This is a bar chart"; + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BubbleChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BubbleChart.java index 23dac5780f..1510d85f01 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BubbleChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BubbleChart.java @@ -40,4 +40,9 @@ protected void init() { public BubbleData getBubbleData() { return mData; } + + @Override + public String getAccessibilityDescription() { + return "This is bubble chart"; + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CandleStickChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CandleStickChart.java index fa36e3522f..5541cbff6c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CandleStickChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CandleStickChart.java @@ -41,4 +41,9 @@ protected void init() { public CandleData getCandleData() { return mData; } + + @Override + public String getAccessibilityDescription() { + return "This is a candlestick"; + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 0ac15052d9..b49cc612e9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -23,6 +23,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; +import android.view.accessibility.AccessibilityEvent; import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.animation.Easing; @@ -176,6 +177,11 @@ public abstract class Chart and completed as " + completed); + + event.getText().add(getAccessibilityDescription()); + + return true; + } // endregion } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java index cd01f0ef73..bfbbbb88d2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java @@ -269,4 +269,8 @@ protected void drawMarkers(Canvas canvas) { } } + @Override + public String getAccessibilityDescription() { + return "This is a combined chart"; + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/LineChart.java index aa7afc4c85..3dbc4db909 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/LineChart.java @@ -47,4 +47,9 @@ protected void onDetachedFromWindow() { } super.onDetachedFromWindow(); } + + @Override + public String getAccessibilityDescription() { + return "This is a line chart"; + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java index de11b3a844..73114a86ef 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java @@ -801,4 +801,9 @@ protected void onDetachedFromWindow() { } super.onDetachedFromWindow(); } + + @Override + public String getAccessibilityDescription() { + return "This is a pie chart"; + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java index 8c0885395d..6f263d14d5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java @@ -359,4 +359,9 @@ public float getYChartMin() { public float getYRange() { return mYAxis.mAxisRange; } + + @Override + public String getAccessibilityDescription() { + return "This is a Radar chart"; + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java index 37e8395b5e..231ed0288b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java @@ -74,4 +74,9 @@ public static ScatterShape[] getAllDefaultShapes() { return new ScatterShape[]{SQUARE, CIRCLE, TRIANGLE, CROSS, X, CHEVRON_UP, CHEVRON_DOWN}; } } + + @Override + public String getAccessibilityDescription() { + return "This is scatter chart"; + } } From 3f0744629ba772d66e0e5f9c9fe4d1d6babc840b Mon Sep 17 00:00:00 2001 From: Ishan Joshi Date: Thu, 9 Jul 2020 15:14:13 +1000 Subject: [PATCH 3/6] add: basic bar-chart description --- .../mikephil/charting/charts/BarChart.java | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java index 3988fbf8e2..24bc450614 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java @@ -8,6 +8,7 @@ import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.BarHighlighter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; @@ -258,6 +259,24 @@ public void groupBars(float fromX, float groupSpace, float barSpace) { @Override public String getAccessibilityDescription() { - return "This is a bar chart"; + + BarData barData = getBarData(); + + int entryCount = barData.getDataSetCount(); + + // Find the min and max index + ValueFormatter yAxisValueFormmater = getAxisLeft().getValueFormatter(); + String minVal = yAxisValueFormmater.getFormattedValue(barData.getYMin()); + String maxVal = yAxisValueFormmater.getFormattedValue(barData.getYMax()); + + String entries = entryCount == 1 ? "entry" : "entries"; + + // Format the values of min and max; to recite them back + + String description = String.format("The bar chart has %d %s. " + + "The minimum value is %s and maximum value is %s", + entryCount, entries, minVal, maxVal); + + return description; } } From f4d17af7a158e7d4c963d9b8ff9a16e21ba57bbc Mon Sep 17 00:00:00 2001 From: Ishan Joshi Date: Thu, 9 Jul 2020 15:15:40 +1000 Subject: [PATCH 4/6] fix: entry label reading (was reading wrong value) --- .../main/java/com/github/mikephil/charting/charts/BarChart.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java index 24bc450614..0b80d5b691 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java @@ -262,7 +262,7 @@ public String getAccessibilityDescription() { BarData barData = getBarData(); - int entryCount = barData.getDataSetCount(); + int entryCount = barData.getEntryCount(); // Find the min and max index ValueFormatter yAxisValueFormmater = getAxisLeft().getValueFormatter(); From 44c1f1d871268f0f214da8839ad7262138494c60 Mon Sep 17 00:00:00 2001 From: Ishan Joshi Date: Fri, 10 Jul 2020 09:50:57 +1000 Subject: [PATCH 5/6] add: more descriptive text for BarChart.java add: support for user generated description --- .../mikephil/charting/charts/BarChart.java | 14 +++++++++++--- .../github/mikephil/charting/charts/Chart.java | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java index 0b80d5b691..17a57c4955 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java @@ -15,6 +15,8 @@ import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.renderer.BarChartRenderer; +import java.util.Locale; + /** * Chart that draws bars. * @@ -269,13 +271,19 @@ public String getAccessibilityDescription() { String minVal = yAxisValueFormmater.getFormattedValue(barData.getYMin()); String maxVal = yAxisValueFormmater.getFormattedValue(barData.getYMax()); + // Data range... + ValueFormatter xAxisValueFormatter = getXAxis().getValueFormatter(); + String minRange = xAxisValueFormatter.getFormattedValue(barData.getXMin()); + String maxRange = xAxisValueFormatter.getFormattedValue(barData.getXMax()); + String entries = entryCount == 1 ? "entry" : "entries"; // Format the values of min and max; to recite them back - String description = String.format("The bar chart has %d %s. " + - "The minimum value is %s and maximum value is %s", - entryCount, entries, minVal, maxVal); + String description = String.format(Locale.getDefault(), "The bar chart has %d %s. " + + "The minimum value is %s and maximum value is %s." + + "Data ranges from %s to %s.", + entryCount, entries, minVal, maxVal, minRange, maxRange); return description; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index b49cc612e9..2ee7e06d99 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -182,6 +182,11 @@ public abstract class Chart Date: Fri, 10 Jul 2020 17:27:23 +1000 Subject: [PATCH 6/6] add: pie chart information for screen-reader --- .../mikephil/charting/charts/LineChart.java | 28 ++++++++++++++++++- .../mikephil/charting/charts/PieChart.java | 25 ++++++++++++++++- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/LineChart.java index 3dbc4db909..eae593f0de 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/LineChart.java @@ -5,9 +5,12 @@ import android.util.AttributeSet; import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; import com.github.mikephil.charting.renderer.LineChartRenderer; +import java.util.Locale; + /** * Chart that draws lines, surfaces, circles, ... * @@ -50,6 +53,29 @@ protected void onDetachedFromWindow() { @Override public String getAccessibilityDescription() { - return "This is a line chart"; + + LineData lineData = getLineData(); + + int numberOfPoints = lineData.getEntryCount(); + + // Min and max values... + ValueFormatter yAxisValueFormmater = getAxisLeft().getValueFormatter(); + String minVal = yAxisValueFormmater.getFormattedValue(lineData.getYMin()); + String maxVal = yAxisValueFormmater.getFormattedValue(lineData.getYMax()); + + // Data range... + ValueFormatter xAxisValueFormatter = getXAxis().getValueFormatter(); + String minRange = xAxisValueFormatter.getFormattedValue(lineData.getXMin()); + String maxRange = xAxisValueFormatter.getFormattedValue(lineData.getXMax()); + + String entries = numberOfPoints == 1 ? "entry" : "entries"; + + String description = String.format(Locale.getDefault(), "The line chart has %d %s. " + + "The minimum value is %s and maximum value is %s." + + "Data ranges from %s to %s.", + numberOfPoints, entries, minVal, maxVal, minRange, maxRange); + + + return description; } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java index 73114a86ef..dd60c339c4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java @@ -6,10 +6,13 @@ import android.graphics.Paint; import android.graphics.RectF; import android.graphics.Typeface; +import android.text.TextUtils; import android.util.AttributeSet; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.data.PieData; +import com.github.mikephil.charting.data.PieEntry; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.highlight.PieHighlighter; import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; @@ -17,7 +20,9 @@ import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Utils; +import java.util.ArrayList; import java.util.List; +import java.util.Locale; /** * View that represents a pie chart. Draws cake like slices. @@ -804,6 +809,24 @@ protected void onDetachedFromWindow() { @Override public String getAccessibilityDescription() { - return "This is a pie chart"; + + PieData pieData = getData(); + + int entryCount = pieData.getEntryCount(); + + StringBuilder builder = new StringBuilder(); + + builder.append(String.format(Locale.getDefault(), "The pie chart has %d entries.", + entryCount)); + + for (int i = 0; i < entryCount; i++) { + PieEntry entry = pieData.getDataSet().getEntryForIndex(i); + float percentage = (entry.getValue() / pieData.getYValueSum()) * 100; + builder.append(String.format(Locale.getDefault(), "%s has %.2f percent pie taken", + (TextUtils.isEmpty(entry.getLabel()) ? "No Label" : entry.getLabel()), + percentage)); + } + + return builder.toString(); } }