You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Kotlin实现TalkBack朗读进度条项目数而非百分比

实现TalkBack朗读故事进度(当前/总数)而非百分比

要让Android的TalkBack功能像Instagram故事那样朗读“第X个故事,共Y个”,而非默认的百分比进度,需要修改进度条的可访问性配置,并动态更新朗读内容。以下是具体实现步骤:

1. 禁用单个进度条的默认可访问性播报

每个LinearProgressIndicator默认会播报自身的进度百分比,我们需要让TalkBack忽略这些单个进度条,转而关注整体的故事进度信息。

修改createProgressBars函数,在创建每个进度条时添加可访问性设置:

private fun storyState.createProgressBars() {
    var progressBarWidth = context?.resources?.displayMetrics?.widthPixels?.div(stories.size) ?: STORY_PROGRESS_BAR
    progressBarWidth -= (STORY_PROGRESS_BAR_SPACING * 2)
    (0 until stories.size).forEach { _ ->
        val progressBar = LinearProgressIndicator(requireContext())
        // 禁用单个进度条的可访问性播报
        progressBar.importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO
        progressBar.layoutParams = LinearLayout.LayoutParams(progressBarWidth, STORY_PROGRESS_BAR_SPACING, 1f)
        progressBar.setIndicatorColor(getColorByMode(currentStoryScreen.mode.value))
        progressBar.trackCornerRadius = STORY_PROGRESS_BAR_SPACING
        progressBar.trackThickness = STORY_PROGRESS_BAR_SPACING
        progressBar.trackColor = Color.parseColor("#A79AA9")
        progressBar.alpha = STORY_PROGRESS_BAR_ALPHA
        progressBar.setPadding(STORY_PROGRESS_BAR_SPACING, 0, STORY_PROGRESS_BAR_SPACING, 0)
        binding.linearLayoutStoryProgressBar.addView(progressBar)
    }
    // 设置父布局可聚焦,让TalkBack能识别并朗读内容描述
    binding.linearLayoutStoryProgressBar.isFocusable = true
    binding.linearLayoutStoryProgressBar.isFocusableInTouchMode = true
    binding.linearLayoutStoryProgressBar.requestLayout()
}

2. 添加动态更新可访问性播报的函数

创建一个专门的函数,用于生成并更新当前故事进度的朗读内容,必要时可主动触发TalkBack播报:

private fun updateStoryAccessibilityAnnouncement() {
    val currentPosition = viewModel.getCurrentPosition() + 1 // 转换为1-based索引
    val totalStories = stories.size
    val announcementText = "第${currentPosition}个故事,共${totalStories}个"
    
    // 更新父布局的内容描述
    binding.linearLayoutStoryProgressBar.contentDescription = announcementText
    
    // 主动触发TalkBack播报(可选,确保内容变化时即时朗读)
    context?.let { ctx ->
        val accessibilityManager = ctx.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
        if (accessibilityManager.isEnabled) {
            val event = AccessibilityEvent.obtain(AccessibilityEvent.TYPE_ANNOUNCEMENT)
            event.text.add(announcementText)
            accessibilityManager.sendAccessibilityEvent(event)
        }
    }
}

3. 在故事切换时调用更新函数

需要在故事进度变化的关键节点调用上述函数,确保TalkBack能及时朗读最新的进度信息:

3.1 初始化进度条时调用

修改setupStoryProgressBar函数,在设置动画后添加播报更新:

private fun storyState.setupStoryProgressBar() {
    if (binding.linearLayoutStoryProgressBar.childCount == 0) { createProgressBars() }
    setProgressBarAnimation(
        binding.linearLayoutStoryProgressBar.getChildAt(currentPosition) as LinearProgressIndicator,
        currentStoryScreen.storyTimeout.toLong(),
        getColorByMode(currentStoryScreen.mode.value)
    )
    // 更新可访问性播报
    updateStoryAccessibilityAnnouncement()
}

3.2 切换到下一个故事时调用

在goToNextStory函数执行完成后(即当前故事位置更新后),调用更新函数:

private fun goToNextStory() {
    // 原有切换逻辑...
    
    // 更新可访问性播报
    updateStoryAccessibilityAnnouncement()
}

3.3 手动切换故事时调用

如果支持手动左右滑动切换故事,同样需要在切换完成后调用updateStoryAccessibilityAnnouncement()。

4. 可选:处理TalkBack焦点

如果希望用户通过TalkBack导航时能聚焦到进度条区域并朗读内容,确保父布局的focusable和focusableInTouchMode已设置为true(步骤1中已添加)。

这样修改后,TalkBack就会忽略单个进度条的百分比播报,转而朗读当前故事的位置和总数量,与Instagram的故事进度提示一致。

内容的提问来源于stack exchange,提问作者Rayssa Vanessa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 19:05:04