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)
}
}
}
}
我有一个支持 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)
}
}
}
}