SwiftUI - 如何使水平滚动视图 RTL 友好?

SwiftUI - how to make horizontally scrollable views RTL friendly?

我有一个支持 LTR 和 RTL 语言的 SwiftUI 应用程序。它不固定于其中任何一个,它只取决于用户想要什么。

我有一个水平滚动的列表,里面有一个垂直滚动的列表,之前是通过 UICollectionView inside a UITableViewCell inside a UITableView.

实现的

对于RTL,水平滚动行默认需要在最右边的第一个元素上(显然与LTR相反)。我还没有找到实现这一目标的方法。

我试过 flipsForRightToLeftLayoutDirection(_:) 但问题是它翻转了所有内容,包括滚动视图中的 Text()。所以阿拉伯文字看起来是镜像的。

这是我的视图骨架 -

ScrollView(.horizontal) {
  LazyHStack {
    ForEach(things) { thing in
      Text(thing.name)
    }
  }
}

关于如何实现这个的任何想法?提前致谢。

要自动滚动到最右边的元素,您可以使用 ScrollViewReader 视图的 scrollTo 函数。

您应该为 ForEach 循环的每个元素设置一个 id,并使用 ForEach 的 onAppear 修饰符滚动到最右边的元素(最后一个 id)。仅当语言方向是从右到左时才应这样做(Locale.characterDirection 提供此信息)。

下面的代码说明了这一点:

struct LanguageScrollView: View {
    let things: [String] = ["Thing1", "Thing2", "Thing3", "Thing4", "Thing5", "Thing6", "Thing7", "Thing8", "Thing9", "Thing10"]
    
    var body: some View {
        ScrollView(.horizontal) {
            ScrollViewReader { value in
                LazyHStack {
                    ForEach(0..<things.count) { i in
                        Text(things[i])
                            .id(i)
                    }
                    .onAppear {
                        if getLangDirection() == .rightToLeft {
                            value.scrollTo(things.count - 1)
                        }
                    }
                }
            }
        }
    }
    
    func getLangDirection() -> Locale.LanguageDirection? {
        guard let language = Locale.current.languageCode else { return nil }
        let direction = Locale.characterDirection(forLanguage: language)
        return direction
    }
    
}

@MatM 上面的回答是正确的,但是,如果我们没有明确设置框架,我的 LazyHStack 在调整大小方面有问题(至少在 iOS 14 上),我不知道为什么。另一件事改为使用 Locale.LanguageDirection?我更喜欢使用 Environment 中的 layoutDirection,如下所示。 请记住,我写信是为了使用 HStack,因为在 Lazy 中我遇到了一个问题,即除了我们定义框架之外,视图没有正确显示为 RTL。

    @Environment(\.layoutDirection) var layoutDirection
    

ScrollView(.horizontal) {
            ScrollViewReader { value in
                HStack {
                    ForEach(0..<things.count) { i in
                        Text(things[i])
                            .id(i)
                    }
                    .onAppear {
                        // change things.first with whatever is the first identifier you set
                        proxy.scrollTo(things.first ?? 0, anchor: layoutDirection == LayoutDirection.rightToLeft ? .trailing : .leading)
                    }
                }
            }
        }