I am trying to show arrow of my selected page menu. But, the arrow which I draw didn't show as I expected. It needs to be up
Here is my code:
class ArrowView : UIView {
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor.clear
}
var rect: CGRect!
var arrorBackgroundColor: UIColor?
var midX: CGFloat { return rect.midX }
var midY: CGFloat { return rect.midY }
var maxX: CGFloat { return rect.maxX }
var maxY: CGFloat { return rect.maxY }
override func draw(_ rect: CGRect) {
self.rect = rect
let ctx = UIGraphicsGetCurrentContext()
ctx?.beginPath()
ctx?.move(to: CGPoint(x: 0, y: 0))
// Old code which the arrow was down
// ctx?.addQuadCurve(to: CGPoint(x:maxX * 0.2 , y: maxY * 0.2), control: CGPoint(x: maxX * 0.12, y: 0))
// ctx?.addLine(to: CGPoint(x: midX - maxX * 0.05, y: maxY * 0.9))
// ctx?.addQuadCurve(to: CGPoint(x: midX + maxX * 0.05, y: maxY * 0.9), control: CGPoint(x: midX, y: maxY))
// ctx?.addLine(to: CGPoint(x: maxX * 0.8, y: maxY * 0.2))
// ctx?.addQuadCurve(to: CGPoint(x: maxX, y: 0), control: CGPoint(x: maxX * 0.88, y: 0))
ctx?.addLine(to: CGPoint(x: midX - maxX * 106.5, y: maxY * 65.5))
ctx?.addLine(to: CGPoint(x: maxX * 128.5, y: maxY * 88.5))
ctx?.addLine(to: CGPoint(x: 85.5, y: 88.5))
ctx?.closePath()
ctx?.setFillColor((arrorBackgroundColor?.cgColor)!)
ctx?.fillPath();
}
}
And here how it goes
Actually I am trying to customize this library : https://github.com/azurechen/ACTabScrollView
And trying to archive like this : https://puu.sh/viWwc/35a6bddb0d.png
Since I am beginner with UIBezierPath
, any help is appreciated.
I don't understand the constants in your calls to addLine(to:)
and I think the implementation of ArrowView
is unnecessarily weird.
You seem to be confused about midX
/maxX
/... (or I'm just too dense to get it right now). The CGRect documentation should help.
I think the original author of ArrowView
(from the github project you linked to) somehow mixed up bounds
and frame
when setting the arrow's position. Oh, and he also abused the rect
parameter in draw(_:)
, see the docs. Specifically (emphasis mine):
rect
The portion of the view’s bounds that needs to be updated. The first time your view is drawn, this rectangle is typically the entire visible bounds of your view. However, during subsequent drawing operations, the rectangle may specify only part of your view.
Also, ACTabScrollView
seems to work only sometimes. In my shallow experiments, it messed up view positioning most of the time.
Anyways, to implement a simple UIView
for an upwards pointing arrow, this works:
class ArrowView : UIView {
var arrorBackgroundColor: UIColor = UIColor.red
override func draw(_ rect: CGRect) {
guard let ctx = UIGraphicsGetCurrentContext() else { return }
// Sample to really fill the background before drawing the arrow.
ctx.setFillColor(UIColor.yellow.cgColor)
ctx.fill(bounds)
ctx.beginPath()
ctx.move(to: CGPoint(x: 0, y: bounds.maxY))
ctx.addLine(to: CGPoint(x: bounds.midX, y: bounds.minY))
ctx.addLine(to: CGPoint(x: bounds.maxX, y: bounds.maxY))
ctx.addLine(to: CGPoint(x: 0, y: bounds.maxY))
ctx.closePath()
ctx.setFillColor(arrorBackgroundColor.cgColor)
ctx.fillPath()
}
}
The core is using the view's bounds
to compute the coordinates.
From the UIView docs:
The geometry of a view is defined by its frame, bounds, and center properties. The frame defines the origin and dimensions of the view in the coordinate system of its superview and is commonly used during layout to adjust the size or position of the view. The center property can be used to adjust the position of the view without changing its size. The bounds defines the internal dimensions of the view as it sees them and is used almost exclusively in custom drawing code. The size portion of the frame and bounds rectangles are coupled together so that changing the size of either rectangle updates the size of both.
I think arrorBackgroundColor
should really be called arrowColor
(because it is used as the color of the arrow) and you might have another property arrorBackgroundColor
that really is for the background. I added two lines that fill the background with yellow as an example.