swift – Reverse ScrollView bug in iOS 15+ contextMenu

0
22

[ad_1]

Thanks for taking your time to help others 🙂

And for instance, I already checked all the solutions of this post, but none worked for us.

Posted also at Apple Developer, I publish here also hoping for better luck. Thanks!

Bug description:

As we are building a chat, we need messages to display in the reverse order of a List/ ScrollView has. That’s why we are putting everything upsideDown.

On iOS 15 and iOS 16 (not in 14), there is an strange behaviour (seems a bug) when showing contextMenu on a reversed List/ScrollView.

Depending on the method you use, it will even disappear. Let’s dive in.

Code simple demo to show what happens.

import SwiftUI

struct ContentView: View {
    var body: some View {
        ScrollView { // It also happens using List (instead ScrollView + LazyVStack)
            LazyVStack {
                ForEach(1..<101, id: \.self) { msg in
                    messageView(msg)
                        .upsideDown() // Upside down each element, you can try .upsideDownBis()
                }
            }
        }
        .upsideDown() // Upside down entire ScrollView, you can try .upsideDownBis()
    }

    private func messageView(_ msg: Int) -> some View {
        Text("Msg no. \(msg)")
            .padding()
            .background(Color.red.cornerRadius(8))
            .contextMenu {
                    Button(action: {
                        print("A")
                    }) {
                        Text("Button A")
                    }

                    Button(action: {
                        print("B")
                    }) {
                        Text("Button B")
                    }
            }
    }
}

// Just for setting upside down list/ ScrollView
extension View {
    func upsideDown() -> some View {
        self
            .rotationEffect(Angle(radians: .pi))
            .scaleEffect(x: -1, y: 1, anchor: .center)
    }

    // This one just rotates, does not disappear.
    func upsideDownBis() -> some View {
        self
            .rotationEffect(Angle(radians: .pi))
    }
}

GIF resources of this behaviour on iOS 15 and 16:

iOS 15/16 when applying upsideDown() modifier -> Bug:

iOS 15/16, upsideDown() modifier -> Bug

iOS 15/16 when applying upsideDownBis() modifier -> Undesired animation:
iOS 15/16, upsideDownBis() modifier -> Undesired animation

What we have checked?

As mentioned before, every solution posted at this post and some others. The ideas apart from those have been:

  1. As scaleEffect is really causing the worst part of the bug, I did try to set x: -1 to x: 1, when performing a contextMenu gesture… But seems faster than longPressGesture “recogniser”.
  2. Similar to 1. but on upsideDownBis() trying to avoid the animation, setting it to nil, nor making the modifier not to apply in that case…
    So, as things stand, I can’t recognize a longPressGesture before contextMenu does appear.

Questions

  1. Is there any work around for this? To not have that animation with upsideDownBis() ?
  2. Is there any work around for this? To not have that bug with upsideDown() ?

[ad_2]