我有一个叫做ChartView
的容器,里面装着我星球的UIImageView
。我以编程的方式添加我的行星,然后给它们分配UIPanGestureRecognizer
。根据我的理解,我需要将委托转发到容器ViewController,然后实现我的draggedView()
函数。
我成功地进入了这个函数,但是即使我在draggedView()中打印它的新位置,UIImageView也不会在视觉上移动。我做错了什么?
****更新****
import UIKit
extension FloatingPoint {
var degreesToRadians: Self { return self * .pi / 180 }
var radiansToDegrees: Self { return self * 180 / .pi }
}
extension CGFloat {
static func random() -> CGFloat {
return CGFloat(arc4random()) / CGFloat(UInt32.max)
}
}
extension UIColor {
static func random() -> UIColor {
return UIColor(red: .random(),
green: .random(),
blue: .random(),
alpha: 1)
}
}
class FirstViewController: UIViewController, UIGestureRecognizerDelegate {
@IBOutlet weak var chartView: ChartView!
private var planets: [Planet] = []
override func viewDidLoad() {
super.viewDidLoad()
self.chartView.delegate = self
self.chartView.setSegmentValues(
values: [50, 50, 50,50,50,50,50,50,50,50,50,50],
totals: [50, 50, 50,50,50,50,50,50,50,50,50,50])
self.chartView.addPlanet(fullAngle: CGFloat(180),name: "test")
}
@objc func didPan(sender: UIPanGestureRecognizer) {
let translation = sender.translation(in: self.view)
if let view = sender.view {
view.center = CGPoint(x:view.center.x + translation.x,
y:view.center.y + translation.y)
}
sender.setTranslation(CGPoint.zero, in: self.view)
print("Pos: \(translation.x)- \(translation.y)")
}
}
这是图表视图:
import UIKit
import Foundation
@IBDesignable class ChartView: UIView {
var delegate: UIGestureRecognizerDelegate?
// Static value
private let ELEMENT_COLOR: [UIColor] = [UIColor.red, UIColor.gray, UIColor.blue, UIColor.yellow, UIColor.cyan]
//Values for each segment
private var segmentValues : [Float]
//Total for each segment
private var segmentTotals : [Float]
//Sum of each segmentTotals element
private var segmentTotalAll : Float
override init(frame: CGRect) {
segmentValues = []
segmentTotals = []
segmentTotalAll = 0
super.init(frame: frame)
self.isUserInteractionEnabled = true
self.backgroundColor = UIColor.clear
}
required init?(coder aDecoder: NSCoder) {
segmentValues = []
segmentTotals = []
segmentTotalAll = 0
super.init(coder: aDecoder)
self.isUserInteractionEnabled = true
self.backgroundColor = UIColor.clear
}
override func draw(_ rect: CGRect) {
// Base Circle
UIColor.random().setFill()
let outerPath = UIBezierPath(ovalIn: rect)
outerPath.fill()
// Semicircles
//self.frame isn't defined yet, so we can't use self.center
let viewCenter = CGPoint(x: rect.width / 2, y: rect.height / 2)
var i: Int = 0
var lastAngle :Float = 0.0
let baseCircleRadius = rect.width / 2 - 1.5
let centerCircleRadius = rect.width / 2 * 0.4
//value : current number
for value in segmentValues {
//total : total number
let total = segmentTotals[i]
//offsetTotal : difference between Base Circle and Center Circle
let offset = baseCircleRadius - centerCircleRadius
//radius : radius of segment
let radius = CGFloat(value / total) * offset + centerCircleRadius
//startAngle : start angle of this segment
let startAngle = lastAngle
//endAngle : end angle of this segment
let endAngle = lastAngle + total / segmentTotalAll * 360.0
//color : color of the segment
let color = self.ELEMENT_COLOR[i % 4]
color.setFill()
let midPath = UIBezierPath()
midPath.move(to: viewCenter)
midPath.addArc(withCenter: viewCenter, radius: CGFloat(radius), startAngle: CGFloat(startAngle.degreesToRadians), endAngle: CGFloat(endAngle.degreesToRadians), clockwise: true)
midPath.close()
UIColor.black.setStroke()
midPath.lineWidth = 2
midPath.stroke()
midPath.fill()
lastAngle = endAngle
i += 1
}
//Center circle
UIColor.white.setFill()
let centerPath = UIBezierPath(ovalIn: rect.insetBy(dx: rect.width / 2 * 0.4, dy: rect.height / 2 * 0.4))
UIColor.black.setStroke()
centerPath.lineWidth = 3
centerPath.stroke()
centerPath.fill()
}
//Sets all the segment members in order to draw each segment
func setSegmentValues(values : [Int], totals : [Int]){
//Must be equal lengths
if values.count != totals.count{
return;
}
//Set the colors
segmentTotalAll = 0
for total in totals {
segmentTotalAll += Float(total)
segmentTotals.append(Float(total))
}
for val in values {
segmentValues.append(Float(val))
}
}
public func addPlanet(fullAngle: CGFloat, name: String) {
let planetPosition: CGPoint = self.getPosition(center: CGPoint(x: self.frame.width/2, y: self.frame.height/2), radius: self.bounds.width/4, angle: fullAngle)
let planetImageView: UIImageView = UIImageView()
planetImageView.frame = CGRect(origin: planetPosition, size: CGSize(width: 10, height: 10))
planetImageView.center = planetPosition
planetImageView.backgroundColor = .blue
self.addSubview(planetImageView)
let panGesture = UIPanGestureRecognizer(target: self.delegate, action: #selector(FirstViewController.didPan(sender:)))
panGesture.delegate = self.delegate
planetImageView.isUserInteractionEnabled = true
planetImageView.addGestureRecognizer(panGesture)
// paint curve for sun
let path = UIBezierPath(arcCenter: CGPoint(x: self.frame.width/2, y: self.frame.height/2), radius: self.bounds.width/4, startAngle: CGFloat(0), endAngle: fullAngle.degreesToRadians, clockwise: true)
let animation = CAKeyframeAnimation(keyPath: #keyPath(CALayer.position))
animation.duration = 1.5
animation.isRemovedOnCompletion = false // do not remove the animation effect, no state changes.
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
animation.fillMode = kCAFillModeBoth // keep to value after finishing
animation.path = path.cgPath
planetImageView.layer.add(animation, forKey: animation.keyPath)
}
private func getPosition(center: CGPoint, radius: CGFloat, angle: CGFloat) -> CGPoint {
return CGPoint(x: center.x + radius * cos(angle.degreesToRadians), y: center.y + radius * sin(angle.degreesToRadians))
}
public func addCenterCircle(){
let centerCircle = UIBezierPath(arcCenter: CGPoint(x: self.bounds.width/2,y: self.bounds.height/2), radius: self.bounds.width/4, startAngle: CGFloat(0), endAngle:CGFloat(Double.pi * 2), clockwise: true)
let shapeLayer = CAShapeLayer()
shapeLayer.path = centerCircle.cgPath
//change the fill color
shapeLayer.fillColor = UIColor.white.cgColor
//you can change the stroke color
shapeLayer.strokeColor = UIColor.black.cgColor
//you can change the line width
shapeLayer.lineWidth = 1
self.layer.addSublayer(shapeLayer)
}
}
最佳答案
我创建了一个简单的蓝色正方形,然后添加了一个红色的行星。你可以煎一个红方块。
下面是一个示例,以编程方式。
import UIKit
class ViewController: UIViewController, UIGestureRecognizerDelegate {
private lazy var chartView: ChartView = {
let cv = ChartView(frame: CGRect(x: 0,
y: 0,
width: view.frame.width - 20,
height: view.frame.height/2))
cv.center = view.center
// Important
cv.panGesture.delegate = self
return cv
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(chartView)
chartView.addPlanet(fullAngle: 50, name: "Mars")
}
}
class ChartView: UIView {
lazy var panGesture: UIPanGestureRecognizer = {
let v = UIPanGestureRecognizer(target: self, action: #selector(didPan(sender:)))
return v
}()
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .blue
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc private func didPan(sender: UIPanGestureRecognizer) {
let translation = sender.translation(in: self)
if let view = sender.view {
view.center = CGPoint(x:view.center.x + translation.x,
y:view.center.y + translation.y)
}
sender.setTranslation(CGPoint.zero, in: self)
print("Pos: \(translation.x)- \(translation.y)")
}
func addPlanet(fullAngle: CGFloat, name: String) {
let planetImageView: UIImageView = UIImageView()
planetImageView.frame = CGRect(origin: CGPoint(x: 0, y: 0), size: CGSize(width: 100, height: 100))
planetImageView.backgroundColor = .red
planetImageView.addGestureRecognizer(panGesture)
planetImageView.isUserInteractionEnabled = true
self.addSubview(planetImageView)
}
}
关于ios - 使用UIPanGestureRecognizer拖动时,UIView不会移动,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51912873/