AccessibilityInfo

有时候我们希望知道用户的设备是否正在运行读屏应用。AccessibilityInfo正是用于此目的。你可以用它来查询读屏应用的当前状态,并且可以监听其状态变化。

好的,以下是关于 React Native 中 AccessibilityInfo 模块的详细说明。

AccessibilityInfo 是 React Native 提供的一个核心模块,用于与设备的辅助功能(Accessibility)服务进行交互。它允许开发者检测系统辅助功能设置的变化,并主动向屏幕阅读器等工具发送自定义的可访问性公告,从而显著提升应用对视障用户或其他有特殊需求用户的友好度。

核心功能概览

AccessibilityInfo 主要提供两大类功能:事件监听和主动通知。

  1. 事件监听 (addEventListener)

你可以使用 addEventListener 方法监听系统辅助功能状态的变化。这对于根据用户的偏好动态调整应用行为非常有用。

支持的事件类型包括:

  • accessibilityServiceChanged (Android):当设备上启用或禁用了某些辅助功能服务(如 TalkBack)时触发。事件处理程序会收到一个布尔值,true 表示服务已启用。
  • announcementFinished (鸿蒙OpenHarmony):当屏幕阅读器完成一次公告时触发。事件处理程序会收到一个包含 announcement(被朗读的字符串)和 success(公告是否成功)字段的对象。
  • boldTextChanged (鸿蒙OpenHarmony):当系统“加粗文本”功能的切换状态改变时触发。返回 true 表示已启用。
  • grayscaleChanged (鸿蒙OpenHarmony):当系统“灰度”模式的切换状态改变时触发。返回 true 表示已启用。
  • invertColorsChanged (鸿蒙OpenHarmony):当系统“反转颜色”功能的切换状态改变时触发。返回 true 表示已启用。
  • reduceMotionChanged:当“减少动画”功能的切换状态改变时触发。返回 true 表示已启用(动画被关闭或减速)。
  • reduceTransparencyChanged (鸿蒙OpenHarmony):当“减少透明度”功能的切换状态改变时触发。返回 true 表示已启用。
  • screenReaderChanged:当系统屏幕阅读器(如 VoiceOver)的启用状态改变时触发。返回 true 表示屏幕阅读器已启用。

示例:监听屏幕阅读器状态变化

import { AccessibilityInfo } from 'react-native';

// 添加事件监听
const subscription = AccessibilityInfo.addEventListener(
  'screenReaderChanged',
  (isScreenReaderEnabled) => {
    console.log('屏幕阅读器是否启用:', isScreenReaderEnabled);
    // 根据状态调整UI或行为
  }
);

// 之后,记得清理订阅以避免内存泄漏
// subscription.remove();
  1. 主动通知 (announceForAccessibility)

这是 AccessibilityInfo 最强大的功能之一,它允许你主动向系统屏幕阅读器发送文本进行朗读。

  • announceForAccessibility(announcement: string):将指定的字符串发送给屏幕阅读器进行朗读。默认情况下,这会中断任何正在进行的语音。
  • announceForAccessibilityWithOptions(announcement: string, options: { queue?: boolean }):与上一个方法类似,但提供了更多选项。通过在 options 对象中设置 { queue: true },可以使公告在现有语音之后排队播放,而不是打断。

示例:向屏幕阅读器发送公告

import { AccessibilityInfo } from 'react-native';

// 立即朗读
AccessibilityInfo.announceForAccessibility('操作成功完成!');

// 在现有语音后排队朗读
AccessibilityInfo.announceForAccessibilityWithOptions('请检查您的订单详情', { queue: true });
  1. 查询系统状态 (异步方法)

这些方法用于查询当前系统的辅助功能设置状态,它们都返回一个 Promise

  • isBoldTextEnabled() (鸿蒙OpenHarmony):查询“加粗文本”是否启用。
  • isGrayscaleEnabled() (鸿蒙OpenHarmony):查询“灰度”模式是否启用。
  • isInvertColorsEnabled() (鸿蒙OpenHarmony):查询“反转颜色”是否启用。
  • isReduceTransparencyEnabled() (鸿蒙OpenHarmony):查询“减少透明度”是否启用。
  • getRecommendedTimeoutMillis(originalTimeout: number) (Android):获取系统推荐的超时时间(毫秒),用于辅助功能操作。如果系统未设置,则返回 originalTimeout

实际案例演示:

import React, {useState, useEffect} from 'react';
import {AccessibilityInfo, View, Text, StyleSheet, TouchableOpacity, Alert} from 'react-native';

const App = () => {
  const [reduceMotionEnabled, setReduceMotionEnabled] = useState(false);
  const [screenReaderEnabled, setScreenReaderEnabled] = useState(false);
  const [isLoading, setIsLoading] = useState(false);

  useEffect(() => {
    const reduceMotionChangedSubscription = AccessibilityInfo.addEventListener(
      'reduceMotionChanged',
      isReduceMotionEnabled => {
        setReduceMotionEnabled(isReduceMotionEnabled);
      },
    );
    const screenReaderChangedSubscription = AccessibilityInfo.addEventListener(
      'screenReaderChanged',
      isScreenReaderEnabled => {
        setScreenReaderEnabled(isScreenReaderEnabled);
      },
    );

    AccessibilityInfo.isReduceMotionEnabled().then(isReduceMotionEnabled => {
      setReduceMotionEnabled(isReduceMotionEnabled);
    });
    AccessibilityInfo.isScreenReaderEnabled().then(isScreenReaderEnabled => {
      setScreenReaderEnabled(isScreenReaderEnabled);
    });

    return () => {
      reduceMotionChangedSubscription.remove();
      screenReaderChangedSubscription.remove();
    };
  }, []);

  const toggleReduceMotion = async () => {
    setIsLoading(true);
    try {
      await AccessibilityInfo.setReduceMotionEnabled(!reduceMotionEnabled);
      Alert.alert('Success', `Reduce motion is now ${!reduceMotionEnabled ? 'enabled' : 'disabled'}`);
    } catch (error) {
      Alert.alert('Error', 'Failed to toggle reduce motion');
    } finally {
      setIsLoading(false);
    }
  };

  const toggleScreenReader = async () => {
    setIsLoading(true);
    try {
      await AccessibilityInfo.setScreenReaderEnabled(!screenReaderEnabled);
      Alert.alert('Success', `Screen reader is now ${!screenReaderEnabled ? 'enabled' : 'disabled'}`);
    } catch (error) {
      Alert.alert('Error', 'Failed to toggle screen reader');
    } finally {
      setIsLoading(false);
    }
  };

  return (
    <View style={styles.container}>
      <Text style={[styles.status, { color: reduceMotionEnabled ? 'green' : 'red' }]}>
        The reduce motion is {reduceMotionEnabled ? 'enabled' : 'disabled'}.
      </Text>
      <TouchableOpacity 
        style={styles.button} 
        onPress={toggleReduceMotion}
        disabled={isLoading}
      >
        <Text style={styles.buttonText}>
          {isLoading ? 'Loading...' : 'Toggle Reduce Motion'}
        </Text>
      </TouchableOpacity>

      <Text style={[styles.status, { color: screenReaderEnabled ? 'green' : 'red' }]}>
        The screen reader is {screenReaderEnabled ? 'enabled' : 'disabled'}.
      </Text>
      <TouchableOpacity 
        style={styles.button} 
        onPress={toggleScreenReader}
        disabled={isLoading}
      >
        <Text style={styles.buttonText}>
          {isLoading ? 'Loading...' : 'Toggle Screen Reader'}
        </Text>
      </TouchableOpacity>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  status: {
    margin: 20,
    fontSize: 16,
  },
  button: {
    backgroundColor: '#007AFF',
    padding: 15,
    borderRadius: 10,
    margin: 10,
    width: 200,
    alignItems: 'center',
  },
  buttonText: {
    color: 'white',
    fontSize: 16,
  },
});

export default App;

这段React Native代码实现了一个完整的无障碍功能管理应用,其核心原理基于React Native的无障碍API和React的响应式状态管理机制。应用通过AccessibilityInfo模块来监听和控制系统级别的无障碍设置,包括减少动画效果和屏幕阅读器功能。

在初始化阶段,应用使用useEffect钩子来建立与设备无障碍系统的连接。它通过AccessibilityInfo.isReduceMotionEnabled()和AccessibilityInfo.isScreenReaderEnabled()这两个异步方法获取当前的系统设置状态,并将结果存储在组件的状态中。同时,应用注册了两个事件监听器来实时响应系统无障碍设置的变更,当用户在系统设置中修改这些选项时,应用界面会自动更新以反映最新的状态。

在这里插入图片描述
状态管理方面,应用维护了三个关键状态变量:reduceMotionEnabled用于跟踪减少动画功能的启用状态,screenReaderEnabled用于跟踪屏幕阅读器的启用状态,isLoading用于管理异步操作期间的加载状态。这种状态设计确保了用户界面的实时响应性和操作反馈的完整性。

用户交互层面,应用提供了两个主要功能按钮,分别用于切换减少动画和屏幕阅读器设置。当用户点击这些按钮时,会触发相应的异步操作函数。这些函数首先设置加载状态为true,然后通过AccessibilityInfo.setReduceMotionEnabled()和AccessibilityInfo.setScreenReaderEnabled()方法尝试修改系统设置。这些操作被包装在try-catch块中,以确保在操作成功或失败时都能给用户适当的反馈。

界面渲染逻辑采用条件样式设计,根据当前的无障碍设置状态动态改变文本颜色。启用状态显示为绿色,禁用状态显示为红色,这种视觉反馈帮助用户快速理解当前系统状态。按钮在异步操作期间会显示加载状态并禁用交互,防止用户重复操作。


打包

接下来通过打包命令npn run harmony将reactNative的代码打包成为bundle,这样可以进行在开源鸿蒙OpenHarmony中进行使用。

在这里插入图片描述
最后运行效果图如下显示:

请添加图片描述

欢迎大家加入开源鸿蒙跨平台开发者社区,一起共建开源鸿蒙跨平台生态。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐