前言

在可拜访性方面,图表是杂乱的事物之一。iOS 15 引入了一项名为“音频图表”的新功用。

下面咱们将学习如何经过运用 accessibilityChartDescriptor 视图修饰符为任何 SwiftUI 视图构建音频表明,呈现类似自界说条形图视图或图像的图表。

DataPoint 结构体

让咱们从在 SwiftUI 中构建一个简单的条形图视图开端,该视图运用笔直条形显示一组数据点。

struct DataPoint: Identifiable {
    let id = UUID()
    let label: String
    let value: Double
    let color: Color
}

在这里,咱们有一个 DataPoint 结构,用于描绘条形图视图中的条形。它具有 id、标签、数值和填充颜色。

BarChartView 结构体

接下来,咱们能够界说一个条形图视图,它接受一组 DataPoint 结构体实例并将它们显示出来。

struct BarChartView: View {
    let dataPoints: [DataPoint]
    var body: some View {
        HStack(alignment: .bottom) {
            ForEach(dataPoints) { point in
                VStack {
                    RoundedRectangle(cornerRadius: 8, style: .continuous)
                        .fill(point.color)
                        .frame(height: point.value * 50)
                    Text(point.label)
                }
            }
        }
    }
}

如上例所示,咱们有一个 BarChartView,它接纳一组 DataPoint 实例并将它们显示为水平仓库中不同高度的圆角矩形。

ContentView 结构体

咱们能够在 SwiftUI 中轻松构建条形图视图。接下来让咱们尝试运用带有示例数据的新 BarChartView

struct ContentView: View {
    @State private var dataPoints = [
        DataPoint(label: "1", value: 3, color: .red),
        DataPoint(label: "2", value: 5, color: .blue),
        DataPoint(label: "3", value: 2, color: .red),
        DataPoint(label: "4", value: 4, color: .blue),
    ]
    var body: some View {
        BarChartView(dataPoints: dataPoints)
            .accessibilityElement()
            .accessibilityLabel("Chart representing some data")
    }
}

在这里,咱们创建了一组 DataPoint 实例的示例数组,并将其传递给 BarChartView。咱们还为图表创建了一个可拜访元素,并禁用了其子元素的可拜访性信息。为了改进图表视图的可拜访性体验,咱们还增加了可拜访性标签。

最终,咱们能够开端为咱们的条形图视图完成音频图表功用。音频图表能够经过旋钮菜单取得。要运用旋钮,请在 iOS 设备的屏幕上旋转两个手指,就像您在拨盘。VoiceOver 会说出第一个旋钮选项。继续旋转手指以听到更多选项。松开手指选择音频图表。然后在屏幕上上下滑动手指以导航。

音频图表允许用户运用音频组件了解和解说图表数据。VoiceOver 在移动到图表视图中的条形时播放具有不同腔调的声音。VoiceOver 关于更大的值运用高腔调,关于较小的值运用低腔调。这些腔调代表数组中的数据。

完成协议

现在,咱们能够评论在 BarChartView 中完成此功用的方法。首要,咱们必须创建一个契合 AXChartDescriptorRepresentable 协议的类型。AXChartDescriptorRepresentable 协议只要一个要求,即创建 AXChartDescriptor 类型的实例。AXChartDescriptor 类型的实例表明咱们图表中的数据,以 VoiceOver 能够了解和交互的格式呈现。

extension ContentView: AXChartDescriptorRepresentable {
    func makeChartDescriptor() -> AXChartDescriptor {
        let xAxis = AXCategoricalDataAxisDescriptor(
            title: "Labels",
            categoryOrder: dataPoints.map(.label)
        )
        let min = dataPoints.map(.value).min() ?? 0.0
        let max = dataPoints.map(.value).max() ?? 0.0
        let yAxis = AXNumericDataAxisDescriptor(
            title: "Values",
            range: min...max,
            gridlinePositions: []
        ) { value in "(value) points" }
        let series = AXDataSeriesDescriptor(
            name: "",
            isContinuous: false,
            dataPoints: dataPoints.map {
                .init(x: $0.label, y: $0.value)
            }
        )
        return AXChartDescriptor(
            title: "Chart representing some data",
            summary: nil,
            xAxis: xAxis,
            yAxis: yAxis,
            additionalAxes: [],
            series: [series]
        )
    }
}

咱们所需做的便是契合 AXChartDescriptorRepresentable 协议,并增加 makeChartDescriptor 函数,该函数回来 AXChartDescriptor 的实例。

首要,咱们经过运用 AXCategoricalDataAxisDescriptorAXNumericDataAxisDescriptor 类型界说 X 轴和 Y 轴。咱们期望在 X 轴上运用字符串标签,这便是为什么咱们运用 AXCategoricalDataAxisDescriptor 类型的原因。在线图的情况下,咱们将在两个轴上都运用 AXNumericDataAxisDescriptor 类型。

完成线图

接下来,咱们运用 AXDataSeriesDescriptor 类型界说图表中的点。有一个 isContinuous 参数,允许咱们界说不同的图表样式。例如,关于条形图,它应该是 false,而关于线图,它应该是 true。

struct ContentView: View {
    @State private var dataPoints = [
        DataPoint(label: "1", value: 3, color: .red),
        DataPoint(label: "2", value: 5, color: .blue),
        DataPoint(label: "3", value: 2, color: .red),
        DataPoint(label: "4", value: 4, color: .blue),
    ]
    var body: some View {
        BarChartView(dataPoints: dataPoints)
            .accessibilityElement()
            .accessibilityLabel("Chart representing some data")
            .accessibilityChartDescriptor(self)
    }
}

作为最终一步,咱们运用 accessibilityChartDescriptor 视图修饰符将契合 AXChartDescriptorRepresentable 协议的实例设置为描绘咱们图表的实例。

示例截图:

如安在 SwiftUI 中完成音频图表

总结

音频图表功用关于视力受损的用户来说是一项严重改进。音频图表功用的好处是,能够将其用于任何您想要的视图,甚至包含图像视图。只需创建 AXChartDescriptor 类型的实例。