Swift.小型弹出列表菜单

效果图

实现效果:

点击弹出小型列表菜单.

view.frame,初始位置等都可通过调用方法自定制.

实现cell数量自适应,当数量大于4时,view高度固定,可滑动.

cell实现纯文字与icon+文字两种状态.自适应.

通过回调响应点击方法.

点任意位置菜单消失.

实现思路:

本质上这个弹出菜单是一个tableView.

所以我们实现的是一个弹出一个背景透明的全屏View,其中包含一个小tableView.

实现方式:

1.创建弹出View,并添加tableView.

2.使用drawRect方法,添加tableView上的小三角形.

3.创建menuCell,使其实现纯文字,icon+文字两种type

4.创建EWPopMenu类,留出外部方法方便调用


1.创建弹出View,并添加tableView.

     /// init
    ///
    /// - Parameters:
    ///   - width: tableView.width
    ///   - height: tableView最大height,如果cell数量大于4,则是tableView.frame.size.height
    ///   - point: 初始点,tableView上的三角形的顶点
    ///   - items: 每个cell的title数组
    ///   - imgSource: 每个cell的icon数组,可为空
    ///   - action: 回调方法
    init(width: CGFloat, height: CGFloat, point: CGPoint, items: [String], imgSource: [String],  action: ((Int) -> ())?){
        super.init(frame:CGRect(x: 0, y: 0, width: ScreenInfo.Width, height: ScreenInfo.Height))
        drawMyTableView()
        /// view全屏展示
        self.frame = CGRect(x: 0, y: 0, width: ScreenInfo.Width, height: ScreenInfo.Height)
        /// 获取起始点
        self.point = CGPoint(x: point.x, y: ScreenInfo.navigationHeight + point.y)
        /// tableView高度由init方法传入
        self.layerWidth = width
        self.titleSource.removeAll()
        self.titleSource += items
        self.imgSource.removeAll()
        self.imgSource += imgSource
        /// 如果图片数组与标题数组数量不符,则不展示图片
        if imgSource.count != titleSource.count{
            self.imgSource.removeAll()
        }
        /// 如果没有图片展示,则将tabelView宽度控制在100
        if imgSource.count == 0{
            self.layerWidth = 100
        }
        /// 弱引用防止闭包循环引用
        weak var weakSelf = self
        if action != nil{
            weakSelf?.indexBlock = { row in
                /// 点击cell回调,将点击cell.indexpath.row返回
                action!(row)
            }
        }
        /// tableView高度,如果大于4个则为4个itemHeight,使tableView可滑动,如果小于4个则动态显示
        self.layerHeight = titleSource.count > 4 ? height : CGFloat(CGFloat(items.count) * itemHeight)
        self.addSubview(self.tableView)
        /// 将tableView.frame更新,使其在展示正确效果
        let y1 = (self.point?.y)! + 10
        let x2 = (self.point?.x)! - self.layerWidth! + 20
        tableView.frame = CGRect(x: x2, y: y1, width: self.layerWidth!, height: self.layerHeight!)
        self.backgroundColor = UIColor.clear
    }

extension EWPopMenuView:UITableViewDelegate,UITableViewDataSource{

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return itemHeight
    }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.titleSource.count
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier:  EWMenuTableViewCell.identifier) as? EWMenuTableViewCell else {
            return EWMenuTableViewCell()
        }
        cell.setContentBy(titArray: self.titleSource, imgArray: self.imgSource, row: indexPath.row)
        cell.conLabel.text = self.titleSource[indexPath.row]
        return cell
    }
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        self.indexBlock!(indexPath.row)
    }
}

2.使用drawRect方法,添加tableView上的小三角形.

     /// drawRect方法,画tableView上的小三角形
    override func draw(_ rect: CGRect) {
        let y1 = (self.point?.y)! + 10
        let x1 = (self.point?.x)! - 10
        let x2 = (self.point?.x)! + 10

        UIColor(white: 0, alpha: 0.66).set()

        let context = UIGraphicsGetCurrentContext()
        context?.beginPath()
        context?.move(to: CGPoint(x: (self.point?.x)!, y: (self.point?.y)!))
        context?.addLine(to: CGPoint(x: x1, y: y1))
        context?.addLine(to: CGPoint(x: x2, y: y1))
        context?.closePath()
        context?.fillPath()
        context?.drawPath(using: .stroke)
    }

3.创建menuCell,使其实现纯文字,icon+文字两种type

public func setContentBy(titArray: [String], imgArray: [String], row: Int){
        if imgArray.count == 0{
            self.iconImg.isHidden = true
            self.conLabel.frame = CGRect(x: kLineXY, y: 0, width: itemWidth - kLineXY * 2, height: itemHeight)
        }else{
            self.iconImg.isHidden = false
            self.conLabel.frame = CGRect(x: self.iconImg.frame.maxX + kImgLabelWidth, y: 0, width: itemWidth - kImgLabelWidth - kLineXY - kImageWidth - 15 , height: itemHeight)
            self.iconImg.image = UIImage(named: imgArray[row])
        }
    }

4.创建EWPopMenu类,留出外部方法方便调用

let NavigationMenuShared = EWPopMenu.shared

class EWPopMenu: NSObject {
    static let shared = EWPopMenu()
    private var menuView: EWPopMenuView?

    public func showPopMenuSelecteWithFrameWidth(width: CGFloat, height: CGFloat, point: CGPoint, item: [String], imgSource: [String], action: @escaping ((Int) -> ())){
        weak var weakSelf = self
        /// 每次重置保证显示效果
        if self.menuView != nil{
            weakSelf?.hideMenu()
        }
        let window = UIApplication.shared.windows.first
        self.menuView = EWPopMenuView(width: width, height: height, point: point, items: item, imgSource: imgSource, action: { (index) in
            ///点击回调
            action(index)
            weakSelf?.hideMenu()
        })
        menuView?.touchBlock = {
            weakSelf?.hideMenu()
        }
        self.menuView?.backgroundColor = UIColor.black.withAlphaComponent(0)
        window?.addSubview(self.menuView!)
    }
    public func hideMenu(){
        self.menuView?.removeFromSuperview()
        self.menuView = nil
    }
}

使用方法:

将EWPopMenu文件夹拖入项目,调用时:

let items: [String] = ["测试1","测试2"]
let imgSource: [String] = ["test1","test2"]
NavigationMenuShared.showPopMenuSelecteWithFrameWidth(width: itemWidth, height: 160, point: CGPoint(x: ScreenInfo.Width - 30, y: 0), item: items, imgSource: imgSource) { (index) in
///点击回调
    switch index{
    case 0:
        EWToast.showCenterWithText(text: "点击测试1")
    case 1:
        EWToast.showCenterWithText(text: "点击测试2")
    default:
        break
    }
}

项目地址:EWPopMenu

有问题欢迎探讨.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,386评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,142评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,704评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,702评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,716评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,573评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,314评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,230评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,680评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,873评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,991评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,706评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,329评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,910评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,038评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,158评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,941评论 2 355

推荐阅读更多精彩内容