You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS如何自定义默认Contextual Menu?修改图标位置至左侧

自定义iOS Contextual Menu:将图标移至左侧

需求:修改iOS系统默认Contextual Menu的布局,让菜单选项中的图标显示在文字左侧。尝试通过设置UIView.appearance().semanticContentAttribute = .forceRightToLeft实现,但未达到预期效果。

当前代码(基于UIKit,iOS15+):

import UIKit

@available(iOS 14.0, *)
class ViewController: UIViewController, UIContextMenuInteractionDelegate {
  
    @IBOutlet weak var imageView: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let interaction = UIContextMenuInteraction(delegate: self)
        imageView.addInteraction(interaction)
        imageView.isUserInteractionEnabled = true
        imageView.layer.cornerRadius = 25
        
    }
    
    func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {
        imageView.layer.borderWidth = 4
        imageView.layer.cornerRadius = 25
        imageView.layer.borderColor = CGColor.init(red: 256, green: 256, blue: 256, alpha: 1)
        return UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { _ -> UIMenu? in
            return self.createContextMenu()
        }
    }
    
    func contextMenuInteraction(_ interaction: UIContextMenuInteraction, willEndFor configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionAnimating?) {
        self.imageView.layer.borderWidth = 0
    }
    
    func createContextMenu() -> UIMenu {
        let shareAction = UIAction(title: "Share", image: UIImage(systemName: "square.and.arrow.up")) { _ in
            self.imageView.layer.borderWidth = 0
            print("Share")
        }
        
        let copy = UIAction(title: "Copy", image: UIImage(systemName: "doc.on.doc")) { _ in
            print("Copy")
            self.imageView.layer.borderWidth = 0
        }
        
        let saveToPhotos = UIAction(title: "Add To Photos", image: UIImage(systemName: "photo")) { _ in
            print("Save to Photos")
            self.imageView.layer.borderWidth = 0
        }
        
        UIView.appearance().semanticContentAttribute = .forceRightToLeft
        return UIMenu(title: "", children: [saveToPhotos, copy, shareAction])
    }
}

当前UI效果:菜单选项文字居左,图标居右。
期望UI效果:菜单选项图标居左,文字居右。


解决方案

方法1:针对菜单单元格设置语义方向(兼容iOS15+)

全局设置UIView.appearance()会影响所有视图,且无法精准作用于Contextual Menu的选项单元格。正确做法是针对菜单的私有单元格类UIContextMenuActionCell设置语义方向,仅修改菜单选项布局:

在createContextMenu()方法中,替换全局UIView外观设置,改为:

// 仅针对Contextual Menu的选项单元格设置语义方向
if let cellClass = NSClassFromString("UIContextMenuActionCell") as? UIView.Type {
    cellClass.appearance().semanticContentAttribute = .forceRightToLeft
}

方法2:使用iOS16+原生属性(更优雅)

如果项目支持iOS16及以上,可直接给UIAction添加.imageLeading属性,无需修改语义方向:

let shareAction = UIAction(title: "Share", image: UIImage(systemName: "square.and.arrow.up"), attributes: .imageLeading) { _ in
    self.imageView.layer.borderWidth = 0
    print("Share")
}

let copy = UIAction(title: "Copy", image: UIImage(systemName: "doc.on.doc"), attributes: .imageLeading) { _ in
    print("Copy")
    self.imageView.layer.borderWidth = 0
}

let saveToPhotos = UIAction(title: "Add To Photos", image: UIImage(systemName: "photo"), attributes: .imageLeading) { _ in
    print("Save to Photos")
    self.imageView.layer.borderWidth = 0
}

注意事项

  • 方法1中使用的UIContextMenuActionCell是私有类,当前iOS版本兼容,但后续苹果可能修改类名,需关注兼容性。
  • 方法2的.imageLeading属性为iOS16新增,若需兼容iOS15,建议使用方法1。

内容的提问来源于stack exchange,提问作者Pushkar Pandey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 01:05:27