how to create this 2D look
How to I create this.
Thanks a lot.
Try this
class TwoDView : UIView {
public var xDiff : CGFloat = 5.0
public var yDiff : CGFloat = 5.0
override func draw(_ rect: CGRect) {
let ctx = UIGraphicsGetCurrentContext()
ctx?.move(to: CGPoint(x: 0, y: rect.height - yDiff))
ctx?.addLines(between: [
CGPoint(x: rect.width - xDiff, y: rect.height - yDiff),
CGPoint(x: rect.width, y: rect.height),
CGPoint(x: xDiff, y: rect.height),
CGPoint(x: 0, y: rect.height - yDiff)
])
ctx?.setFillColor(UIColor.black.cgColor)
ctx?.fillPath()
ctx?.move(to: CGPoint(x: rect.width - xDiff, y: 0))
ctx?.addLines(between: [
CGPoint(x: rect.width, y: yDiff),
CGPoint(x: rect.width, y: rect.height),
CGPoint(x: rect.width - xDiff, y: rect.height - yDiff),
CGPoint(x: rect.width - xDiff, y: 0)
])
ctx?.setFillColor(UIColor.gray.cgColor)
ctx?.fillPath()
UIImage(named: "Image")?.draw(in: CGRect(x: 0, y: 0, width: rect.width - xDiff, height: rect.height - yDiff))
}
}
Related
I want to make curved bottom bar it is not looking perfect round by below code
struct customShape: Shape {
var xAxis : CGFloat
var animatableData: CGFloat{
get { return xAxis}
set { xAxis = newValue}
}
func path(in rect: CGRect) -> Path {
return Path { path in
path.move(to: CGPoint(x: 0, y: 0))
path.addLine(to: CGPoint(x: rect.width, y: 0))
path.addLine(to: CGPoint(x: rect.width, y: rect.height))
path.addLine(to: CGPoint(x: 0, y: rect.height))
let center = xAxis
path.move(to: CGPoint(x: center - 43, y: 0))
let to1 = CGPoint(x: center, y: 50)
let center1 = CGPoint(x: center - 30, y: 0)
let center2 = CGPoint(x: center - 46, y: 42)
let to2 = CGPoint(x: center + 52, y: 0)
let center3 = CGPoint(x: center + 57, y: 47)
let center4 = CGPoint(x: center + 35, y: 0)
path.addCurve(to: to1, control1: center1, control2: center2)
path.addCurve(to: to2, control1: center3, control2: center4)
}
}
}
You are trying to construct a circle with Bezier handles. And it seems you are not calculating the values but guessing and trying. This will be at least very hard if not impossible to solve. Try to add an arc instead of a curve.
Possible implementation:
struct customShape: Shape {
var xAxis : CGFloat
var radius: CGFloat = 40
var animatableData: CGFloat{
get { return xAxis}
set { xAxis = newValue}
}
func path(in rect: CGRect) -> Path {
return Path { path in
path.move(to: CGPoint(x: 0, y: 0))
// add a line to the starting point of the circle
path.addLine(to: CGPoint(x: xAxis - radius, y: 0))
// add the arc with the centerpoint of (xAxis,0) and 180°
path.addArc(center: .init(x: xAxis, y: 0), radius: radius, startAngle: .init(degrees: 180), endAngle: .init(degrees: 0), clockwise: true)
// complete the rectangle
path.addLine(to: .init(x: rect.size.width, y: 0))
path.addLine(to: CGPoint(x: rect.width, y: rect.height))
path.addLine(to: CGPoint(x: 0, y: rect.height))
path.closeSubpath()
}
}
}
I'm trying to use my own UITabBar instance inside a UITabBarController. Using Storyboard I know that you can add your Custom Class to your TabbarController using the following:
How can I achieve the same thing programmatically?
Here's my custom class:
I've tried modifying and overriding the tabBar variable inside UITabBarController but it seems that it's a get only variable and can not be modified. Is there an easy solution to fix this issue?
Much appreciated!
class CustomTabBar: UITabBar {
private var shapeLayer: CALayer?
private func addShape() {
let shapeLayer = CAShapeLayer()
shapeLayer.path = createPath()
shapeLayer.strokeColor = UIColor.lightGray.cgColor
shapeLayer.fillColor = UIColor.white.cgColor
shapeLayer.lineWidth = 1.0
if let oldShapeLayer = self.shapeLayer {
self.layer.replaceSublayer(oldShapeLayer, with: shapeLayer)
} else {
self.layer.insertSublayer(shapeLayer, at: 0)
}
self.shapeLayer = shapeLayer
}
override func draw(_ rect: CGRect) {
self.addShape()
}
func createPath() -> CGPath {
let height: CGFloat = 37.0
let path = UIBezierPath()
let centerWidth = self.frame.width / 2
path.move(to: CGPoint(x: 0, y: 0)) // start top left
path.addLine(to: CGPoint(x: (centerWidth - height * 2), y: 0)) // the beginning of the trough
// first curve down
path.addCurve(to: CGPoint(x: centerWidth, y: height),
controlPoint1: CGPoint(x: (centerWidth - 30), y: 0), controlPoint2: CGPoint(x: centerWidth - 35, y: height))
// second curve up
path.addCurve(to: CGPoint(x: (centerWidth + height * 2), y: 0),
controlPoint1: CGPoint(x: centerWidth + 35, y: height), controlPoint2: CGPoint(x: (centerWidth + 30), y: 0))
// complete the rect
path.addLine(to: CGPoint(x: self.frame.width, y: 0))
path.addLine(to: CGPoint(x: self.frame.width, y: self.frame.height))
path.addLine(to: CGPoint(x: 0, y: self.frame.height))
path.close()
return path.cgPath
}
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
let buttonRadius: CGFloat = 35
return abs(self.center.x - point.x) > buttonRadius || abs(point.y) > buttonRadius
}
func createPathCircle() -> CGPath {
let radius: CGFloat = 37.0
let path = UIBezierPath()
let centerWidth = self.frame.width / 2
path.move(to: CGPoint(x: 0, y: 0))
path.addLine(to: CGPoint(x: (centerWidth - radius * 2), y: 0))
path.addArc(withCenter: CGPoint(x: centerWidth, y: 0), radius: radius, startAngle: CGFloat(180).degreesToRadians, endAngle: CGFloat(0).degreesToRadians, clockwise: false)
path.addLine(to: CGPoint(x: self.frame.width, y: 0))
path.addLine(to: CGPoint(x: self.frame.width, y: self.frame.height))
path.addLine(to: CGPoint(x: 0, y: self.frame.height))
path.close()
return path.cgPath
}
}
And here's my view controller:
final class TabbarViewController: UITabBarController {
// MARK: - Properties
private lazy var tabBarItemControllers: [UIViewController] = {
let editorController = ...
let settingsController = ...
return [editorController, settingsController]
}()
// MARK: - Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
configureTabbar()
setViewControllers(tabBarItemControllers, animated: true)
}
}
i have a problem while drawing curve:
strokePath = UIBezierPath()
strokePath.move(to: CGPoint(x:curveWidth / 2.0 - headerWidth, y: headerHeight))
strokePath.addLine(to: CGPoint(x: 0, y: headerHeight))
strokePath.addCurve(to: CGPoint(x: curveRadius, y: headerHeight - curveRadius),
controlPoint1: CGPoint(x: degree, y: headerHeight),
controlPoint2: CGPoint(x: curveRadius, y: headerHeight - curveRadius))
strokePath.addLine(to: CGPoint(x: curveWidth - curveRadius, y: curveRadius))
strokePath.addCurve(to: CGPoint(x: curveWidth, y: 0),
controlPoint1: CGPoint(x: curveWidth - curveRadius + curveRadius * 0.25, y: 0),
controlPoint2: CGPoint(x: curveWidth, y: 0))
strokePath.addLine(to: CGPoint(x: self.frame.size.width, y: 0.0))
strokeLayer.path = strokePath.cgPath
strokeLayer.strokeColor = uiConfig.color.misc.tabGrayBorder.cgColor
strokeLayer.fillColor = UIColor.clear.cgColor
strokeLayer.lineWidth = 0.5
self.layer.addSublayer(strokeLayer)
and i have unexpectable result:
curve is bold than the line, have somebody idea why it happened and how it fixing?
sorry, its my mistake after review many lines of code i find active "Clip to bounds" property of one of my parent view
How do i design a UIView whose all 4 corners have different corner radius. So, UIView with its top right corner radius of 20, top left corner radius of 30, bottom left corner radius of 10 and bottom right corner radius of 20
I want to add different cornerRadius to Viw Container shown in image.
using UIBEZIER method cuts off the share comment and like portion.
viw Container is pinned to cell
You can use this UIView extension. It will create and apply a mask layer according to your radius values.
extension UIView {
func applyRadiusMaskFor(topLeft: CGFloat = 0, bottomLeft: CGFloat = 0, bottomRight: CGFloat = 0, topRight: CGFloat = 0) {
let path = UIBezierPath()
path.move(to: CGPoint(x: bounds.width - topRight, y: 0))
path.addLine(to: CGPoint(x: topLeft, y: 0))
path.addQuadCurve(to: CGPoint(x: 0, y: topLeft), controlPoint: .zero)
path.addLine(to: CGPoint(x: 0, y: bounds.height - bottomLeft))
path.addQuadCurve(to: CGPoint(x: bottomLeft, y: bounds.height), controlPoint: CGPoint(x: 0, y: bounds.height))
path.addLine(to: CGPoint(x: bounds.width - bottomRight, y: bounds.height))
path.addQuadCurve(to: CGPoint(x: bounds.width, y: bounds.height - bottomRight), controlPoint: CGPoint(x: bounds.width, y: bounds.height))
path.addLine(to: CGPoint(x: bounds.width, y: topRight))
path.addQuadCurve(to: CGPoint(x: bounds.width - topRight, y: 0), controlPoint: CGPoint(x: bounds.width, y: 0))
let shape = CAShapeLayer()
shape.path = path.cgPath
layer.mask = shape
}
}
Example usage:
let view = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
view.backgroundColor = .red
view.applyRadiusMaskFor(topLeft: 80, bottomLeft: 40, bottomRight: 30, topRight: 60)
Result: Radius applied image
Currently I am having a small issue. The code below will output an triangle shaped layer on top of my tableViewHeader but I want to reverse the cut direction of the bazier path.
Code:
let cutDirection = UIBezierPath()
cutDirection.move(to: CGPoint(x: 0, y: 0))
cutDirection.addLine(to: CGPoint(x: headerRect.width, y: 0))
cutDirection.addLine(to: CGPoint(x: headerRect.width, y: headerRect.height))
cutDirection.addLine(to: CGPoint(x: 0, y: headerRect.height - headerCut))
newHeaderLayer.path = cutDirection.cgPath
Outputs:
Result I am looking for:
Thanks for any help!
Kevin.
Try this:
let cutDirection = UIBezierPath()
cutDirection.move(to: CGPoint(x: 0, y: 0))
cutDirection.addLine(to: CGPoint(x: headerRect.width, y: 0))
cutDirection.addLine(to: CGPoint(x: headerRect.width, y: headerRect.height - headerCut))
cutDirection.addLine(to: CGPoint(x: 0, y: headerRect.height))
newHeaderLayer.path = cutDirection.cgPath
If I follow this correctly you should swap the following:
cutDirection.addLine(to: CGPoint(x: headerRect.width, y: headerRect.height))
cutDirection.addLine(to: CGPoint(x: 0, y: headerRect.height - headerCut))
To:
cutDirection.addLine(to: CGPoint(x: 0, y: headerRect.height - headerCut))
cutDirection.addLine(to: CGPoint(x: headerRect.width, y: headerRect.height))
Fixed it by doing it the old school way: On Paper!
Solution:
let cutDirection = UIBezierPath()
cutDirection.move(to: CGPoint(x: 0, y: 0))
cutDirection.addLine(to: CGPoint(x: headerRect.width, y: 0))
cutDirection.addLine(to: CGPoint(x: headerRect.width, y: headerRect.height - headerCut))
cutDirection.addLine(to: CGPoint(x: 0, y: headerRect.height))
cutDirection.close()
newHeaderLayer.path = cutDirection.cgPath