Search Results for

    Show / Hide Table of Contents

    SciChart Accessibility Integration Guide

    This guide helps you add accessibility support to SciChart. By following these steps, you will ensure that screen readers like TalkBack can interpret and vocalize chart interactions for visually impaired users.


    Step 1: Extend SciChartSurface for Accessibility

    Create a custom surface that enables navigation and interaction through accessibility tools.

    Code Example

    • Java
    • Kotlin
    public class AccessibilityCustomSurface extends SciChartSurface {
    
        public AccessibilityCustomSurface(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        @Override
        public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
            // If the AccessibilityEvent isn't null, then add text to be announced when the SciChartSurface
            // is in focus in accessibility mode.
            if (event != null) {
                // This text will be announced when the SciChartSurface is in focus in accessibility mode
                event.getText().add("sci chart event");
            }
            return true;
        }
    
        @Override
        public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
            super.onInitializeAccessibilityNodeInfo(info);
            if (info != null) {
                // Set the SciChartSurface to be Clickable, Focusable and Scrollable
                info.setClickable(true);
                info.setFocusable(true);
                info.setScrollable(true);
    
                // Add an action, so that it is possible to click on SciChartSurface
                info.addAction(new AccessibilityNodeInfo.AccessibilityAction(
                        AccessibilityNodeInfo.ACTION_CLICK, "Action click"
                ));
            }
        }
    
        @Override
        public boolean performAccessibilityAction(int action, Bundle arguments) {
            // If the action is a click event, then return true to handle the event.
            if (action == AccessibilityNodeInfo.ACTION_CLICK) {
                // Any custom code that you need will go here
                return true;
            } else {
                return super.performAccessibilityAction(action, arguments);
            }
        }
    }
    
    class AccessibilityCustomSurface(
        context: Context, attrs: AttributeSet?
    ) : SciChartSurface(context, attrs) {
        override fun dispatchPopulateAccessibilityEvent(event: AccessibilityEvent?): Boolean {
            // If the AccessibilityEvent isn't null, then add text to be announced when the SciChartSurface
            // is in focus in accessibility mode.
            event?.text?.add("sci chart event")
            return true
        }
    
        override fun onInitializeAccessibilityNodeInfo(info: AccessibilityNodeInfo?) {
            super.onInitializeAccessibilityNodeInfo(info)
            if (info != null) {
                // Set the SciChartSurface to be Clickable, Focusable and Scrollable
                info.isClickable = true
                info.isFocusable = true
                info.isScrollable = true
    
                // Add an action, so that it is possible to click on SciChartSurface
                info.addAction(
                    AccessibilityNodeInfo.AccessibilityAction(
                        AccessibilityNodeInfo.ACTION_CLICK, "Action click"
                    )
                )
            }
        }
    
        override fun performAccessibilityAction(action: Int, arguments: Bundle?): Boolean {
            // If the action is a click event, then return true to handle the event.
            return if (action == AccessibilityNodeInfo.ACTION_CLICK) {
                // Any custom code that you need will go here
                true
            } else {
                super.performAccessibilityAction(action, arguments)
            }
        }
    }
    

    What This Does

    • Makes the chart surface visible and interactive for screen readers.
    • Adds a verbal description: "sci chart event".
    • Supports accessible click actions.

    Step 2: Announce Zoom or Pan (Visible Range Change)

    When the chart’s visible range changes due to scroll or zoom, notify the screen reader so users stay informed.

    Code Example

    • Java
    • Kotlin
    binding.surface.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
    
    xAxis.setVisibleRangeChangeListener((axis, oldRange, newRange, isAnimating) -> {
        binding.surface.announceForAccessibility("visible range changed");
        binding.surface.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
    });
    
    binding.surface.importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_YES
    xAxis.setVisibleRangeChangeListener { axis, oldRange, newRange, isAnimating -> // need to send this even to update position of rects on screen during scrolling
        binding.surface.announceForAccessibility("visible range changed")
        binding.surface.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED)
    }
    

    What This Does

    • Announces "visible range changed" when user interacts with the chart.
    • Emits a window content change event for accessibility services.

    Step 3: Provide Accessible Custom Tooltips

    Customize tooltips to announce the current data point (X, Y, and series name) using announceForAccessibility().

    Code Example

    • Java
    • Kotlin
    private static class FirstCustomSeriesInfoProvider extends DefaultXySeriesInfoProvider {
        @Override
        public ISeriesTooltip getSeriesTooltipInternal(Context context, XySeriesInfo<?> seriesInfo, Class<?> modifierType) {
            if (modifierType == RolloverModifier.class) {
                return new FirstCustomXySeriesTooltip(context, seriesInfo);
            } else {
                return super.getSeriesTooltipInternal(context, seriesInfo, modifierType);
            }
        }
    
        private static class FirstCustomXySeriesTooltip extends XySeriesTooltip {
    
            public FirstCustomXySeriesTooltip(Context context, XySeriesInfo<?> seriesInfo) {
                super(context, seriesInfo);
            }
    
            @Override
            protected void internalUpdate(XySeriesInfo seriesInfo) {
                super.internalUpdate(seriesInfo);
                SpannableStringBuilder sb = new SpannableStringBuilder();
                sb.append("X is ").append(seriesInfo.getFormattedXValue()).append(StringUtil.NEW_LINE);
                sb.append("Y is ").append(seriesInfo.getFormattedYValue()).append(StringUtil.NEW_LINE);
    
                if (seriesInfo.seriesName != null) {
                    sb.append(seriesInfo.seriesName).append(StringUtil.NEW_LINE);
                }
    
                setText(sb);
                announceForAccessibility(sb.toString());
    
                setTooltipBackgroundColor(0xffe97064);
                setTooltipStroke(0xfff4840b);
                setTooltipTextColor(ColorUtil.White);
            }
        }
    }
    
    private class FirstCustomSeriesInfoProvider() : DefaultXySeriesInfoProvider() {
    
    
        override fun getSeriesTooltipInternal(context: Context, seriesInfo: XySeriesInfo<*>, modifierType: Class<*>): ISeriesTooltip {
            return when (modifierType) {
                RolloverModifier::class.java -> { FirstCustomXySeriesTooltip(context, seriesInfo) }
                else -> { super.getSeriesTooltipInternal(context, seriesInfo, modifierType) }
            }
        }
    
        private class FirstCustomXySeriesTooltip(context: Context?, seriesInfo: XySeriesInfo<*>) :
            XySeriesTooltip(context, seriesInfo) {
    
            override fun internalUpdate(seriesInfo: XySeriesInfo<*>) {
                val sb = SpannableStringBuilder()
                sb.append("X is ").append(seriesInfo.formattedXValue).append(StringUtil.NEW_LINE)
                sb.append("Y is ").append(seriesInfo.formattedYValue).append(StringUtil.NEW_LINE)
    
                seriesInfo.seriesName?.run {
                    sb.append(this).append(StringUtil.NEW_LINE)
                }
                text = sb
    
                announceForAccessibility(sb.toString())
    
                setTooltipBackgroundColor(0xffe97064.toInt())
                setTooltipStroke(0xfff4840b.toInt())
                setTooltipTextColor(ColorUtil.White)
            }
        }
    }
    

    What This Does

    • Announces chart data values (X, Y, series name) when the tooltip appears.
    • Works with rollover modifiers and other dynamic interactions.
    • Enhances accessibility for real-time data updates.

    Final Checklist

    Feature Purpose Implemented In
    Surface is accessible Lets users navigate chart surface Step 1
    Zoom/pan announcement Alerts user to visible range changes Step 2
    Tooltip speaks values Reads out data point details aloud Step 3

    Recommended Tools for Testing

    • TalkBack (Android)
    • Accessibility Scanner (Google)
    • Manual screen reader interaction testing
    Back to top © 2011-2025 SciChart. All rights reserved. | sitemap.xml