SwiftUI: Shadow glitch after context menu

Viewed 354

I have a rectangle with a shadow and a context menu. When I close this context menu the shadow of the rectangle appears with a delay (~0.5 seconds). Both the shadow of the complete rectangle as well the shadow of the inner elements. I'm not sure what I am doing wrong.

enter image description here

struct Playground: View {
    var body: some View {
        VStack(alignment: .leading, spacing: 4.0) {
            Spacer()
            HStack {
                Spacer()
                Image(systemName: "house")
                    .font(.system(size: 50))
                Spacer()
            }
            Text("SwiftUI for iOS 14").fontWeight(.bold).foregroundColor(Color.white)
            Text("20 Sections").font(.footnote).foregroundColor(Color.white)
        }
        .frame(width: 200, height: 300)
        .padding(.all)
        .background(Color.blue)
        .cornerRadius(20.0)
        .shadow(radius: 10)
        .contentShape(RoundedRectangle(cornerRadius: 20))
        .contextMenu(menuItems: {
            Text("Menu Item 1")
            Text("Menu Item 2")
            Text("Menu Item 3")
        })
    }
}
1 Answers

I found a hacky way to mitigate the issue. This is using pure UIKit and Objective-C but it might be able to be done in SwiftUI too in one way or another.

This is a temporary direct-via-subview access to the view that animates, and I simply attach a shadow to it. This way the animating view will have a shadow and when the REAL shadow pops in, it does so below this shadow. The result looks fine.

-(void)contextMenuInteraction:(UIContextMenuInteraction *)interaction 
      willEndForConfiguration:(UIContextMenuConfiguration *)configuration 
                     animator:(id<UIContextMenuInteractionAnimating>)animator {
  // TODO: Find view dynamically /safer
  UIView *platter = (UIView*)self.view.window.subviews[1].subviews[1].subviews[0];
  platter.clipsToBounds = NO;
  platter.layer.shadowOffset = CGSizeMake(0, 0);
  platter.layer.shadowRadius = 5;
  platter.layer.shadowOpacity = 0.5;
  platter.layer.shadowColor = [UIColor blackColor].CGColor;
}

This works in iOS 13. Have not tried on iOS 14.

Related