SwiftUI ScrollView 水平 RTL 不正常工作

7

我正在尝试为使用SwiftUI构建的iOS应用程序支持从右到左(RTL)模式。在更改布局方向时一切都很好:

.environment(\.layoutDirection, .rightToLeft)

仅使用水平滚动视图(horizontal ScrollView),它无法正常工作

当我这样做时:

 ScrollView(.horizontal) {
            HStack{
                Text("b1")
                Text("b2")
                Text("b3")
            }
        } .environment(\.layoutDirection, .rightToLeft)

项目的位置会旋转,但HSTACK将始终保持在左侧,就像下面的屏幕截图一样:

enter image description here

有没有任何解决方案或技巧可以使其在右侧?

6个回答

12

我发现一种使用.flipsForRightToLeftLayoutDirection(true).rotation3DEffect的技巧来实现这一点。

这样,滚动视图将会被翻转,然后你需要将HStack中的每个项目使用.rotation3DEffect进行翻转。

 ScrollView(.horizontal) {
            HStack{
                Text("b1")
                    .rotation3DEffect(Angle(degrees: 180), axis: (x: CGFloat(0), y: CGFloat(10), z: CGFloat(0)))
                Text("b2")
                 .rotation3DEffect(Angle(degrees: 180), axis: (x: CGFloat(0), y: CGFloat(10), z: CGFloat(0)))
                Text("b3")
                 .rotation3DEffect(Angle(degrees: 180), axis: (x: CGFloat(0), y: CGFloat(10), z: CGFloat(0)))
            }
        }.flipsForRightToLeftLayoutDirection(true)
        .environment(\.layoutDirection, .rightToLeft)

1
它能够工作,但我认为一定有更好的方法来完成它。 - Farshid roohi
1
我认为单独使用.flipsForRightToLeftLayoutDirection(true)就可以解决问题。不是吗?它解决了我的问题。 - Alhomaidhi
@Alhomaidhi给出了正确的答案。谢谢! - undefined

4
通过在 onAppear 中使用 .scrollTo 以编程方式滚动视图的尾部锚点,如果 layoutDirection.rightToLeft,则可以获得正确的滚动位置。如果 layoutDirection.leftToRight,也可以工作。
struct ScrollViewRTL<Content: View>: View {
    var showsIndicators: Bool
    @ViewBuilder var content: Content
    @Environment(\.layoutDirection) private var layoutDirection
        
    init(showsIndicators: Bool = true, @ViewBuilder content: () -> Content) {
        self.showsIndicators = showsIndicators             
        self.content = content()
    }
        
    var body: some View {
       ScrollViewReader { proxy in
         ScrollView(.horizontal, showsIndicators: showsIndicators) {
             content
                 .id("RTL")
                 .onAppear {
                     if layoutDirection == .rightToLeft {
                           proxy.scrollTo("RTL", anchor: .trailing)
                     }
                 }
             }
         }
     }
}

使用方法:

 ScrollViewRTL {
     HStack {
         Text("b1")
         Text("b2")
         Text("b3")
     }
 }

0

https://stackoverflow.com/questions/77440793/is-there-a-way-to-use-scrollview-rtl-arabic-with-ltr-animation - undefined

0
作为一种hack,你可以从这里开始:
var body: some View {
    GeometryReader { geom in
        ScrollView(.horizontal) {
            HStack {
                Text("b1")
                Text("b2")
                Text("b3")
            }.environment(\.layoutDirection, .rightToLeft)
             .padding(.leading, geom.size.width - 100) // adjust for the number of items
        }
    }
}

就像这样,由于填充的原因,它不会向左滚动。 - Ouail Bellal

0

对我来说,这段代码有效。只需旋转滚动视图和滚动视图的内容,它就可以从右向左滚动,并且内容将具有正确的方向。

@Environment(\.layoutDirection) private var layoutDirection

var body: some View {
    ScrollView(.horizontal, showsIndicators: false) {
        HStack(alignment: .top, spacing: 16) {
           /* content of your scroll view */
        }
        .rotation3DEffect(Angle(degrees: layoutDirection == .rightToLeft ? -180 : 0), axis: (
            x: CGFloat(0),
            y: CGFloat(layoutDirection == .rightToLeft ? -10 : 0),
            z: CGFloat(0)))
    }
    .rotation3DEffect(Angle(degrees: layoutDirection == .rightToLeft ? 180 : 0), axis: (
        x: CGFloat(0),
        y: CGFloat(layoutDirection == .rightToLeft ? 10 : 0),
        z: CGFloat(0)))
}

0
基于Ouail Bellal的回答,提供一个更加灵活的解决方案:
@Environment(\.layoutDirection) var direction

ScrollView(.horizontal) {
        HStack{
            Text("b1")
                .rotation3DEffect(Angle(degrees: direction == .rightToLeft ? 180 : 0), axis: (x: CGFloat(0), y: CGFloat(10), z: CGFloat(0)))
            Text("b2")
             .rotation3DEffect(Angle(degrees: direction == .rightToLeft ? 180 : 0), axis: (x: CGFloat(0), y: CGFloat(10), z: CGFloat(0)))
            Text("b3")
             .rotation3DEffect(Angle(degrees: direction == .rightToLeft ? 180 : 0), axis: (x: CGFloat(0), y: CGFloat(10), z: CGFloat(0)))
        }
    }.flipsForRightToLeftLayoutDirection(true)

它在从右到左和从左到右的方向上都运行良好。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接