-
-
Save SpectralDragon/e1c01388db09752eac790ae23f1d4587 to your computer and use it in GitHub Desktop.
This is so great. But how can I change the frame size of the preview?
This is so great. But how can I change the frame size of the preview?
@vulgur I'm not sure, but maybe u can use preferredContentSize for it? Currently, it's works only for subclasses of UIHostingViewController (https://openradar.appspot.com/FB7650894)
I am having a problem implementing this. While the preview works perfectly. During the animation effect the text that is long pressed has a white overlay. This same thing happens when I close the view. I wouldn't mind this but for the fact that I am using it inside of a list and it pretty much covers the entire item inside of the list for like a second when I close the preview. Any ideas on how I may be able to fix this?
@jalvini did you ever manage to resolve this?
@jalvini @acal11 It looks like the white overlay can be fixed by adding these to Coordinator
:
func contextMenuInteraction(_ interaction: UIContextMenuInteraction, previewForHighlightingMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? {
let parameters = UIPreviewParameters()
parameters.backgroundColor = .clear
return UITargetedPreview(view: interaction.view!, parameters: parameters)
}
func contextMenuInteraction(_ interaction: UIContextMenuInteraction, previewForDismissingMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? {
let parameters = UIPreviewParameters()
parameters.backgroundColor = .clear
return UITargetedPreview(view: interaction.view!, parameters: parameters)
}
what if we have a button in the preview. how action should be triggered? cause now buttons are not working
what if we have a button in the preview. how action should be triggered? cause now buttons are not working
I did it only for previewing :) You could not interact with it at the moment, but if you know how to improve this solution, you're welcome!
The animation when long pressing does not appear but it is a good attempt and does not screw up my layout like other methods! Would appreciate an update to the code where the animation can appear just like Apple's implementation!
This one works good also adding buttons underneath the destination view:
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
Text("Hello, World!")
.contextMenu(PreviewContextMenu(destination: Text("Destination").padding(),
editAction: {
print("Edit action")
},
deleteAction: {
print("Delete action")
}))
}
}
}
// MARK: - Custom Menu Context Implementation
struct PreviewContextMenu<Content: View> {
let destination: Content
let editAction: () -> Void
let deleteAction: () -> Void
let actionProvider: UIContextMenuActionProvider?
init(destination: Content, editAction: @escaping () -> Void, deleteAction: @escaping () -> Void, actionProvider: UIContextMenuActionProvider? = nil) {
self.destination = destination
self.editAction = editAction
self.deleteAction = deleteAction
self.actionProvider = actionProvider
}
}
// UIView wrapper with UIContextMenuInteraction
struct PreviewContextView<Content: View>: UIViewRepresentable {
let menu: PreviewContextMenu<Content>
let didCommitView: () -> Void
func makeUIView(context: Context) -> UIView {
let view = UIView()
view.backgroundColor = .clear
let menuInteraction = UIContextMenuInteraction(delegate: context.coordinator)
view.addInteraction(menuInteraction)
return view
}
func updateUIView(_ uiView: UIView, context: Context) { }
func makeCoordinator() -> Coordinator {
return Coordinator(menu: self.menu, didCommitView: self.didCommitView)
}
class Coordinator: NSObject, UIContextMenuInteractionDelegate {
let menu: PreviewContextMenu<Content>
let didCommitView: () -> Void
init(menu: PreviewContextMenu<Content>, didCommitView: @escaping () -> Void) {
self.menu = menu
self.didCommitView = didCommitView
}
func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {
return UIContextMenuConfiguration(identifier: nil, previewProvider: { () -> UIViewController? in
UIHostingController(rootView: self.menu.destination)
}, actionProvider: { _ in
let editAction = UIAction(title: "Edit", image: UIImage(systemName: "pencil")) { _ in
self.menu.editAction()
}
let deleteAction = UIAction(title: "Delete", image: UIImage(systemName: "trash"), attributes: .destructive) { _ in
self.menu.deleteAction()
}
return UIMenu(title: "", children: [editAction, deleteAction])
})
}
func contextMenuInteraction(_ interaction: UIContextMenuInteraction, willPerformPreviewActionForMenuWith configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionCommitAnimating) {
animator.addCompletion(self.didCommitView)
}
func contextMenuInteraction(_ interaction: UIContextMenuInteraction, previewForHighlightingMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? {
let parameters = UIPreviewParameters()
parameters.backgroundColor = .clear
return UITargetedPreview(view: interaction.view!, parameters: parameters)
}
func contextMenuInteraction(_ interaction: UIContextMenuInteraction, previewForDismissingMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? {
let parameters = UIPreviewParameters()
parameters.backgroundColor = .clear
return UITargetedPreview(view: interaction.view!, parameters: parameters)
}
}
}
// Add context menu modifier
extension View {
func contextMenu<Content: View>(_ menu: PreviewContextMenu<Content>) -> some View {
self.modifier(PreviewContextViewModifier(menu: menu))
}
}
struct PreviewContextViewModifier<V: View>: ViewModifier {
let menu: PreviewContextMenu<V>
@Environment(\.presentationMode) var mode
@State var isActive: Bool = false
func body(content: Content) -> some View {
Group {
if isActive {
VStack {
menu.destination
HStack {
Button("Edit") {
menu.editAction()
}
.padding()
Button("Delete") {
menu.deleteAction()
}
.padding()
}
}
} else {
content.overlay(PreviewContextView(menu: menu, didCommitView: { self.isActive = true }))
}
}
}
}
Hi! Sorry, I didn’t save the example project