├── LICENSE ├── README.md ├── SwiftPopMenu.podspec ├── SwiftPopMenu └── SwiftPopMenu.swift ├── SwiftPopMenuDemo ├── SwiftPopMenu.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ ├── MACBOOK.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ │ │ └── liyajun.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ ├── MACBOOK.xcuserdatad │ │ └── xcschemes │ │ │ ├── SwiftPopMenu.xcscheme │ │ │ └── xcschememanagement.plist │ │ └── liyajun.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ └── xcschememanagement.plist ├── SwiftPopMenu │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── Shape.imageset │ │ │ ├── Contents.json │ │ │ ├── Shape.png │ │ │ ├── Shape@2x.png │ │ │ └── Shape@3x.png │ │ ├── SignRule.imageset │ │ │ ├── Contents.json │ │ │ ├── SignRule.png │ │ │ ├── SignRule@2x.png │ │ │ └── SignRule@3x.png │ │ └── saoyisao.imageset │ │ │ ├── Contents.json │ │ │ ├── saoyisao.png │ │ │ ├── saoyisao@2x.png │ │ │ └── saoyisao@3x.png │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ ├── SwiftPopMenuSrc │ │ └── SwiftPopMenu.swift │ └── ViewController.swift └── SwiftPopMenuUITests │ ├── Info.plist │ └── SwiftPopMenuUITests.swift ├── img1.png ├── img2.png ├── img3.png └── swiftPopMenu.gif /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011-2016 SwiftPopMenu Software Foundation (https://github.com/TangledHusky/SwiftPopMenu) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SwiftPopMenu 效果图: 2 | 3 | 4 | 5 | 6 | 7 | 功能: 8 | 只需要传入菜单箭头点位置、菜单宽度、数据源即可。 9 | 10 | 1、支持任意点弹出(点是基于整个屏幕位置) 11 | 2、会根据点位置自动计算菜单位置和高度 12 | 3、背景色、文字等属性支持自定义设置 13 | 4、easy自定义,有更多需求,可以直接在SwiftPopMenu.swift自己修改 14 | 15 | 16 | 导入项目: 17 | 18 | - pods导入:pod 'SwiftPopMenu' 19 | 20 | - 文件导入:下载Demo,导入SwiftPopMenu.swift文件即可 21 | 22 | - 代码现已支持 Swift5 (2.x已支持swift5,1.x支持swift3) 23 | 24 | 25 | 使用介绍: 26 | 27 | import SwiftPopMenu 28 | 29 | 30 | 1、初始化Init 31 |
 32 | 
 33 |     ///初始化菜单
 34 |     init(menuWidth:CGFloat,                                 //菜单宽度(高度不需要传,会根据item高*item数量自动计算)
 35 |          arrow:CGPoint,                                     //箭头点位置是基于整个屏幕的位置
 36 |          datas:[(icon:String,title:String)],                //数据源数组,icon没有就传空
 37 |          configures:[SwiftPopMenuConfigure] = []            //配置信息,可不传,不传采用默认值
 38 |          ) {}
 39 | 
 40 | 
41 | 42 | 2、显示与移除 43 |
 44 |  popMenu.show()
 45 | 
 46 |  popMenu.dismiss()  
 47 | 
48 | 49 | 3、点击事件,提供两种方式 50 | 51 | - block回调处理 52 | - delegate代理处理 53 | 54 | 4、参数配置(使用时可不传) 55 |
 56 | public enum SwiftPopMenuConfigure {
 57 |     case PopMenuTextFont(UIFont)            //菜单文字字体,默认systemFont(ofSize: 17)
 58 |     case PopMenuTextColor(UIColor)          //菜单文字颜色,默认black
 59 |     case PopMenuBackgroudColor(UIColor)     //菜单背景色,默认white
 60 |     case popMenuCornorRadius(CGFloat)       //菜单圆角,默认6
 61 |     case popMenuItemHeight(CGFloat)         //菜单内单行高度(非整个menu高度),默认44.0
 62 |     case popMenuSplitLineColor(UIColor)     //菜单分割线颜色,默认(222,222,222)
 63 |     case popMenuIconLeftMargin(CGFloat)     //icon左间距,默认15
 64 |     case popMenuMargin(CGFloat)             //菜单与屏幕边距,默认10
 65 |     case popMenuAlpha(CGFloat)              //菜单背景透明度,默认0.3
 66 | }
 67 |  
68 | 69 | 完整示例代码: 70 |
 71 | var popMenu:SwiftPopMenu!
 72 | 
 73 |  
 74 |  //数据源(icon可不填)
 75 | let popData = [(icon:"saoyisao",title:"扫一扫"),
 76 |                (icon:"SignRule",title:"签到规则"),
 77 |                (icon:"saoyisao",title:"扫一扫"),
 78 |                (icon:"SignRule",title:"签到规则")]
 79 | 
 80 | //设置Parameter(可不写)
 81 | let parameters:[SwiftPopMenuConfigure] = [
 82 |     .PopMenuTextColor(UIColor.black),
 83 |     .popMenuItemHeight(44),
 84 |     .PopMenuTextFont(UIFont.systemFont(ofSize: 18))
 85 | ]
 86 | 
 87 | //init  (注意:arrow点是基于屏幕的位置)
 88 | popMenu = SwiftPopMenu(menuWidth: 150, arrow: CGPoint(x: 100, y: 100), datas: popData,configures: parameters)
 89 | 
 90 | //click
 91 | popMenu.didSelectMenuBlock = { [weak self](index:Int)->Void in            
 92 |     print("block select \(index)")
 93 |     self?.popMenu = nil
 94 | }
 95 | 
 96 | //show
 97 | popMenu.show()
 98 | 
 99 | 
100 | 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /SwiftPopMenu.podspec: -------------------------------------------------------------------------------- 1 | 2 | Pod::Spec.new do |s| 3 | 4 | 5 | 6 | s.name = "SwiftPopMenu" 7 | s.version = "2.0.2" 8 | s.summary = "support swift5 ,any point pop" 9 | s.swift_version = '5.0' 10 | 11 | s.description = "优化使用方式 support swift5 ,easy use SwiftPopMenu on iOS" 12 | 13 | s.homepage = "https://github.com/TangledHusky/SwiftPopMenu" 14 | 15 | 16 | s.license = { :type => "MIT", :file => "LICENSE" } 17 | 18 | 19 | s.author = { "TangledHusky" => "994825763@qq.com" } 20 | s.platform = :ios, "8.0" 21 | 22 | 23 | 24 | s.source = { :git => "https://github.com/TangledHusky/SwiftPopMenu.git", :tag => "v#{s.version}" } 25 | 26 | 27 | 28 | s.source_files = "SwiftPopMenu/*.{swift}" 29 | 30 | 31 | 32 | 33 | end 34 | -------------------------------------------------------------------------------- /SwiftPopMenu/SwiftPopMenu.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PopView.swift 3 | // TestSwift 4 | // 5 | // Created by lyj on 16/5/7. 6 | // Copyright © 2016年 zyyj. All rights reserved. 7 | /* 8 | GitHub:https://github.com/TangledHusky/SwiftPopMenu 9 | 10 | 功能: 11 | 只需要传入菜单箭头点位置、菜单宽度、数据源即可。 12 | 13 | 1、支持任意点弹出(点是基于整个屏幕位置) 14 | 2、会根据点位置自动计算菜单位置 15 | 3、背景色、文字等支持自定义设置 16 | 4、菜单最大宽度=屏幕-边距 最大高度=屏幕高度一半 17 | */ 18 | 19 | import UIKit 20 | 21 | public protocol SwiftPopMenuDelegate :NSObjectProtocol{ 22 | func swiftPopMenuDidSelectIndex(index:Int) 23 | } 24 | 25 | 26 | public enum SwiftPopMenuConfigure { 27 | case PopMenuTextFont(UIFont) //菜单文字字体 28 | case PopMenuTextColor(UIColor) //菜单文字颜色 29 | case PopMenuBackgroudColor(UIColor) //菜单背景色 30 | case popMenuCornorRadius(CGFloat) //菜单圆角 31 | case popMenuItemHeight(CGFloat) //菜单行高度 32 | case popMenuSplitLineColor(UIColor) //菜单分割线颜色 33 | case popMenuIconLeftMargin(CGFloat) //icon左间距 34 | case popMenuMargin(CGFloat) //菜单与屏幕边距 35 | case popMenuAlpha(CGFloat) //菜单背景透明度 36 | } 37 | 38 | public class SwiftPopMenu: UIView { 39 | 40 | //delegate 41 | weak var delegate : SwiftPopMenuDelegate? 42 | //block 43 | public var didSelectMenuBlock:((_ index:Int)->Void)? 44 | 45 | let KScrW:CGFloat = UIScreen.main.bounds.size.width 46 | let KScrH:CGFloat = UIScreen.main.bounds.size.height 47 | 48 | 49 | 50 | ///* ----------------------- 外部参数 通过configure设置 ---------------------------- */ 51 | //区域外背景透明度 52 | private var popMenuOutAlpha:CGFloat = 0.3 53 | //背景色 54 | private var popMenuBgColor:UIColor = UIColor.white 55 | //圆角弧度 56 | private var popMenuCornorRadius:CGFloat = 6 57 | //文字颜色 58 | private var popMenuTextColor:UIColor = UIColor.black 59 | //字体大小等 60 | private var popMenuTextFont:UIFont = UIFont.systemFont(ofSize: 17) 61 | //菜单高度 62 | private var popMenuItemHeight:CGFloat = 44.0 63 | //菜单分割线颜色 64 | private var popMenuSplitLineColor:UIColor = UIColor(red: 222/255.0, green: 222/255.0, blue: 222/255.0, alpha: 0.5) 65 | //icon左间距 66 | private var popMenuIconLeftMargin:CGFloat = 15 67 | //菜单与屏幕边距 68 | private var popMenuMargin:CGFloat = 10 69 | 70 | ///* ----------------------- 外部参数 over------------------------------------------ */ 71 | 72 | private var arrowPoint : CGPoint = CGPoint.zero //小箭头位置 73 | private var arrowViewWidth : CGFloat = 15 //三角箭头宽 74 | private var arrowViewHeight : CGFloat = 10 //三角箭头高 75 | private var popData:[(icon:String,title:String)]! //数据源 76 | 77 | static let cellID:String = "SwiftPopMenuCellID" 78 | private var myFrame:CGRect! //tableview frame 79 | private var arrowView : UIView! = nil 80 | 81 | var tableView:UITableView! = nil 82 | 83 | 84 | 85 | /// 初始化菜单 86 | /// 87 | /// - Parameters: 88 | /// - menuWidth: 菜单宽度 89 | /// - arrow: 箭头位置是popmenu相对整个屏幕的位置 90 | /// - datas: 数据源,icon允许传空,数据源没数据,不会显示菜单 91 | /// - configure: 配置信息,可不传 92 | public init(menuWidth:CGFloat,arrow:CGPoint,datas:[(icon:String,title:String)],configures:[SwiftPopMenuConfigure] = []) { 93 | super.init(frame: UIScreen.main.bounds) 94 | self.frame = UIScreen.main.bounds 95 | //读取配置 96 | configures.forEach { (config) in 97 | switch (config){ 98 | case let .PopMenuTextFont(value): 99 | popMenuTextFont = value 100 | case let .PopMenuTextColor(value): 101 | popMenuTextColor = value 102 | case let .PopMenuBackgroudColor(value): 103 | popMenuBgColor = value 104 | case let .popMenuCornorRadius(value): 105 | popMenuCornorRadius = value 106 | case let .popMenuItemHeight(value): 107 | popMenuItemHeight = value 108 | case let .popMenuSplitLineColor(value): 109 | popMenuSplitLineColor = value 110 | case let .popMenuIconLeftMargin(value): 111 | popMenuIconLeftMargin = value 112 | case let .popMenuMargin(value): 113 | popMenuMargin = value 114 | case let .popMenuAlpha(value): 115 | popMenuOutAlpha = value 116 | } 117 | } 118 | 119 | popData = datas 120 | //设置myFrame size ,original会在后面计算 121 | myFrame = CGRect(x: 0, y: 0, width: menuWidth, height: popMenuItemHeight*CGFloat(popData.count)) 122 | myFrame.size.height = min(KScrH/2, myFrame.height) 123 | myFrame.size.width = min(KScrW-popMenuMargin*2, myFrame.width) 124 | 125 | //设置肩头,与屏幕间隔10 126 | arrowPoint = arrow 127 | arrowPoint.x = max(popMenuMargin, min(arrowPoint.x, KScrW-popMenuMargin)) 128 | 129 | } 130 | 131 | required public init?(coder aDecoder: NSCoder) { 132 | fatalError("init(coder:) has not been implemented") 133 | } 134 | 135 | 136 | 137 | func initViews() { 138 | self.backgroundColor = UIColor.black.withAlphaComponent(popMenuOutAlpha) 139 | 140 | let arrowPs = getArrowPoints() 141 | myFrame.origin = arrowPs.3 142 | let isarrowUP = arrowPs.4 143 | print(arrowPs) 144 | //箭头 145 | arrowView=UIView(frame: CGRect(x: myFrame.origin.x, y: isarrowUP ? myFrame.origin.y-arrowViewHeight : myFrame.origin.y+myFrame.height, width: myFrame.width, height: arrowViewHeight)) 146 | let layer=CAShapeLayer() 147 | let path=UIBezierPath() 148 | path.move(to: arrowPs.0) 149 | path.addLine(to: arrowPs.1) 150 | path.addLine(to: arrowPs.2) 151 | layer.path=path.cgPath 152 | layer.fillColor = popMenuBgColor.cgColor 153 | arrowView.layer.addSublayer(layer) 154 | self.addSubview(arrowView) 155 | 156 | tableView=UITableView(frame: CGRect(x: myFrame.origin.x,y: myFrame.origin.y,width: myFrame.width,height: myFrame.height), style: .plain) 157 | tableView.register(SwiftPopMenuCell.classForCoder(), forCellReuseIdentifier: SwiftPopMenu.cellID) 158 | tableView.backgroundColor = popMenuBgColor 159 | tableView.layer.cornerRadius = popMenuCornorRadius 160 | tableView.separatorStyle = .none 161 | tableView.layer.masksToBounds = true 162 | tableView.delegate = self 163 | tableView.dataSource = self 164 | tableView.bounces = false 165 | UIView.animate(withDuration: 0.3) { 166 | self.addSubview(self.tableView) 167 | } 168 | } 169 | 170 | 171 | /// 计算箭头位置 172 | /// 173 | /// - Returns: (三角箭头顶,三角箭头左,三角箭头右,tableview 原点,是否箭头朝上) 174 | func getArrowPoints() -> (CGPoint,CGPoint,CGPoint,CGPoint,Bool) { 175 | if arrowPoint.x <= popMenuMargin { 176 | arrowPoint.x = popMenuMargin 177 | } 178 | if arrowPoint.x >= KScrW - popMenuMargin{ 179 | arrowPoint.x = KScrW - popMenuMargin 180 | } 181 | var originalPoint = CGPoint.zero 182 | 183 | //箭头中间距离左边距离 184 | var arrowMargin:CGFloat = popMenuMargin 185 | if arrowPoint.x < KScrW/2{ 186 | if (arrowPoint.x > myFrame.width/2) { 187 | arrowMargin = myFrame.width/2 188 | originalPoint = CGPoint(x: arrowPoint.x - myFrame.width/2, y: arrowPoint.y+arrowViewHeight) 189 | }else{ 190 | arrowMargin = arrowPoint.x-popMenuMargin 191 | originalPoint = CGPoint(x: popMenuMargin, y: arrowPoint.y+arrowViewHeight) 192 | } 193 | 194 | }else{ 195 | 196 | if (KScrW-arrowPoint.x) < myFrame.width/2{ 197 | arrowMargin = (myFrame.width - KScrW + arrowPoint.x ) 198 | originalPoint = CGPoint(x: KScrW-popMenuMargin-myFrame.width, y: arrowPoint.y+arrowViewHeight) 199 | 200 | 201 | }else{ 202 | arrowMargin = myFrame.width/2 203 | originalPoint = CGPoint(x: arrowPoint.x-myFrame.width/2, y: arrowPoint.y+arrowViewHeight) 204 | } 205 | } 206 | 207 | //箭头朝上 208 | if (KScrH - arrowPoint.y) > myFrame.height{ 209 | 210 | return (CGPoint(x: arrowMargin, y: 0),CGPoint(x: arrowMargin-arrowViewWidth/2, y: arrowViewHeight),CGPoint(x: arrowMargin+arrowViewWidth/2, y: arrowViewHeight),originalPoint,true) 211 | 212 | }else{ 213 | originalPoint.y = arrowPoint.y-myFrame.height-arrowViewHeight 214 | 215 | return (CGPoint(x: arrowMargin, y: arrowViewHeight),CGPoint(x: arrowMargin-arrowViewWidth/2, y: 0),CGPoint(x: arrowMargin+arrowViewWidth/2, y: 0),originalPoint,false) 216 | } 217 | 218 | } 219 | 220 | } 221 | 222 | 223 | 224 | // MARK: - 页面显示、隐藏 225 | extension SwiftPopMenu{ 226 | 227 | override public func touchesBegan(_ touches: Set, with event: UIEvent?) { 228 | if touches.first?.view != tableView{ 229 | dismiss() 230 | } 231 | } 232 | 233 | public func show() { 234 | if popData.isEmpty{ 235 | return 236 | } 237 | initViews() 238 | UIApplication.shared.keyWindow?.addSubview(self) 239 | } 240 | 241 | public func dismiss() { 242 | self.removeFromSuperview() 243 | } 244 | 245 | } 246 | 247 | // MARK: - UITableViewDataSource,UITableViewDelegate 248 | extension SwiftPopMenu : UITableViewDataSource,UITableViewDelegate{ 249 | 250 | public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 251 | return popData.count 252 | } 253 | 254 | public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 255 | if popData.count>indexPath.row { 256 | let cell = tableView.dequeueReusableCell(withIdentifier: SwiftPopMenu.cellID) as! SwiftPopMenuCell 257 | 258 | let model = popData[indexPath.row] 259 | cell.setConfig(_txtColor: popMenuTextColor, _lineColor: popMenuSplitLineColor, _txtFont: popMenuTextFont, _iconLeft: popMenuIconLeftMargin) 260 | if indexPath.row == popData.count - 1 { 261 | cell.fill(iconName: model.icon, title: model.title, islast: true) 262 | }else{ 263 | cell.fill(iconName: model.icon, title: model.title) 264 | } 265 | return cell 266 | } 267 | 268 | return UITableViewCell() 269 | } 270 | 271 | public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 272 | return popMenuItemHeight 273 | } 274 | 275 | public func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { 276 | return 0.01 277 | } 278 | 279 | public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 280 | if self.delegate != nil{ 281 | self.delegate?.swiftPopMenuDidSelectIndex(index: indexPath.row) 282 | } 283 | if didSelectMenuBlock != nil { 284 | didSelectMenuBlock!(indexPath.row) 285 | } 286 | 287 | dismiss() 288 | } 289 | 290 | } 291 | 292 | 293 | 294 | /// UITableViewCell 295 | class SwiftPopMenuCell: UITableViewCell { 296 | var iconImage:UIImageView! 297 | var lblTitle:UILabel! 298 | var line:UIView! 299 | 300 | //自定义属性 301 | var lineColor:UIColor = UIColor(red: 222/255.0, green: 222/255.0, blue: 222/255.0, alpha: 0.5) 302 | var txtColor:UIColor = UIColor.black 303 | var txtFont:UIFont = UIFont.systemFont(ofSize: 17) 304 | var iconLeft:CGFloat = 15 305 | 306 | 307 | override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { 308 | super.init(style: style, reuseIdentifier: reuseIdentifier) 309 | self.backgroundColor = UIColor.clear 310 | 311 | iconImage = UIImageView() 312 | self.contentView.addSubview(iconImage) 313 | self.selectionStyle = .none 314 | 315 | lblTitle = UILabel() 316 | self.contentView.addSubview(lblTitle) 317 | 318 | line = UIView() 319 | self.contentView.addSubview(line) 320 | } 321 | 322 | 323 | required init?(coder aDecoder: NSCoder) { 324 | fatalError("init(coder:) has not been implemented") 325 | } 326 | 327 | 328 | func fill(iconName:String,title:String,islast:Bool = false) { 329 | iconImage.image = UIImage(named: iconName) 330 | lblTitle.text = title 331 | line.isHidden = islast 332 | } 333 | 334 | func setConfig(_txtColor:UIColor,_lineColor:UIColor,_txtFont:UIFont,_iconLeft:CGFloat) { 335 | txtColor = _txtColor 336 | txtFont = _txtFont 337 | lineColor = _lineColor 338 | iconLeft = _iconLeft 339 | 340 | line.backgroundColor = lineColor 341 | lblTitle.textColor = txtColor 342 | lblTitle.font = txtFont 343 | } 344 | 345 | override func layoutSubviews() { 346 | super.layoutSubviews() 347 | print(self.bounds) 348 | self.iconImage.frame = CGRect(x: iconLeft, y: (self.bounds.size.height - 20)/2, width: 20, height: 20) 349 | self.lblTitle.frame = CGRect(x: 20+iconLeft*2, y: 0, width: self.bounds.size.width - 40, height: self.bounds.size.height) 350 | self.line.frame = CGRect(x: 0, y: self.frame.size.height - 1, width: self.frame.size.width, height: 1) 351 | 352 | } 353 | 354 | 355 | } 356 | -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenu.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | FA12F7871DF18166002F5FE1 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA12F7861DF18166002F5FE1 /* AppDelegate.swift */; }; 11 | FA12F7891DF18166002F5FE1 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA12F7881DF18166002F5FE1 /* ViewController.swift */; }; 12 | FA12F78C1DF18166002F5FE1 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FA12F78A1DF18166002F5FE1 /* Main.storyboard */; }; 13 | FA12F78E1DF18166002F5FE1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = FA12F78D1DF18166002F5FE1 /* Assets.xcassets */; }; 14 | FA12F7911DF18166002F5FE1 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FA12F78F1DF18166002F5FE1 /* LaunchScreen.storyboard */; }; 15 | FA12F79C1DF18166002F5FE1 /* SwiftPopMenuUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA12F79B1DF18166002F5FE1 /* SwiftPopMenuUITests.swift */; }; 16 | FA12F7AA1DF27AC3002F5FE1 /* SwiftPopMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA12F7A91DF27AC3002F5FE1 /* SwiftPopMenu.swift */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXContainerItemProxy section */ 20 | FA12F7981DF18166002F5FE1 /* PBXContainerItemProxy */ = { 21 | isa = PBXContainerItemProxy; 22 | containerPortal = FA12F77B1DF18166002F5FE1 /* Project object */; 23 | proxyType = 1; 24 | remoteGlobalIDString = FA12F7821DF18166002F5FE1; 25 | remoteInfo = SwiftPopMenu; 26 | }; 27 | /* End PBXContainerItemProxy section */ 28 | 29 | /* Begin PBXFileReference section */ 30 | FA12F7831DF18166002F5FE1 /* SwiftPopMenu.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftPopMenu.app; sourceTree = BUILT_PRODUCTS_DIR; }; 31 | FA12F7861DF18166002F5FE1 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 32 | FA12F7881DF18166002F5FE1 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 33 | FA12F78B1DF18166002F5FE1 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 34 | FA12F78D1DF18166002F5FE1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 35 | FA12F7901DF18166002F5FE1 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 36 | FA12F7921DF18166002F5FE1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 37 | FA12F7971DF18166002F5FE1 /* SwiftPopMenuUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwiftPopMenuUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 38 | FA12F79B1DF18166002F5FE1 /* SwiftPopMenuUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftPopMenuUITests.swift; sourceTree = ""; }; 39 | FA12F79D1DF18166002F5FE1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 40 | FA12F7A91DF27AC3002F5FE1 /* SwiftPopMenu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftPopMenu.swift; sourceTree = ""; }; 41 | /* End PBXFileReference section */ 42 | 43 | /* Begin PBXFrameworksBuildPhase section */ 44 | FA12F7801DF18166002F5FE1 /* Frameworks */ = { 45 | isa = PBXFrameworksBuildPhase; 46 | buildActionMask = 2147483647; 47 | files = ( 48 | ); 49 | runOnlyForDeploymentPostprocessing = 0; 50 | }; 51 | FA12F7941DF18166002F5FE1 /* Frameworks */ = { 52 | isa = PBXFrameworksBuildPhase; 53 | buildActionMask = 2147483647; 54 | files = ( 55 | ); 56 | runOnlyForDeploymentPostprocessing = 0; 57 | }; 58 | /* End PBXFrameworksBuildPhase section */ 59 | 60 | /* Begin PBXGroup section */ 61 | FA12F77A1DF18166002F5FE1 = { 62 | isa = PBXGroup; 63 | children = ( 64 | FA12F7851DF18166002F5FE1 /* SwiftPopMenu */, 65 | FA12F79A1DF18166002F5FE1 /* SwiftPopMenuUITests */, 66 | FA12F7841DF18166002F5FE1 /* Products */, 67 | ); 68 | sourceTree = ""; 69 | }; 70 | FA12F7841DF18166002F5FE1 /* Products */ = { 71 | isa = PBXGroup; 72 | children = ( 73 | FA12F7831DF18166002F5FE1 /* SwiftPopMenu.app */, 74 | FA12F7971DF18166002F5FE1 /* SwiftPopMenuUITests.xctest */, 75 | ); 76 | name = Products; 77 | sourceTree = ""; 78 | }; 79 | FA12F7851DF18166002F5FE1 /* SwiftPopMenu */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | FA12F7A81DF27AC3002F5FE1 /* SwiftPopMenuSrc */, 83 | FA12F7861DF18166002F5FE1 /* AppDelegate.swift */, 84 | FA12F7881DF18166002F5FE1 /* ViewController.swift */, 85 | FA12F78A1DF18166002F5FE1 /* Main.storyboard */, 86 | FA12F78D1DF18166002F5FE1 /* Assets.xcassets */, 87 | FA12F78F1DF18166002F5FE1 /* LaunchScreen.storyboard */, 88 | FA12F7921DF18166002F5FE1 /* Info.plist */, 89 | ); 90 | path = SwiftPopMenu; 91 | sourceTree = ""; 92 | }; 93 | FA12F79A1DF18166002F5FE1 /* SwiftPopMenuUITests */ = { 94 | isa = PBXGroup; 95 | children = ( 96 | FA12F79B1DF18166002F5FE1 /* SwiftPopMenuUITests.swift */, 97 | FA12F79D1DF18166002F5FE1 /* Info.plist */, 98 | ); 99 | path = SwiftPopMenuUITests; 100 | sourceTree = ""; 101 | }; 102 | FA12F7A81DF27AC3002F5FE1 /* SwiftPopMenuSrc */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | FA12F7A91DF27AC3002F5FE1 /* SwiftPopMenu.swift */, 106 | ); 107 | path = SwiftPopMenuSrc; 108 | sourceTree = ""; 109 | }; 110 | /* End PBXGroup section */ 111 | 112 | /* Begin PBXNativeTarget section */ 113 | FA12F7821DF18166002F5FE1 /* SwiftPopMenu */ = { 114 | isa = PBXNativeTarget; 115 | buildConfigurationList = FA12F7A01DF18166002F5FE1 /* Build configuration list for PBXNativeTarget "SwiftPopMenu" */; 116 | buildPhases = ( 117 | FA12F77F1DF18166002F5FE1 /* Sources */, 118 | FA12F7801DF18166002F5FE1 /* Frameworks */, 119 | FA12F7811DF18166002F5FE1 /* Resources */, 120 | ); 121 | buildRules = ( 122 | ); 123 | dependencies = ( 124 | ); 125 | name = SwiftPopMenu; 126 | productName = SwiftPopMenu; 127 | productReference = FA12F7831DF18166002F5FE1 /* SwiftPopMenu.app */; 128 | productType = "com.apple.product-type.application"; 129 | }; 130 | FA12F7961DF18166002F5FE1 /* SwiftPopMenuUITests */ = { 131 | isa = PBXNativeTarget; 132 | buildConfigurationList = FA12F7A31DF18166002F5FE1 /* Build configuration list for PBXNativeTarget "SwiftPopMenuUITests" */; 133 | buildPhases = ( 134 | FA12F7931DF18166002F5FE1 /* Sources */, 135 | FA12F7941DF18166002F5FE1 /* Frameworks */, 136 | FA12F7951DF18166002F5FE1 /* Resources */, 137 | ); 138 | buildRules = ( 139 | ); 140 | dependencies = ( 141 | FA12F7991DF18166002F5FE1 /* PBXTargetDependency */, 142 | ); 143 | name = SwiftPopMenuUITests; 144 | productName = SwiftPopMenuUITests; 145 | productReference = FA12F7971DF18166002F5FE1 /* SwiftPopMenuUITests.xctest */; 146 | productType = "com.apple.product-type.bundle.ui-testing"; 147 | }; 148 | /* End PBXNativeTarget section */ 149 | 150 | /* Begin PBXProject section */ 151 | FA12F77B1DF18166002F5FE1 /* Project object */ = { 152 | isa = PBXProject; 153 | attributes = { 154 | LastSwiftUpdateCheck = 0810; 155 | LastUpgradeCheck = 0810; 156 | ORGANIZATIONNAME = zyyj; 157 | TargetAttributes = { 158 | FA12F7821DF18166002F5FE1 = { 159 | CreatedOnToolsVersion = 8.1; 160 | ProvisioningStyle = Automatic; 161 | }; 162 | FA12F7961DF18166002F5FE1 = { 163 | CreatedOnToolsVersion = 8.1; 164 | ProvisioningStyle = Automatic; 165 | TestTargetID = FA12F7821DF18166002F5FE1; 166 | }; 167 | }; 168 | }; 169 | buildConfigurationList = FA12F77E1DF18166002F5FE1 /* Build configuration list for PBXProject "SwiftPopMenu" */; 170 | compatibilityVersion = "Xcode 3.2"; 171 | developmentRegion = English; 172 | hasScannedForEncodings = 0; 173 | knownRegions = ( 174 | English, 175 | en, 176 | Base, 177 | ); 178 | mainGroup = FA12F77A1DF18166002F5FE1; 179 | productRefGroup = FA12F7841DF18166002F5FE1 /* Products */; 180 | projectDirPath = ""; 181 | projectRoot = ""; 182 | targets = ( 183 | FA12F7821DF18166002F5FE1 /* SwiftPopMenu */, 184 | FA12F7961DF18166002F5FE1 /* SwiftPopMenuUITests */, 185 | ); 186 | }; 187 | /* End PBXProject section */ 188 | 189 | /* Begin PBXResourcesBuildPhase section */ 190 | FA12F7811DF18166002F5FE1 /* Resources */ = { 191 | isa = PBXResourcesBuildPhase; 192 | buildActionMask = 2147483647; 193 | files = ( 194 | FA12F7911DF18166002F5FE1 /* LaunchScreen.storyboard in Resources */, 195 | FA12F78E1DF18166002F5FE1 /* Assets.xcassets in Resources */, 196 | FA12F78C1DF18166002F5FE1 /* Main.storyboard in Resources */, 197 | ); 198 | runOnlyForDeploymentPostprocessing = 0; 199 | }; 200 | FA12F7951DF18166002F5FE1 /* Resources */ = { 201 | isa = PBXResourcesBuildPhase; 202 | buildActionMask = 2147483647; 203 | files = ( 204 | ); 205 | runOnlyForDeploymentPostprocessing = 0; 206 | }; 207 | /* End PBXResourcesBuildPhase section */ 208 | 209 | /* Begin PBXSourcesBuildPhase section */ 210 | FA12F77F1DF18166002F5FE1 /* Sources */ = { 211 | isa = PBXSourcesBuildPhase; 212 | buildActionMask = 2147483647; 213 | files = ( 214 | FA12F7891DF18166002F5FE1 /* ViewController.swift in Sources */, 215 | FA12F7AA1DF27AC3002F5FE1 /* SwiftPopMenu.swift in Sources */, 216 | FA12F7871DF18166002F5FE1 /* AppDelegate.swift in Sources */, 217 | ); 218 | runOnlyForDeploymentPostprocessing = 0; 219 | }; 220 | FA12F7931DF18166002F5FE1 /* Sources */ = { 221 | isa = PBXSourcesBuildPhase; 222 | buildActionMask = 2147483647; 223 | files = ( 224 | FA12F79C1DF18166002F5FE1 /* SwiftPopMenuUITests.swift in Sources */, 225 | ); 226 | runOnlyForDeploymentPostprocessing = 0; 227 | }; 228 | /* End PBXSourcesBuildPhase section */ 229 | 230 | /* Begin PBXTargetDependency section */ 231 | FA12F7991DF18166002F5FE1 /* PBXTargetDependency */ = { 232 | isa = PBXTargetDependency; 233 | target = FA12F7821DF18166002F5FE1 /* SwiftPopMenu */; 234 | targetProxy = FA12F7981DF18166002F5FE1 /* PBXContainerItemProxy */; 235 | }; 236 | /* End PBXTargetDependency section */ 237 | 238 | /* Begin PBXVariantGroup section */ 239 | FA12F78A1DF18166002F5FE1 /* Main.storyboard */ = { 240 | isa = PBXVariantGroup; 241 | children = ( 242 | FA12F78B1DF18166002F5FE1 /* Base */, 243 | ); 244 | name = Main.storyboard; 245 | sourceTree = ""; 246 | }; 247 | FA12F78F1DF18166002F5FE1 /* LaunchScreen.storyboard */ = { 248 | isa = PBXVariantGroup; 249 | children = ( 250 | FA12F7901DF18166002F5FE1 /* Base */, 251 | ); 252 | name = LaunchScreen.storyboard; 253 | sourceTree = ""; 254 | }; 255 | /* End PBXVariantGroup section */ 256 | 257 | /* Begin XCBuildConfiguration section */ 258 | FA12F79E1DF18166002F5FE1 /* Debug */ = { 259 | isa = XCBuildConfiguration; 260 | buildSettings = { 261 | ALWAYS_SEARCH_USER_PATHS = NO; 262 | CLANG_ANALYZER_NONNULL = YES; 263 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 264 | CLANG_CXX_LIBRARY = "libc++"; 265 | CLANG_ENABLE_MODULES = YES; 266 | CLANG_ENABLE_OBJC_ARC = YES; 267 | CLANG_WARN_BOOL_CONVERSION = YES; 268 | CLANG_WARN_CONSTANT_CONVERSION = YES; 269 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 270 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 271 | CLANG_WARN_EMPTY_BODY = YES; 272 | CLANG_WARN_ENUM_CONVERSION = YES; 273 | CLANG_WARN_INFINITE_RECURSION = YES; 274 | CLANG_WARN_INT_CONVERSION = YES; 275 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 276 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 277 | CLANG_WARN_UNREACHABLE_CODE = YES; 278 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 279 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 280 | COPY_PHASE_STRIP = NO; 281 | DEBUG_INFORMATION_FORMAT = dwarf; 282 | ENABLE_STRICT_OBJC_MSGSEND = YES; 283 | ENABLE_TESTABILITY = YES; 284 | GCC_C_LANGUAGE_STANDARD = gnu99; 285 | GCC_DYNAMIC_NO_PIC = NO; 286 | GCC_NO_COMMON_BLOCKS = YES; 287 | GCC_OPTIMIZATION_LEVEL = 0; 288 | GCC_PREPROCESSOR_DEFINITIONS = ( 289 | "DEBUG=1", 290 | "$(inherited)", 291 | ); 292 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 293 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 294 | GCC_WARN_UNDECLARED_SELECTOR = YES; 295 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 296 | GCC_WARN_UNUSED_FUNCTION = YES; 297 | GCC_WARN_UNUSED_VARIABLE = YES; 298 | IPHONEOS_DEPLOYMENT_TARGET = 10.1; 299 | MTL_ENABLE_DEBUG_INFO = YES; 300 | ONLY_ACTIVE_ARCH = YES; 301 | SDKROOT = iphoneos; 302 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 303 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 304 | SWIFT_VERSION = 5.0; 305 | }; 306 | name = Debug; 307 | }; 308 | FA12F79F1DF18166002F5FE1 /* Release */ = { 309 | isa = XCBuildConfiguration; 310 | buildSettings = { 311 | ALWAYS_SEARCH_USER_PATHS = NO; 312 | CLANG_ANALYZER_NONNULL = YES; 313 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 314 | CLANG_CXX_LIBRARY = "libc++"; 315 | CLANG_ENABLE_MODULES = YES; 316 | CLANG_ENABLE_OBJC_ARC = YES; 317 | CLANG_WARN_BOOL_CONVERSION = YES; 318 | CLANG_WARN_CONSTANT_CONVERSION = YES; 319 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 320 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 321 | CLANG_WARN_EMPTY_BODY = YES; 322 | CLANG_WARN_ENUM_CONVERSION = YES; 323 | CLANG_WARN_INFINITE_RECURSION = YES; 324 | CLANG_WARN_INT_CONVERSION = YES; 325 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 326 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 327 | CLANG_WARN_UNREACHABLE_CODE = YES; 328 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 329 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 330 | COPY_PHASE_STRIP = NO; 331 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 332 | ENABLE_NS_ASSERTIONS = NO; 333 | ENABLE_STRICT_OBJC_MSGSEND = YES; 334 | GCC_C_LANGUAGE_STANDARD = gnu99; 335 | GCC_NO_COMMON_BLOCKS = YES; 336 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 337 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 338 | GCC_WARN_UNDECLARED_SELECTOR = YES; 339 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 340 | GCC_WARN_UNUSED_FUNCTION = YES; 341 | GCC_WARN_UNUSED_VARIABLE = YES; 342 | IPHONEOS_DEPLOYMENT_TARGET = 10.1; 343 | MTL_ENABLE_DEBUG_INFO = NO; 344 | SDKROOT = iphoneos; 345 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 346 | SWIFT_VERSION = 5.0; 347 | VALIDATE_PRODUCT = YES; 348 | }; 349 | name = Release; 350 | }; 351 | FA12F7A11DF18166002F5FE1 /* Debug */ = { 352 | isa = XCBuildConfiguration; 353 | buildSettings = { 354 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 355 | INFOPLIST_FILE = SwiftPopMenu/Info.plist; 356 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 357 | PRODUCT_BUNDLE_IDENTIFIER = www.zyyj.com.cn.SwiftPopMenu; 358 | PRODUCT_NAME = "$(TARGET_NAME)"; 359 | SWIFT_VERSION = 5.0; 360 | }; 361 | name = Debug; 362 | }; 363 | FA12F7A21DF18166002F5FE1 /* Release */ = { 364 | isa = XCBuildConfiguration; 365 | buildSettings = { 366 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 367 | INFOPLIST_FILE = SwiftPopMenu/Info.plist; 368 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 369 | PRODUCT_BUNDLE_IDENTIFIER = www.zyyj.com.cn.SwiftPopMenu; 370 | PRODUCT_NAME = "$(TARGET_NAME)"; 371 | SWIFT_VERSION = 5.0; 372 | }; 373 | name = Release; 374 | }; 375 | FA12F7A41DF18166002F5FE1 /* Debug */ = { 376 | isa = XCBuildConfiguration; 377 | buildSettings = { 378 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 379 | INFOPLIST_FILE = SwiftPopMenuUITests/Info.plist; 380 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 381 | PRODUCT_BUNDLE_IDENTIFIER = www.zyyj.com.cn.SwiftPopMenuUITests; 382 | PRODUCT_NAME = "$(TARGET_NAME)"; 383 | SWIFT_VERSION = 5.0; 384 | TEST_TARGET_NAME = SwiftPopMenu; 385 | }; 386 | name = Debug; 387 | }; 388 | FA12F7A51DF18166002F5FE1 /* Release */ = { 389 | isa = XCBuildConfiguration; 390 | buildSettings = { 391 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 392 | INFOPLIST_FILE = SwiftPopMenuUITests/Info.plist; 393 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 394 | PRODUCT_BUNDLE_IDENTIFIER = www.zyyj.com.cn.SwiftPopMenuUITests; 395 | PRODUCT_NAME = "$(TARGET_NAME)"; 396 | SWIFT_VERSION = 5.0; 397 | TEST_TARGET_NAME = SwiftPopMenu; 398 | }; 399 | name = Release; 400 | }; 401 | /* End XCBuildConfiguration section */ 402 | 403 | /* Begin XCConfigurationList section */ 404 | FA12F77E1DF18166002F5FE1 /* Build configuration list for PBXProject "SwiftPopMenu" */ = { 405 | isa = XCConfigurationList; 406 | buildConfigurations = ( 407 | FA12F79E1DF18166002F5FE1 /* Debug */, 408 | FA12F79F1DF18166002F5FE1 /* Release */, 409 | ); 410 | defaultConfigurationIsVisible = 0; 411 | defaultConfigurationName = Release; 412 | }; 413 | FA12F7A01DF18166002F5FE1 /* Build configuration list for PBXNativeTarget "SwiftPopMenu" */ = { 414 | isa = XCConfigurationList; 415 | buildConfigurations = ( 416 | FA12F7A11DF18166002F5FE1 /* Debug */, 417 | FA12F7A21DF18166002F5FE1 /* Release */, 418 | ); 419 | defaultConfigurationIsVisible = 0; 420 | defaultConfigurationName = Release; 421 | }; 422 | FA12F7A31DF18166002F5FE1 /* Build configuration list for PBXNativeTarget "SwiftPopMenuUITests" */ = { 423 | isa = XCConfigurationList; 424 | buildConfigurations = ( 425 | FA12F7A41DF18166002F5FE1 /* Debug */, 426 | FA12F7A51DF18166002F5FE1 /* Release */, 427 | ); 428 | defaultConfigurationIsVisible = 0; 429 | defaultConfigurationName = Release; 430 | }; 431 | /* End XCConfigurationList section */ 432 | }; 433 | rootObject = FA12F77B1DF18166002F5FE1 /* Project object */; 434 | } 435 | -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenu.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenu.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenu.xcodeproj/project.xcworkspace/xcuserdata/MACBOOK.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TangledHusky/SwiftPopMenu/cba2bf540b52ee9c0cc13b6ea639cd102f1ebbf1/SwiftPopMenuDemo/SwiftPopMenu.xcodeproj/project.xcworkspace/xcuserdata/MACBOOK.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenu.xcodeproj/project.xcworkspace/xcuserdata/liyajun.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TangledHusky/SwiftPopMenu/cba2bf540b52ee9c0cc13b6ea639cd102f1ebbf1/SwiftPopMenuDemo/SwiftPopMenu.xcodeproj/project.xcworkspace/xcuserdata/liyajun.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenu.xcodeproj/xcuserdata/MACBOOK.xcuserdatad/xcschemes/SwiftPopMenu.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenu.xcodeproj/xcuserdata/MACBOOK.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SwiftPopMenu.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | FA12F7821DF18166002F5FE1 16 | 17 | primary 18 | 19 | 20 | FA12F7961DF18166002F5FE1 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenu.xcodeproj/xcuserdata/liyajun.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenu.xcodeproj/xcuserdata/liyajun.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SwiftPopMenu.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenu/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SwiftPopMenu 4 | // 5 | // Created by lyj on 2016/12/2. 6 | // Copyright © 2016年 zyyj. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenu/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | } 43 | ], 44 | "info" : { 45 | "version" : 1, 46 | "author" : "xcode" 47 | } 48 | } -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenu/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenu/Assets.xcassets/Shape.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Shape.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Shape@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Shape@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenu/Assets.xcassets/Shape.imageset/Shape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TangledHusky/SwiftPopMenu/cba2bf540b52ee9c0cc13b6ea639cd102f1ebbf1/SwiftPopMenuDemo/SwiftPopMenu/Assets.xcassets/Shape.imageset/Shape.png -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenu/Assets.xcassets/Shape.imageset/Shape@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TangledHusky/SwiftPopMenu/cba2bf540b52ee9c0cc13b6ea639cd102f1ebbf1/SwiftPopMenuDemo/SwiftPopMenu/Assets.xcassets/Shape.imageset/Shape@2x.png -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenu/Assets.xcassets/Shape.imageset/Shape@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TangledHusky/SwiftPopMenu/cba2bf540b52ee9c0cc13b6ea639cd102f1ebbf1/SwiftPopMenuDemo/SwiftPopMenu/Assets.xcassets/Shape.imageset/Shape@3x.png -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenu/Assets.xcassets/SignRule.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "SignRule.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "SignRule@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "SignRule@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenu/Assets.xcassets/SignRule.imageset/SignRule.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TangledHusky/SwiftPopMenu/cba2bf540b52ee9c0cc13b6ea639cd102f1ebbf1/SwiftPopMenuDemo/SwiftPopMenu/Assets.xcassets/SignRule.imageset/SignRule.png -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenu/Assets.xcassets/SignRule.imageset/SignRule@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TangledHusky/SwiftPopMenu/cba2bf540b52ee9c0cc13b6ea639cd102f1ebbf1/SwiftPopMenuDemo/SwiftPopMenu/Assets.xcassets/SignRule.imageset/SignRule@2x.png -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenu/Assets.xcassets/SignRule.imageset/SignRule@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TangledHusky/SwiftPopMenu/cba2bf540b52ee9c0cc13b6ea639cd102f1ebbf1/SwiftPopMenuDemo/SwiftPopMenu/Assets.xcassets/SignRule.imageset/SignRule@3x.png -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenu/Assets.xcassets/saoyisao.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "saoyisao.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "saoyisao@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "saoyisao@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenu/Assets.xcassets/saoyisao.imageset/saoyisao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TangledHusky/SwiftPopMenu/cba2bf540b52ee9c0cc13b6ea639cd102f1ebbf1/SwiftPopMenuDemo/SwiftPopMenu/Assets.xcassets/saoyisao.imageset/saoyisao.png -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenu/Assets.xcassets/saoyisao.imageset/saoyisao@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TangledHusky/SwiftPopMenu/cba2bf540b52ee9c0cc13b6ea639cd102f1ebbf1/SwiftPopMenuDemo/SwiftPopMenu/Assets.xcassets/saoyisao.imageset/saoyisao@2x.png -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenu/Assets.xcassets/saoyisao.imageset/saoyisao@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TangledHusky/SwiftPopMenu/cba2bf540b52ee9c0cc13b6ea639cd102f1ebbf1/SwiftPopMenuDemo/SwiftPopMenu/Assets.xcassets/saoyisao.imageset/saoyisao@3x.png -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenu/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenu/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenu/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenu/SwiftPopMenuSrc/SwiftPopMenu.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PopView.swift 3 | // TestSwift 4 | // 5 | // Created by lyj on 16/5/7. 6 | // Copyright © 2016年 zyyj. All rights reserved. 7 | /* 8 | GitHub:https://github.com/TangledHusky/SwiftPopMenu 9 | 10 | 功能: 11 | 只需要传入菜单箭头点位置、菜单宽度、数据源即可。 12 | 13 | 1、支持任意点弹出(点是基于整个屏幕位置) 14 | 2、会根据点位置自动计算菜单位置 15 | 3、背景色、文字等支持自定义设置 16 | 4、菜单最大宽度=屏幕-边距 最大高度=屏幕高度一半 17 | */ 18 | 19 | import UIKit 20 | 21 | protocol SwiftPopMenuDelegate :NSObjectProtocol{ 22 | func swiftPopMenuDidSelectIndex(index:Int) 23 | } 24 | 25 | 26 | public enum SwiftPopMenuConfigure { 27 | case PopMenuTextFont(UIFont) //菜单文字字体 28 | case PopMenuTextColor(UIColor) //菜单文字颜色 29 | case PopMenuBackgroudColor(UIColor) //菜单背景色 30 | case popMenuCornorRadius(CGFloat) //菜单圆角 31 | case popMenuItemHeight(CGFloat) //菜单行高度 32 | case popMenuSplitLineColor(UIColor) //菜单分割线颜色 33 | case popMenuIconLeftMargin(CGFloat) //icon左间距 34 | case popMenuMargin(CGFloat) //菜单与屏幕边距 35 | case popMenuAlpha(CGFloat) //菜单背景透明度 36 | } 37 | 38 | public class SwiftPopMenu: UIView { 39 | 40 | //delegate 41 | weak var delegate : SwiftPopMenuDelegate? 42 | //block 43 | public var didSelectMenuBlock:((_ index:Int)->Void)? 44 | 45 | let KScrW:CGFloat = UIScreen.main.bounds.size.width 46 | let KScrH:CGFloat = UIScreen.main.bounds.size.height 47 | 48 | 49 | 50 | ///* ----------------------- 外部参数 通过configure设置 ---------------------------- */ 51 | //区域外背景透明度 52 | private var popMenuOutAlpha:CGFloat = 0.3 53 | //背景色 54 | private var popMenuBgColor:UIColor = UIColor.white 55 | //圆角弧度 56 | private var popMenuCornorRadius:CGFloat = 6 57 | //文字颜色 58 | private var popMenuTextColor:UIColor = UIColor.black 59 | //字体大小等 60 | private var popMenuTextFont:UIFont = UIFont.systemFont(ofSize: 17) 61 | //菜单高度 62 | private var popMenuItemHeight:CGFloat = 44.0 63 | //菜单分割线颜色 64 | private var popMenuSplitLineColor:UIColor = UIColor(red: 222/255.0, green: 222/255.0, blue: 222/255.0, alpha: 0.5) 65 | //icon左间距 66 | private var popMenuIconLeftMargin:CGFloat = 15 67 | //菜单与屏幕边距 68 | private var popMenuMargin:CGFloat = 10 69 | 70 | ///* ----------------------- 外部参数 over------------------------------------------ */ 71 | 72 | private var arrowPoint : CGPoint = CGPoint.zero //小箭头位置 73 | private var arrowViewWidth : CGFloat = 15 //三角箭头宽 74 | private var arrowViewHeight : CGFloat = 10 //三角箭头高 75 | private var popData:[(icon:String,title:String)]! //数据源 76 | 77 | static let cellID:String = "SwiftPopMenuCellID" 78 | private var myFrame:CGRect! //tableview frame 79 | private var arrowView : UIView! = nil 80 | 81 | var tableView:UITableView! = nil 82 | 83 | 84 | 85 | /// 初始化菜单 86 | /// 87 | /// - Parameters: 88 | /// - menuWidth: 菜单宽度 89 | /// - arrow: 箭头位置是popmenu相对整个屏幕的位置 90 | /// - datas: 数据源,icon允许传空,数据源没数据,不会显示菜单 91 | /// - configure: 配置信息,可不传 92 | init(menuWidth:CGFloat,arrow:CGPoint,datas:[(icon:String,title:String)],configures:[SwiftPopMenuConfigure] = []) { 93 | super.init(frame: UIScreen.main.bounds) 94 | self.frame = UIScreen.main.bounds 95 | //读取配置 96 | configures.forEach { (config) in 97 | switch (config){ 98 | case let .PopMenuTextFont(value): 99 | popMenuTextFont = value 100 | case let .PopMenuTextColor(value): 101 | popMenuTextColor = value 102 | case let .PopMenuBackgroudColor(value): 103 | popMenuBgColor = value 104 | case let .popMenuCornorRadius(value): 105 | popMenuCornorRadius = value 106 | case let .popMenuItemHeight(value): 107 | popMenuItemHeight = value 108 | case let .popMenuSplitLineColor(value): 109 | popMenuSplitLineColor = value 110 | case let .popMenuIconLeftMargin(value): 111 | popMenuIconLeftMargin = value 112 | case let .popMenuMargin(value): 113 | popMenuMargin = value 114 | case let .popMenuAlpha(value): 115 | popMenuOutAlpha = value 116 | } 117 | } 118 | 119 | popData = datas 120 | //设置myFrame size ,original会在后面计算 121 | myFrame = CGRect(x: 0, y: 0, width: menuWidth, height: popMenuItemHeight*CGFloat(popData.count)) 122 | myFrame.size.height = min(KScrH/2, myFrame.height) 123 | myFrame.size.width = min(KScrW-popMenuMargin*2, myFrame.width) 124 | 125 | //设置肩头,与屏幕间隔10 126 | arrowPoint = arrow 127 | arrowPoint.x = max(popMenuMargin, min(arrowPoint.x, KScrW-popMenuMargin)) 128 | 129 | } 130 | 131 | required public init?(coder aDecoder: NSCoder) { 132 | fatalError("init(coder:) has not been implemented") 133 | } 134 | 135 | 136 | 137 | func initViews() { 138 | self.backgroundColor = UIColor.black.withAlphaComponent(popMenuOutAlpha) 139 | 140 | let arrowPs = getArrowPoints() 141 | myFrame.origin = arrowPs.3 142 | let isarrowUP = arrowPs.4 143 | print(arrowPs) 144 | //箭头 145 | arrowView=UIView(frame: CGRect(x: myFrame.origin.x, y: isarrowUP ? myFrame.origin.y-arrowViewHeight : myFrame.origin.y+myFrame.height, width: myFrame.width, height: arrowViewHeight)) 146 | let layer=CAShapeLayer() 147 | let path=UIBezierPath() 148 | path.move(to: arrowPs.0) 149 | path.addLine(to: arrowPs.1) 150 | path.addLine(to: arrowPs.2) 151 | layer.path=path.cgPath 152 | layer.fillColor = popMenuBgColor.cgColor 153 | arrowView.layer.addSublayer(layer) 154 | self.addSubview(arrowView) 155 | 156 | tableView=UITableView(frame: CGRect(x: myFrame.origin.x,y: myFrame.origin.y,width: myFrame.width,height: myFrame.height), style: .plain) 157 | tableView.register(SwiftPopMenuCell.classForCoder(), forCellReuseIdentifier: SwiftPopMenu.cellID) 158 | tableView.backgroundColor = popMenuBgColor 159 | tableView.layer.cornerRadius = popMenuCornorRadius 160 | tableView.separatorStyle = .none 161 | tableView.layer.masksToBounds = true 162 | tableView.delegate = self 163 | tableView.dataSource = self 164 | tableView.bounces = false 165 | UIView.animate(withDuration: 0.3) { 166 | self.addSubview(self.tableView) 167 | } 168 | } 169 | 170 | 171 | /// 计算箭头位置 172 | /// 173 | /// - Returns: (三角箭头顶,三角箭头左,三角箭头右,tableview 原点,是否箭头朝上) 174 | func getArrowPoints() -> (CGPoint,CGPoint,CGPoint,CGPoint,Bool) { 175 | if arrowPoint.x <= popMenuMargin { 176 | arrowPoint.x = popMenuMargin 177 | } 178 | if arrowPoint.x >= KScrW - popMenuMargin{ 179 | arrowPoint.x = KScrW - popMenuMargin 180 | } 181 | var originalPoint = CGPoint.zero 182 | 183 | //箭头中间距离左边距离 184 | var arrowMargin:CGFloat = popMenuMargin 185 | if arrowPoint.x < KScrW/2{ 186 | if (arrowPoint.x > myFrame.width/2) { 187 | arrowMargin = myFrame.width/2 188 | originalPoint = CGPoint(x: arrowPoint.x - myFrame.width/2, y: arrowPoint.y+arrowViewHeight) 189 | }else{ 190 | arrowMargin = arrowPoint.x-popMenuMargin 191 | originalPoint = CGPoint(x: popMenuMargin, y: arrowPoint.y+arrowViewHeight) 192 | } 193 | 194 | }else{ 195 | 196 | if (KScrW-arrowPoint.x) < myFrame.width/2{ 197 | arrowMargin = (myFrame.width - KScrW + arrowPoint.x ) 198 | originalPoint = CGPoint(x: KScrW-popMenuMargin-myFrame.width, y: arrowPoint.y+arrowViewHeight) 199 | 200 | 201 | }else{ 202 | arrowMargin = myFrame.width/2 203 | originalPoint = CGPoint(x: arrowPoint.x-myFrame.width/2, y: arrowPoint.y+arrowViewHeight) 204 | } 205 | } 206 | 207 | //箭头朝上 208 | if (KScrH - arrowPoint.y) > myFrame.height{ 209 | 210 | return (CGPoint(x: arrowMargin, y: 0),CGPoint(x: arrowMargin-arrowViewWidth/2, y: arrowViewHeight),CGPoint(x: arrowMargin+arrowViewWidth/2, y: arrowViewHeight),originalPoint,true) 211 | 212 | }else{ 213 | originalPoint.y = arrowPoint.y-myFrame.height-arrowViewHeight 214 | 215 | return (CGPoint(x: arrowMargin, y: arrowViewHeight),CGPoint(x: arrowMargin-arrowViewWidth/2, y: 0),CGPoint(x: arrowMargin+arrowViewWidth/2, y: 0),originalPoint,false) 216 | } 217 | 218 | } 219 | 220 | } 221 | 222 | 223 | 224 | // MARK: - 页面显示、隐藏 225 | extension SwiftPopMenu{ 226 | 227 | override public func touchesBegan(_ touches: Set, with event: UIEvent?) { 228 | if touches.first?.view != tableView{ 229 | dismiss() 230 | } 231 | } 232 | 233 | public func show() { 234 | if popData.isEmpty{ 235 | return 236 | } 237 | initViews() 238 | UIApplication.shared.keyWindow?.addSubview(self) 239 | } 240 | 241 | public func dismiss() { 242 | self.removeFromSuperview() 243 | } 244 | 245 | } 246 | 247 | // MARK: - UITableViewDataSource,UITableViewDelegate 248 | extension SwiftPopMenu : UITableViewDataSource,UITableViewDelegate{ 249 | 250 | public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 251 | return popData.count 252 | } 253 | 254 | public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 255 | if popData.count>indexPath.row { 256 | let cell = tableView.dequeueReusableCell(withIdentifier: SwiftPopMenu.cellID) as! SwiftPopMenuCell 257 | 258 | let model = popData[indexPath.row] 259 | cell.setConfig(_txtColor: popMenuTextColor, _lineColor: popMenuSplitLineColor, _txtFont: popMenuTextFont, _iconLeft: popMenuIconLeftMargin) 260 | if indexPath.row == popData.count - 1 { 261 | cell.fill(iconName: model.icon, title: model.title, islast: true) 262 | }else{ 263 | cell.fill(iconName: model.icon, title: model.title) 264 | } 265 | return cell 266 | } 267 | 268 | return UITableViewCell() 269 | } 270 | 271 | public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 272 | return popMenuItemHeight 273 | } 274 | 275 | public func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { 276 | return 0.01 277 | } 278 | 279 | public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 280 | if self.delegate != nil{ 281 | self.delegate?.swiftPopMenuDidSelectIndex(index: indexPath.row) 282 | } 283 | if didSelectMenuBlock != nil { 284 | didSelectMenuBlock!(indexPath.row) 285 | } 286 | 287 | dismiss() 288 | } 289 | 290 | } 291 | 292 | 293 | 294 | /// UITableViewCell 295 | class SwiftPopMenuCell: UITableViewCell { 296 | var iconImage:UIImageView! 297 | var lblTitle:UILabel! 298 | var line:UIView! 299 | 300 | //自定义属性 301 | var lineColor:UIColor = UIColor(red: 222/255.0, green: 222/255.0, blue: 222/255.0, alpha: 0.5) 302 | var txtColor:UIColor = UIColor.black 303 | var txtFont:UIFont = UIFont.systemFont(ofSize: 17) 304 | var iconLeft:CGFloat = 15 305 | 306 | 307 | override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { 308 | super.init(style: style, reuseIdentifier: reuseIdentifier) 309 | self.backgroundColor = UIColor.clear 310 | 311 | iconImage = UIImageView() 312 | self.contentView.addSubview(iconImage) 313 | self.selectionStyle = .none 314 | 315 | lblTitle = UILabel() 316 | self.contentView.addSubview(lblTitle) 317 | 318 | line = UIView() 319 | self.contentView.addSubview(line) 320 | } 321 | 322 | 323 | required init?(coder aDecoder: NSCoder) { 324 | fatalError("init(coder:) has not been implemented") 325 | } 326 | 327 | 328 | func fill(iconName:String,title:String,islast:Bool = false) { 329 | iconImage.image = UIImage(named: iconName) 330 | lblTitle.text = title 331 | line.isHidden = islast 332 | } 333 | 334 | func setConfig(_txtColor:UIColor,_lineColor:UIColor,_txtFont:UIFont,_iconLeft:CGFloat) { 335 | txtColor = _txtColor 336 | txtFont = _txtFont 337 | lineColor = _lineColor 338 | iconLeft = _iconLeft 339 | 340 | line.backgroundColor = lineColor 341 | lblTitle.textColor = txtColor 342 | lblTitle.font = txtFont 343 | } 344 | 345 | override func layoutSubviews() { 346 | super.layoutSubviews() 347 | self.iconImage.frame = CGRect(x: iconLeft, y: (self.bounds.size.height - 20)/2, width: 20, height: 20) 348 | self.lblTitle.frame = CGRect(x: 20+iconLeft*2, y: 0, width: self.bounds.size.width - 40, height: self.bounds.size.height) 349 | self.line.frame = CGRect(x: 0, y: self.frame.size.height - 1, width: self.frame.size.width, height: 1) 350 | 351 | } 352 | 353 | 354 | } 355 | -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenu/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // SwiftPopMenu 4 | // 5 | // Created by lyj on 2016/12/2. 6 | // Copyright © 2016年 zyyj. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | var popMenu:SwiftPopMenu! 14 | 15 | let KSCREEN_WIDTH:CGFloat = UIScreen.main.bounds.size.width 16 | let KSCREEN_HEIGHT:CGFloat = UIScreen.main.bounds.size.height 17 | 18 | lazy var btn:UIButton = { 19 | let btn = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 40)) 20 | btn.center = self.view.center 21 | btn.backgroundColor = UIColor.black 22 | btn.setTitle("点击测试", for: .normal) 23 | btn.addTarget(self, action: #selector(showMenu), for: .touchUpInside) 24 | return btn 25 | }() 26 | 27 | override func viewDidLoad() { 28 | super.viewDidLoad() 29 | view.addSubview(btn) 30 | self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "Shape"), style: .plain, target: self, action: #selector(self.showMenu)) 31 | } 32 | 33 | @objc func showMenu() { 34 | //数据源(icon可不填) 35 | let popData = [(icon:"saoyisao",title:"扫一扫"), 36 | (icon:"SignRule",title:"签到规则"), 37 | (icon:"saoyisao",title:"扫一扫"), 38 | (icon:"SignRule",title:"签到规则")] 39 | 40 | //设置参数 41 | let parameters:[SwiftPopMenuConfigure] = [ 42 | .PopMenuTextColor(UIColor.black), 43 | .popMenuItemHeight(44), 44 | .PopMenuTextFont(UIFont.systemFont(ofSize: 18)) 45 | ] 46 | 47 | 48 | //init (test随机生成点位置,注意:arrow点是基于屏幕的位置) 49 | popMenu = SwiftPopMenu(menuWidth: 150, arrow: CGPoint(x: btn.center.x, y: btn.center.y+30), datas: popData,configures: parameters) 50 | 51 | //click 52 | popMenu.didSelectMenuBlock = { [weak self](index:Int)->Void in 53 | print("block select \(index)") 54 | self?.popMenu = nil 55 | } 56 | //show 57 | popMenu.show() 58 | 59 | } 60 | 61 | 62 | } 63 | -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenuUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /SwiftPopMenuDemo/SwiftPopMenuUITests/SwiftPopMenuUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftPopMenuUITests.swift 3 | // SwiftPopMenuUITests 4 | // 5 | // Created by 李亚军 on 2016/12/2. 6 | // Copyright © 2016年 zyyj. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class SwiftPopMenuUITests: XCTestCase { 12 | 13 | override func setUp() { 14 | super.setUp() 15 | 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | 18 | // In UI tests it is usually best to stop immediately when a failure occurs. 19 | continueAfterFailure = false 20 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 21 | XCUIApplication().launch() 22 | 23 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 24 | } 25 | 26 | override func tearDown() { 27 | // Put teardown code here. This method is called after the invocation of each test method in the class. 28 | super.tearDown() 29 | } 30 | 31 | func testExample() { 32 | // Use recording to get started writing UI tests. 33 | // Use XCTAssert and related functions to verify your tests produce the correct results. 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /img1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TangledHusky/SwiftPopMenu/cba2bf540b52ee9c0cc13b6ea639cd102f1ebbf1/img1.png -------------------------------------------------------------------------------- /img2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TangledHusky/SwiftPopMenu/cba2bf540b52ee9c0cc13b6ea639cd102f1ebbf1/img2.png -------------------------------------------------------------------------------- /img3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TangledHusky/SwiftPopMenu/cba2bf540b52ee9c0cc13b6ea639cd102f1ebbf1/img3.png -------------------------------------------------------------------------------- /swiftPopMenu.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TangledHusky/SwiftPopMenu/cba2bf540b52ee9c0cc13b6ea639cd102f1ebbf1/swiftPopMenu.gif --------------------------------------------------------------------------------