最近项目要实现这么一个有趣味性的功能,网上找了一个Demo是OC实现的,自己项目是Swift的,下面是自己的参考实现。
实现效果如下:
image.png image.png暂时只是做了一个Demo,点击屏幕加外围的圈。
代码如下:
Roundview:
import UIKit
enum RoundviewType: Int {
case RoundviewTypeSystem = 0
case RoundviewTypeCustom = 1
}
typealias JumpBlock = ((String, String ) -> Void)
class Roundview: UIView {
var block: JumpBlock?
var type: RoundviewType = .RoundviewTypeSystem
var viewWidth: CGFloat?
var btnArray: [UIButton]!
var btnArray2: [UIButton]!
var rotationAngleInRadians: CGFloat = 0.0
var isShow: Bool = false
var nameArray: [String]?
var outSideArray: [String]?
var titlesArray: [String]?
var imageArray: [String]?
var buttonWidth: CGFloat = 0.0
var buttonConrenrRadius: CGFloat = 0.0
var cycleLineRadius: CGFloat = 0.0
var corner1: CFloat = 0.0
var corner2: CFloat = 0.0
var r1: CFloat = 0.0
var r2: CFloat = 0.0
var circleCenter: CGPoint!
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override init(frame: CGRect) {
super.init(frame: frame)
self.layer.masksToBounds = true
self.layer.cornerRadius = self.frame.width / 2.0
self.viewWidth = self.frame.width
btnArray = []
btnArray2 = []
nameArray = []
self.addGestureRecognizer(RotationGestureRecognizer(target: self, action: #selector(changeMove(rotation:))))
}
func configure(type: RoundviewType, btnWidth: CGFloat, adjustsFontSizesTowidth: Bool, masksToBounds: Bool, conrenrRadius: CGFloat, images: [String], titileArray: [String], titileColor: UIColor, cycleLineRadius: CGFloat) {
self.titlesArray = titileArray
self.imageArray = images
self.buttonWidth = btnWidth
self.cornerRadius = cornerRadius
self.cycleLineRadius = cycleLineRadius
self.type = type
let buttonWidth2 = buttonWidth / 2.0
self.corner1 = CFloat(CGFloat(M_PI * 2.0 / Double(titileArray.count)))
self.r1 = CFloat((self.viewWidth! - buttonWidth) / 2)
self.corner2 = self.corner1
self.r2 = CFloat(cycleLineRadius / 2.0)
nameArray = titileArray;
self.circleCenter = CGPoint(x: self.bounds.size.width/2.0, y: self.bounds.size.width/2.0)
// 内圈
for (i, _) in titileArray.enumerated() {
let btn = UIButton(type: .custom)
btn.frame = CGRect(x: 0, y: 0, width: btnWidth, height: btnWidth)
btn.layer.masksToBounds = true
btn.layer.cornerRadius = buttonWidth2 / 2.0
let offsetx2: CGFloat = CGFloat(self.r2 * cos(self.corner2 * Float(i) + Float(M_PI_2)))
let offsety2 = self.r2 * sin(self.corner2 * Float(i) + Float(M_PI_2))
btn.center = CGPoint(x: self.circleCenter.x - offsetx2, y: self.circleCenter.y - CGFloat(offsety2))
if (type == .RoundviewTypeCustom) {
let imageView: UIImageView = UIImageView(image: UIImage(named: images[I]))
imageView.contentMode = .scaleAspectFit
imageView.isUserInteractionEnabled = false
imageView.frame = CGRect(x: 25, y: 5, width: 30, height: 30)
btn.addSubview(imageView)
let label = UILabel(frame: CGRect(x: 10, y: imageView.frame.maxY + 5, width: self.buttonWidth - 20, height: 20))
label.text = titileArray[i]
label.font = UIFont.systemFont(ofSize: 10)
label.textColor = UIColor.black
label.textAlignment = .center
label.adjustsFontSizeToFitWidth = true
label.tag = I
btn.addSubview(label)
} else {
btn.setTitle(titileArray[i], for: .normal)
btn.setTitleColor(titileColor, for: .normal)
}
btn.tag = I
btn.addTarget(self, action: #selector(btnClick(btn:)), for: .touchUpInside)
self.addSubview(btn)
btnArray2.append(btn)
}
let circle = CAShapeLayer()
circle.fillColor = UIColor.clear.cgColor
circle.strokeColor = UIColor.gray.cgColor
circle.lineWidth = 1.0
circle.path = UIBezierPath(arcCenter: self.circleCenter, radius: self.cycleLineRadius / 2, startAngle: 0.0, endAngle: CGFloat(M_PI * 2), clockwise: true).cgPath
//注掉这行可以去除那个圆
layer.addSublayer(circle)
}
func show() {
if (self.isShow) {
UIView.animate(withDuration: 0.5, animations: {
for (i, _) in self.btnArray.enumerated() {
let btn: UIButton = self.btnArray[I]
let offsetx = self.r1 * cos(self.corner1 * Float(i) + Float(M_PI_2))
let offsety = self.r1 * sin(self.corner1 * Float(i) + Float(M_PI_2))
btn.center = CGPoint(x: self.circleCenter.x - CGFloat(offsetx), y: self.circleCenter.y - CGFloat(offsety))
btn.alpha = 1
let btn2: UIButton = self.btnArray2[I]
let offsetx2 = self.r2 * cos(self.corner2 * Float(i) + Float(M_PI_2))
let offsety2 = self.r2 * sin(self.corner2 * Float(i) + Float(M_PI_2))
btn2.center = CGPoint(x: self.circleCenter.x - CGFloat(offsetx2), y: self.circleCenter.y - CGFloat(offsety2))
btn2.alpha = btn.alpha
}
}, completion: nil)
} else {
UIView.animate(withDuration: 0.5) {
for (index, _) in self.btnArray.enumerated() {
let btn: UIButton = self.btnArray[index]
btn.center = self.circleCenter
btn.alpha = 0
let btn2: UIButton = self.btnArray2[index]
btn2.center = self.circleCenter
btn2.alpha = btn.alpha
}
}
}
self.isShow = !self.isShow
}
func addRound2View(titileArray: [String], images: [String], conrenrRadius: CGFloat, btnWidth: CGFloat ) {
self.outSideArray = titileArray
for (i, _) in titileArray.enumerated() {
let btn = UIButton(type: .custom)
btn.frame = CGRect(x: 0, y: 0, width: self.buttonWidth, height: self.buttonWidth)
btn.layer.masksToBounds = true
btn.layer.cornerRadius = 40
let offsetx: CGFloat = CGFloat(self.r1 * cos(self.corner1 * Float(i) + Float(M_PI_2)))
let offsety = self.r1 * sin(self.corner1 * Float(i) + Float(M_PI_2))
btn.center = CGPoint(x: self.circleCenter.x - offsetx, y: self.circleCenter.y - CGFloat(offsety))
self.buttonWidth = btnWidth
if (type == .RoundviewTypeCustom) {
let imageView: UIImageView = UIImageView(image: UIImage(named: images[I]))
imageView.contentMode = .scaleAspectFit
imageView.isUserInteractionEnabled = false
imageView.frame = CGRect(x: 25, y: 5, width: 30, height: 30)
btn.addSubview(imageView)
let label = UILabel(frame: CGRect(x: 10, y: imageView.frame.maxY + 5, width: self.buttonWidth - 20, height: 20))
label.text = titileArray[i]
label.font = UIFont.systemFont(ofSize: 12)
label.textColor = UIColor.black
label.textAlignment = .center
label.adjustsFontSizeToFitWidth = true
label.tag = I
btn.addSubview(label)
} else {
btn.setTitle(titileArray[i], for: .normal)
btn.setTitleColor(UIColor.black, for: .normal)
}
btn.tag = I
btn.addTarget(self, action: #selector(btnClick(btn:)), for: .touchUpInside)
self.addSubview(btn)
btnArray.append(btn)
}
let circle = CAShapeLayer()
self.circleCenter = CGPoint(x: self.bounds.size.width/2.0, y: self.bounds.size.width/2.0)
circle.fillColor = UIColor.clear.cgColor
circle.strokeColor = UIColor.red.cgColor
circle.lineWidth = 1.0
circle.path = UIBezierPath(arcCenter: self.circleCenter, radius: self.cycleLineRadius, startAngle: 0.0, endAngle: CGFloat(M_PI * 2), clockwise: true).cgPath
//注掉这行可以去除那个圆
layer.addSublayer(circle)
}
@objc func btnClick(btn: UIButton) {
self.isShow = true
let num1 = btn.tag
let name: String = nameArray?[num1] ?? ""
let outSideName: String = outSideArray?[num1] ?? ""
self.show()
if let block = self.block {
block(outSideName, name)
}
}
@objc func changeMove(rotation: RotationGestureRecognizer) {
if (self.btnArray!.count < 13) {
if (self.rotationAngleInRadians == 0 && rotation.rotation > 0) {
return
}
}
self.transform = CGAffineTransform(rotationAngle: self.rotationAngleInRadians + rotation.rotation)
for btn in self.btnArray {
btn.transform = CGAffineTransform(rotationAngle: -(self.rotationAngleInRadians + rotation.rotation))
}
for btn in self.btnArray2 {
btn.transform = CGAffineTransform(rotationAngle: -(self.rotationAngleInRadians + rotation.rotation))
}
self.rotationAngleInRadians += rotation.rotation;
}
}
RotationGestureRecognizer:
实现拖拽旋转效果:
import UIKit
class RotationGestureRecognizer: UIGestureRecognizer {
var rotation: CGFloat = 0.0
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
if (event.touches(for: self)!.count > 1) {
self.state = UIGestureRecognizer.State.failed
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
if (self.state == UIGestureRecognizer.State.possible) {
self.state = UIGestureRecognizer.State.began
} else {
self.state = UIGestureRecognizer.State.changed
}
let touch: UITouch? = touches.first
let view: UIView? = self.view
let center: CGPoint = CGPoint(x: 100, y: 100)
let currentTouchPoint: CGPoint = (touch?.location(in: view))!
let previousTouchPoint: CGPoint = (touch?.previousLocation(in: view))!
let angleInRadians: CGFloat = CGFloat(atan2f(Float(currentTouchPoint.y - center.y), Float(currentTouchPoint.x - center.x)) - atan2f(Float(previousTouchPoint.y - center.y), Float(previousTouchPoint.x - center.x)))
self.rotation = angleInRadians
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
if (self.state == UIGestureRecognizer.State.changed) {
self.state = UIGestureRecognizer.State.ended
} else {
self.state = UIGestureRecognizer.State.failed
}
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent) {
self.state = UIGestureRecognizer.State.failed
}
}
调用如下:
let imageArray = ["mine_histroyIcon", "mine_histroyIcon", "mine_histroyIcon", "mine_histroyIcon", "mine_histroyIcon"]
let titleArray = ["小锅", "拼锅", "单锅", "四宫格", "四宫格"]
roundView = Roundview(frame: CGRect(x: 0, y: 0, width: 400, height: 400))
// roundView.backgroundColor = UIColor(red: 100/255.0, green: 152/255.0, blue: 251/255.0, alpha: 0.7)
roundView.configure(type: .RoundviewTypeCustom, btnWidth: 80, adjustsFontSizesTowidth: true, masksToBounds: true, conrenrRadius: 40, images: imageArray, titileArray: titleArray, titileColor: UIColor.black, cycleLineRadius: 160.0)
roundView.center = self.view.center
self.view.addSubview(roundView)
roundView.block = {(name1, name2) in
print(name1, name2)
}
点击屏幕实现加外圈:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let imageArray = ["mine_histroyIcon", "mine_histroyIcon", "mine_histroyIcon", "mine_histroyIcon", "mine_histroyIcon"]
let titleArray = ["加麻", "加辣", "加番茄", "无渣", "特辣"]
roundView.addRound2View(titileArray: titleArray, images: imageArray, conrenrRadius: 160.0, btnWidth: 80)
}
参考链接:
iOS 圆盘旋转 ~demo:
https://blog.csdn.net/shihuboke/article/details/83277900
网友评论