skip to Main Content

When you turn the ScrollView left to right, and try to scroll, content jumps to the other side. Is there any way to prevent this?

Main:

var body: some Scene {
    WindowGroup {
        ContentView()
            .environment(.layoutDirection,  .rightToLeft)
    }
}

ContentView:

struct ContentView: View {
    var body: some View {
        ScrollView(.horizontal) {
            HStack {
                Image(systemName: "circle.fill")
                    .imageScale(.large)
                    .foregroundStyle(.tint)
                Text("مَملَكة")
                
                Image(systemName: "square.fill")
                    .imageScale(.large)
                    .foregroundStyle(.tint)
                Text("اخبرك")
                
                Image(systemName: "heart.fill")
                    .imageScale(.large)
                    .foregroundStyle(.tint)
                Text("عِلاجيّ")
            }
            .padding()
        }
    }
}

enter image description here

2

Answers


  1. Unfortunately, Apple does not support the RTL direction very well.

    This issue happens only when the element inside the scroll view are not enough to fill the width.

    To work around it:

    struct ContentView: View {
        @Environment(.layoutDirection) var direction // 👈 1. Get the direction from the environment
    
        var body: some View {
            ScrollView(.horizontal) {
                HStack {
                    Group { // 👈 2. Put everything in a group (Not the HStack itself)
                        Image(systemName: "circle.fill")
                            .imageScale(.large)
                            .foregroundStyle(.tint)
                        Text("مَملَكة")
    
                        Image(systemName: "square.fill")
                            .imageScale(.large)
                            .foregroundStyle(.tint)
                        Text("اخبرك")
    
                        Image(systemName: "heart.fill")
                            .imageScale(.large)
                            .foregroundStyle(.tint)
                        Text("عِلاجيّ")
                    }
                    .scaleEffect(x: direction == .rightToLeft ? -1 : 1) // 👈 3. Flip items if they are in the RTL direction environment
                }
                .padding()
            }
            .flipsForRightToLeftLayoutDirection(true) // 👈 4. Make the scrollView flips on RTL directions
        }
    }
    

    ⚠️ Note the order and where to apply what.

    If you know the items will fill the width, there is no need to apply any of these.

    Login or Signup to reply.
  2. This issue fixed since iOS 16.4

    You can solve this issue using this
    my code will work in all iOS versions

     struct ScrollViewRTL<Content: View>: View {
         @ViewBuilder var content: Content
        @Environment(.layoutDirection) private var layoutDirection
    
        @ViewBuilder var body: some View {
            if #available(iOS 16.4, *) {
                ScrollView(.horizontal, showsIndicators: false) {
                    content
                }
            } else {
                ScrollView(.horizontal, showsIndicators: false) {
                    content
                        .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)))
    
            }
        }
    }
    

    Use it like this

    truct Demo: View {
        var body: some View {
              
            ScrollViewRTL {
                HStack {
                    ForEach((1...100), id: .self) {
                        Text("($0)")
                        }
                    }
            }
        }
     }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search