如何在 VoiceOver 滑动时水平滚动 UIStackView?

How to scroll UIStackView horizontally when VoiceOver swipe?

我有一个水平的 UIStackView,里面有几个按钮。按钮的数量不是固定的,堆栈视图的长度可能会超过屏幕宽度。

我使用结构UIScrollView - UIView - UIStackView 当长度小于屏幕宽度时右对齐,当长度超过屏幕宽度时左对齐。

右对齐: 左对齐:

当 VoiceOver 打开时,它只会读取屏幕上的按钮。

我尝试将所有按钮添加到 accessibilityElements。 VoiceOver 可以读取所有按钮,但不会滚动堆栈视图来显示它们。当从堆栈视图下方的元素滑动时,VoiceOver 仍然会忽略不在屏幕中的按钮。所以添加 accessibilityElements 无法解决这个问题。

有人知道如何在用户滑动屏幕时滚动堆栈视图以显示隐藏按钮吗?提前致谢。

Anybody knows how to scroll stack view to show hiding buttons when user swipe screen?

将堆栈视图嵌入滚动视图 以便能够获取屏幕外的元素:您可以在 Interface Builder or programmatically.[=24 中执行此操作=]

这是我在 Xcode 下的配置,用于在 UIStackView 中使用 VoiceOver 滑动按钮: 我终于在我的设备上得到了以下结果: 我没有在 UIStackView 中玩过对齐,但是,根据这个原理,您可以 滚动堆栈视图以在用户滑动屏幕时显示隐藏按钮

⚠️ ⬛️◼️▪️ 编辑 ▪️◼️⬛️ ⚠️ (2020 年 2 月:在原始问题中添加新约束后)

The alignment is my primary need.

正如我在评论中所解释的那样,布局约束是无需使用专用 UIView.

即可实现目标的解决方案

我在下面详细介绍了 Interface Builder 配置: 并用几行代码如下:

@IBOutlet weak var myScrollView: UIScrollView!
@IBOutlet weak var myStackView: UIStackView!

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    let delta = myScrollView.frame.width - myStackView.frame.width
    let constant = (delta > 0.0) ? delta : 0.0

    myStackView.leadingAnchor.constraint(greaterThanOrEqualTo: myScrollView.contentLayoutGuide.leadingAnchor,
                                         constant: constant).isActive = true
}

...你用 5 个按钮得到这个结果: ...并通过几个按钮保持正确对齐:

现在,您可以在 VoiceOver 滑动时水平滚动 UIStackView

解决方案是继承 UIButton 并覆盖其 accessibilityElementDidBecomeFocused 方法。

MyButton.h

@interface MyButton : UIButton

@property (weak, nonatomic) UIScrollView *scrollView;

@end

MyButton.m

#import "MyButton.h"

@implementation MyButton

- (void)accessibilityElementDidBecomeFocused
{
    [self.scrollView scrollRectToVisible:CGRectMake(self.frame.origin.x, self.frame.origin.y, self.bounds.size.width, self.bounds.size.height) animated:YES];
}

@end