美文网首页UI
Swift:仿文件 app 菜单 UIMenu 实现 @avai

Swift:仿文件 app 菜单 UIMenu 实现 @avai

作者: SoaringHeart | 来源:发表于2021-07-07 13:14 被阅读0次

    implement checkmark on dropdown menu like “Files” app on swift.

    功能实现:

    section1:单选,section2:多选

    Screenshot:

    WechatIMG22.jpeg

    Example:

    import UIKit
    import SwiftExpand
    
    @available(iOS 14.0, *)
    class MenuActionChooseOneController: UIViewController {
    
        var menuData: [(String, [(String, UIImage?)])] {
            return [
                ("Menu", [
                    (title: "选择", image: UIImage.checkmark_circle),
                    (title: "新建文件夹", image: UIImage.folder_badge_plus),
                    (title: "扫描文档", image: UIImage.doc_text_viewfinder),
                    (title: "连接服务器", image: UIImage.rectangle_connected_to_line_below),
                    ]
                ),
                ("Menu1", [
                    (title: "图标", image: UIImage.square_grid_2x2),
                    (title: "列表", image: UIImage.list_bullet),
                    ]
                ),
                
                ("Menu2", [
                    (title: "名称", image: UIImage.chevron_up),
                    (title: "日期", image: UIImage.chevron_down),
                    (title: "大小", image: UIImage.chevron_left),
                    (title: "种类", image: UIImage.chevron_right),
                    (title: "标签", image: nil),
                    ]
                ),
            ]
        }
        
        lazy var menuBtn: UIButton = {
            let sender = UIButton(type: .custom)
            sender.setTitle("menu", for: .normal);
            sender.showsMenuAsPrimaryAction = true
            sender.menu = UIMenu.map(data: menuData, handler: { action in
                switch action.title {
                case "图标", "列表":
                    action.handleStateChange(sender, section: 1, isSingleChoose: true) {
                        DDLog(sender.checkRow(by: 1))
                //        DDLog(sender.checkActions(by: 1))
                        let tmp = sender.checkActions(by: 1)
                        DDLog(tmp?.map({ $0.title }))
                    }
    
                case "名称", "日期", "大小", "种类", "标签":
                    action.handleStateChange(sender, section: 2, isSingleChoose: false) {
                        DDLog(sender.checkRow(by: 2))
                //        DDLog(sender.checkActions(by: 2))
                        let tmp = sender.checkActions(by: 2)
                        DDLog(tmp?.map({ $0.title }))
                    }
                    
                default:
                    DDLog(action.title)
                }
            })
            return sender
        }()
        
        
        var isListMode: Bool{
            guard let row = menuBtn.checkRow(by: 1) else { return true }
            return row == 1
    //        guard let menu1 = self.menuBtn.menu?.children[1] as? UIMenu,
    //              let value = menu1.children[0].value(forKey: kActionState) as? Int
    //              else { return true }
    //        return value == 1
        }
        // MARK: -lifecycle
        override func viewDidLoad() {
            super.viewDidLoad()
    
            // Do any additional setup after loading the view.
            edgesForExtendedLayout = []
            view.backgroundColor = .white
            title = "MenuActionChooseOne"
            
            navigationItem.rightBarButtonItem = UIBarButtonItem(customView: menuBtn)
        }
        
        // MARK: -funtions
    
    }
    
    

    UIMenu+Helper

    
    /// UIAction: "_state"
    public let kActionState = "_state"
    
    @available(iOS 14.0, *)
    public extension UIMenu{
    
        /// Data mapping UIMenu structure
        static func map(_ title: String = "", data: [(String, [(String, UIImage?)])], handler: @escaping UIActionHandler) -> UIMenu {
            return UIMenu(title: title, children: data.map {
                UIMenu(title: $0.0, options: .displayInline, children: $0.1.map({
                        return UIAction(title: $0.0, image: $0.1, handler: handler)
                    })
                )
            })
        }
    }
    
    @available(iOS 14.0, *)
    public extension UIAction{
        
        /// state change(.on/.off), Support single selection/multiple selection.
        func handleStateChange(_ sender: UIButton, section: Int, isSingleChoose: Bool, handler: (()->Void)?) {
            guard let menu = sender.menu?.children[section] as? UIMenu else { return }
            if isSingleChoose == false {
                if self.state == .off {
                    self.setValue(1, forKey: kActionState)
                } else if self.state == .on {
                    self.setValue( 0, forKey: kActionState)
                }
            } else {
                menu.children.forEach {
                    $0.setValue($0 == self ? 1 : 0, forKey: kActionState)
                }
            }
            handler?()
        }
    }
    
    
    @available(iOS 14.0, *)
    public extension UIButton {
            
        /// Actions (Support single selection/multiple selection)
        /// - Returns: row(state is on)
        func checkActions(by section: Int) -> [UIAction]?{
            guard let sectionMenu = menu?.children[section] as? UIMenu
                  else { return nil }
            
            let firters = sectionMenu.children.filter {
                guard let action = $0 as? UIAction,
                      let value = action.value(forKey: kActionState) as? Int else { return false }
                return value == 1
            }
            return firters as? [UIAction]
        }
        
        /// row(Support single selection)
        /// - Returns: row(state is on)
        func checkRow(by section: Int) -> Int?{
            guard let sectionMenu = menu?.children[section] as? UIMenu
                  else { return nil }
            
            let firters = sectionMenu.children.filter {
                guard let value = $0.value(forKey: kActionState) as? Int else { return false }
                return value == 1
            }
    
            guard let checkAction = firters.first as? UIAction else { return nil }
            return sectionMenu.children.firstIndex(of: checkAction)
        }
        
    }
    

    Github

    相关文章

      网友评论

        本文标题:Swift:仿文件 app 菜单 UIMenu 实现 @avai

        本文链接:https://www.haomeiwen.com/subject/wkeoultx.html