AZPopMenu.swift 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. //
  2. // AZPopMenu.swift
  3. //
  4. // Created by Aaron Zhu on 15/6/4.
  5. // Copyright (c) 2015年 Aaron Zhu All rights reserved.
  6. /******************************************
  7. *作用:
  8. 创建一个pop菜单。
  9. *使用方法:
  10. AZPopMenu.show
  11. *方法声明:
  12. class func show(superView:UIView, startPoint: CGPoint, items: [String], colors: [UIColor], selected: (itemSelected: Int) -> Void)
  13. *方法参数:
  14. superView: 父View,请使用ViewController.view,方便计算坐标
  15. startPoint: pop菜单上方的箭头位置,使用superView的坐标
  16. items: 要显示的菜单项
  17. colors: 菜单项前显示的色块
  18. selected: 选中菜单项后调用的闭包
  19. ******************************************/
  20. import UIKit
  21. import CoreGraphics
  22. let AZ_SELL_WIDTH : CGFloat = 120 //Cell宽度
  23. let AZ_SELL_HEIGHT: CGFloat = 40 //Cell高度
  24. let AZ_ARROW_WIDTH: CGFloat = 10 //Table上方箭头的宽度
  25. let AZ_ARROW_HEIGHT: CGFloat = 10 //Table上方箭头的高度
  26. let AZ_ARROW_FROM_EDGE: CGFloat = 35 //Table上方箭头距离Table边界的最小距离
  27. let AZ_TABLE_WIDTH = AZ_SELL_WIDTH //Table的宽度(同Cell宽度)
  28. let AZ_TABLE_FROM_EDGE: CGFloat = 10 //Table距离手机边界的最小距离
  29. let AZ_SCREEN_WIDTH = UIScreen.main.bounds.size.width
  30. let AZ_SCREEN_HEIGHT = UIScreen.main.bounds.size.height
  31. class SelectCell : UITableViewCell{
  32. var colorView :UIView!
  33. var nameLabel :UILabel!
  34. func setUpItem(_ item: String, withColor: UIColor){
  35. //构造cell上的内容
  36. colorView = UIView(frame: CGRect(x: 18,y: 13,width: 14,height: 14))
  37. colorView.layer.cornerRadius = 2
  38. colorView.layer.masksToBounds = true
  39. self.addSubview(colorView)
  40. nameLabel = UILabel(frame: CGRect(x: 42, y: 15, width: 100, height: 10))
  41. nameLabel.backgroundColor = UIColor.clear
  42. nameLabel.textColor = UIColor(red:192/255, green: 193/255, blue: 195/255, alpha: 1.0)
  43. self.addSubview(nameLabel)
  44. self.backgroundColor = UIColor(red: 57/255, green: 60/255, blue: 66/255, alpha: 1.0)
  45. nameLabel.text = item
  46. colorView.backgroundColor = withColor
  47. }
  48. }
  49. class ArrowView: UIView{
  50. var arrowPoint: CGPoint
  51. init(frame: CGRect, arrowPoint: CGPoint) {
  52. //转换箭头的坐标 相对super坐标 -> 本view坐标
  53. self.arrowPoint = arrowPoint
  54. self.arrowPoint.y = 0
  55. self.arrowPoint.x = arrowPoint.x - frame.origin.x
  56. super.init(frame: frame)
  57. }
  58. required init(coder aDecoder: NSCoder) {
  59. fatalError("init(coder:) has not been implemented")
  60. }
  61. //画顶部的三角形
  62. override func draw(_ rect: CGRect) {
  63. super.draw(rect)
  64. let context = UIGraphicsGetCurrentContext()
  65. context!.setFillColor(red: 57/255, green: 60/255, blue: 66/255, alpha: 1.0) //设置填充颜色
  66. let sPoints: [CGPoint] = [arrowPoint,
  67. CGPoint(x: arrowPoint.x-AZ_ARROW_WIDTH/2, y: arrowPoint.y+AZ_ARROW_HEIGHT),
  68. CGPoint(x: arrowPoint.x+AZ_ARROW_WIDTH/2, y: arrowPoint.y+AZ_ARROW_HEIGHT)]
  69. context?.addLines(between: sPoints)
  70. //CGContextAddLines(context!, sPoints, 3)
  71. context!.closePath()
  72. context!.drawPath(using: .fillStroke)
  73. }
  74. }
  75. class AZPopMenu: UIView,UITableViewDelegate,UITableViewDataSource,UIGestureRecognizerDelegate{
  76. var superView: UIView! //父View,使用ViewController.view,方便计算坐标。
  77. var startPoint: CGPoint = CGPoint(x: 0,y: 0) //箭头位置
  78. var items: [String] = [] //cell中使用字符串
  79. var colors: [UIColor] = [] //cell中使用颜色框
  80. var selected: ((_ itemSelected: Int) -> Void)? //点击选项后调用的闭包
  81. //第一层,self, 全屏透明view,用于接收tabGuesture手势来关闭自己。
  82. var popViewArrow: ArrowView! //第二层,小View,用来画三角箭头
  83. var popTable: UITableView! //第三层,TableView,显示内容和接收点击事件
  84. var tabGuesture: UITapGestureRecognizer!
  85. class func show(_ superView:UIView, startPoint: CGPoint, items: [String], colors: [UIColor], selected: @escaping (_ itemSelected: Int) -> Void){
  86. let p = AZPopMenu()
  87. p.showPopMenu(superView, startPoint: startPoint, items: items, colors: colors, selected: selected)
  88. }
  89. init(){
  90. super.init(frame: CGRect(x: 0, y: 0, width: AZ_SCREEN_WIDTH, height: AZ_SCREEN_HEIGHT))
  91. self.backgroundColor = UIColor(white: 0.0, alpha: 0.2)
  92. }
  93. required init(coder aDecoder: NSCoder) {
  94. fatalError("init(coder:) has not been implemented")
  95. }
  96. func showPopMenu (_ superView:UIView, startPoint: CGPoint, items: [String], colors: [UIColor], selected: @escaping (_ itemSelected: Int) -> Void) {
  97. if items.isEmpty {
  98. print("error: items为空。函数结束。")
  99. return
  100. }
  101. if items.count != colors.count {
  102. print("error: items和colors项目数量不同。函数结束。")
  103. return
  104. }
  105. self.superView = superView
  106. self.startPoint = startPoint
  107. self.items = items
  108. self.colors = colors
  109. self.selected = selected
  110. //调整箭头位置, 距离屏幕两边35个点以上
  111. if self.startPoint.x < AZ_ARROW_FROM_EDGE {
  112. self.startPoint.x = AZ_ARROW_FROM_EDGE
  113. }else if self.startPoint.x > (AZ_SCREEN_WIDTH-AZ_ARROW_FROM_EDGE){
  114. self.startPoint.x = AZ_SCREEN_WIDTH-AZ_ARROW_FROM_EDGE
  115. }
  116. //调整popmenu的frame 默认箭头置中, table距离屏幕两边10个点以上。
  117. let width = AZ_TABLE_WIDTH
  118. let height = AZ_ARROW_HEIGHT + AZ_SELL_HEIGHT * CGFloat(items.count) - 1.0 //隐藏掉最后一个像素的白线
  119. var tableX = self.startPoint.x - AZ_SELL_WIDTH/2
  120. if tableX < AZ_TABLE_FROM_EDGE {
  121. tableX = AZ_TABLE_FROM_EDGE
  122. }else if tableX > (AZ_SCREEN_WIDTH-AZ_SELL_WIDTH-AZ_TABLE_FROM_EDGE){
  123. tableX = AZ_SCREEN_WIDTH-AZ_SELL_WIDTH-AZ_TABLE_FROM_EDGE
  124. }
  125. popViewArrow = ArrowView(frame: CGRect(x: tableX, y: startPoint.y, width: width, height: height), arrowPoint: self.startPoint)
  126. popViewArrow.backgroundColor = UIColor.clear
  127. //popViewArrow.backgroundColor = UIColor(red: 0.2, green: 0.2, blue: 0.2, alpha: 0.3)
  128. //放置table
  129. popTable = UITableView(frame: CGRect(x: 0, y: AZ_ARROW_HEIGHT, width: width, height: height-AZ_ARROW_HEIGHT), style: UITableView.Style.plain)
  130. popTable.delegate = self
  131. popTable.dataSource = self
  132. popTable.layer.cornerRadius = 5
  133. popTable.layer.masksToBounds = true
  134. popTable.isScrollEnabled = false //禁止滚动
  135. popTable.separatorStyle = UITableViewCell.SeparatorStyle.none //去掉cell分割线
  136. popViewArrow.addSubview(popTable)
  137. self.addSubview(popViewArrow)
  138. superView.addSubview(self)
  139. //UITapGestureRecognizer! 用于关闭popmenu
  140. tabGuesture = UITapGestureRecognizer(target: self, action: #selector(AZPopMenu.tabAction(_:)))
  141. tabGuesture.numberOfTapsRequired = 1
  142. tabGuesture.delegate = self
  143. self.addGestureRecognizer(tabGuesture)
  144. //动画打开效果
  145. animationShowPopMenu()
  146. }
  147. func animationShowPopMenu(){
  148. //改变popTable
  149. var done = false
  150. //popTable.alpha = 0.0
  151. let toRect = popTable.frame
  152. popTable.frame = CGRect(x: startPoint.x-popViewArrow.frame.origin.x, y: 0, width: 1, height: 1)
  153. UIView.animate(withDuration: 0.2, animations: { () -> Void in
  154. self.popTable.frame = toRect
  155. //self.popTable.alpha = 1.0
  156. }, completion: { (b: Bool) -> Void in
  157. done = true
  158. })
  159. while !done{
  160. RunLoop.current.run(until: Date(timeIntervalSinceNow: 0.01))
  161. }
  162. }
  163. @objc func tabAction(_ sender: UITapGestureRecognizer){
  164. //关闭本身
  165. self.removeGestureRecognizer(tabGuesture)
  166. self.removeFromSuperview()
  167. self.selected?(-1)
  168. }
  169. //UITableViewDelegate/UITableViewDataSource
  170. func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
  171. return 0.0
  172. }
  173. func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
  174. return 0.0
  175. }
  176. func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
  177. return AZ_SELL_HEIGHT
  178. }
  179. func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  180. return items.count
  181. }
  182. func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) ->UITableViewCell{
  183. let cell = SelectCell(style: UITableViewCell.CellStyle.default, reuseIdentifier: "Cell")
  184. //cell.setUpView(indexPath.row)
  185. cell.setUpItem(items[(indexPath as NSIndexPath).row], withColor: colors[(indexPath as NSIndexPath).row])
  186. return cell;
  187. }
  188. func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
  189. tableView.deselectRow(at: indexPath, animated: true)
  190. //关闭本身
  191. self.removeGestureRecognizer(tabGuesture)
  192. self.removeFromSuperview()
  193. self.selected?((indexPath as NSIndexPath).row)
  194. }
  195. //UIGestureRecognizerDelegate 用于过滤tableview
  196. func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool{
  197. if touch.view is AZPopMenu {
  198. return true
  199. }else{
  200. return false
  201. }
  202. }
  203. }