簡體   English   中英

在 SwiftUI 中自定義上下文菜單項高亮顏色

[英]Customize context menu item highlight color in SwiftUI

我有一個按鈕,其圖像周圍有一些額外的空白。 經常點擊時的高亮看起來很好,並且不會影響空白空間。 但是,當按住以調出上下文菜單時,淺灰色突出顯示應用於整個圖像區域,這看起來很糟糕。

有沒有辦法自定義此突出顯示以使顏色清晰?

我嘗試過但不起作用的一種可能性:

.contentShape(.contextMenuPreview, Circle().size(width: 0, height: 0))

這里的問題是它導致整個視圖在上下文菜單 animation 和可見性期間消失。 我想將突出顯示的顏色更改為清除,同時保持小調整大小 animation,當然還有按鈕的可見性。

iPhone 模擬器屏幕截圖顯示不正確的上下文菜單突出顯示

SwiftUI 不提供刪除背景的選項,但您可以使用其 UIKit 對應的UIContextMenuInteraction

func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configuration: UIContextMenuConfiguration, highlightPreviewForItemWithIdentifier identifier: NSCopying) -> UITargetedPreview? 

並實施您自己的預覽。 它看起來像下面這樣。

func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configuration: UIContextMenuConfiguration, highlightPreviewForItemWithIdentifier identifier: NSCopying) -> UITargetedPreview? {
    print(#function)
    
    interaction.view?.backgroundColor = .clear
    let previewTarget = UIPreviewTarget(container: interaction.view!, center: interaction.view!.center)
    
    let previewParams = UIPreviewParameters()
    
    previewParams.backgroundColor = .clear
    
    return .init(view: interaction.view!, parameters: previewParams, target: previewTarget)
}

您將使用該代碼得到類似的東西。

在此處輸入圖像描述

您將在下面找到完整的實現

struct CustomContextMenuView: View {
    var body: some View {
        
        Image(systemName: "person")
            .resizable()
            .frame(width: 100, height: 100)
        
            .contextMenu(actions: [
                UIAction(title: "Add to Favorites", image: UIImage(systemName: "heart.fill"), handler: { a in
                    print("Add to Favorites action")
                    
                })
            ], willEnd:  {
                //Called when the menu is dismissed
                print("willEnd/onDismiss")
                
            }, willDisplay:  {
                //Called when the menu appears
                print("willDisplay/onAppear")
                
            })
        
        
    }
}

extension View {
    func contextMenu(actions: [UIAction], willEnd: (() -> Void)? = nil, willDisplay: (() -> Void)? = nil) -> some View {
        modifier(ContextMenuViewModifier(actions: actions, willEnd: willEnd, willDisplay: willDisplay))
    }
}
struct ContextMenuViewModifier: ViewModifier {
    let actions: [UIAction]
    let willEnd: (() -> Void)?
    let willDisplay: (() -> Void)?
    func body(content: Content) -> some View {
        Interaction_UI(view: {content}, actions: actions, willEnd: willEnd, willDisplay: willDisplay)
            .fixedSize()
        
    }
}

struct Interaction_UI<Content2: View>: UIViewRepresentable{
    typealias UIViewControllerType = UIView
    @ViewBuilder var view: Content2
    let actions: [UIAction]
    let willEnd: (() -> Void)?
    let willDisplay: (() -> Void)?
    func makeCoordinator() -> Coordinator {
        return Coordinator(parent: self)
    }
    func makeUIView(context: Context) -> some UIView {
        let v = UIHostingController(rootView: view).view!
        context.coordinator.contextMenu = UIContextMenuInteraction(delegate: context.coordinator)
        v.addInteraction(context.coordinator.contextMenu!)
        return v
    }
    
    func updateUIView(_ uiView: UIViewType, context: Context) {
        
    }
    class Coordinator: NSObject,  UIContextMenuInteractionDelegate{
        var contextMenu: UIContextMenuInteraction!
        
        let parent: Interaction_UI
        
        init(parent: Interaction_UI) {
            self.parent = parent
        }
        func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {
            UIContextMenuConfiguration(identifier: nil, previewProvider: nil, actionProvider: { [self]
                suggestedActions in
                
                return UIMenu(title: "", children: parent.actions)
            })
        }
        func contextMenuInteraction(_ interaction: UIContextMenuInteraction, willDisplayMenuFor configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionAnimating?) {
            print(#function)
            parent.willDisplay?()
        }
        func contextMenuInteraction(_ interaction: UIContextMenuInteraction, willEndFor configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionAnimating?) {
            print(#function)
            parent.willEnd?()
            
        }
        func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configuration: UIContextMenuConfiguration, highlightPreviewForItemWithIdentifier identifier: NSCopying) -> UITargetedPreview? {
            print(#function)
            
            interaction.view?.backgroundColor = .clear
            let previewTarget = UIPreviewTarget(container: interaction.view!, center: interaction.view!.center)
            
            let previewParams = UIPreviewParameters()
            
            previewParams.backgroundColor = .clear
            
            return .init(view: interaction.view!, parameters: previewParams, target: previewTarget)
        }
    }
}
struct CustomContextMenuView_Previews: PreviewProvider {
    static var previews: some View {
        CustomContextMenuView()
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM