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
    }
}

github地址:EWPopMenu

有问题欢迎探讨.

猜你喜欢

转载自blog.csdn.net/weixin_43566445/article/details/84314011