ios path绘制形状_使用UIBezierPath绘制自定义形状-iOS

ios path绘制形状

Today we will try to draw custom shapes and views and try to find out more about drawings in iOS (Swift) and how that can be done through CODE.

今天,我们将尝试绘制自定义形状和视图,并尝试找到有关iOS(Swift)中图纸的更多信息,以及如何通过CODE来实现。

For all the frontend developers, one of the most important parts of the development process is the implementation of User Interface. We can create a simple UI with a combination of pre-made graphics and in-built views in the Interface Builder, but this is not enough, there are often cases when devs need to draw custom shaped views programmatically to meet UI requirements, and if we are not able to draw those, it creates a problem.

对于所有前端开发人员来说,开发过程中最重要的部分之一就是用户界面的实现。 我们可以在Interface Builder中结合预制图形和内置视图来创建一个简单的UI,但这还不够,在很多情况下,开发人员需要以编程方式绘制自定义形状的视图来满足UI要求,如果我们无法绘制这些图形,这会产生问题。

This is where UIBezierPath comes in, it’s Apple’s way of helping devs draw on-screen programmatically. It may seem complex at first but it is quite simple to draw custom shapes.

这就是UIBezierPath出现的地方,这是Apple帮助开发人员以编程方式在屏幕上绘制的方式。 乍一看似乎很复杂,但是绘制自定义形状非常简单。

To make it more familiar, we will draw a custom shaped view and define it in such a way that we can use it like any inbuilt UI element.

为了使它更加熟悉,我们将绘制一个自定义形状的视图并对其进行定义,以使我们可以像使用任何内置UI元素一样使用它。

In this write-up we will touch upon the following topics:

在本文中,我们将涉及以下主题:

  1. Analysis of Custom View

    自定义视图分析

  2. UIBezierPath class

    UIBezierPath类

  3. Drawing view programmatically

    以编程方式绘制视图

  4. Use it in your storyboard/code

    在故事板/代码中使用它

To begin with, the aim will be to make a custom Card View that will have rounded corners and a button slot in the bottom-center

首先,我们的目标是制作一个自定义的Card View,该View的圆角和位于底部中心的按钮槽

Image for post
Final Card View with a button in the custom button slot and rounded corners
最终卡片视图,在自定义按钮插槽中带有一个按钮,并带有圆角

Note that here we are also going to draw round edges programmatically, which can be normally done using cornerRadius property of CAShapeLayer for almost any view. We do this to make concepts clearer by working on common properties, which will be interesting and will give a peek into how Apple might be doing things under the hood!

请注意,这里我们还将以编程方式绘制圆形边缘,通常可以使用CAShapeLayer的cornerRadius属性对几乎所有视图进行绘制。 我们这样做的目的是通过研究通用属性来使概念更清晰,这将很有趣,并且可以窥视苹果公司如何在后台进行操作!

When drawing custom views, it is always beneficial to first analyze and divide it into sections that we can easily draw as individual components and later merge them to create a complete view. Once this is done only then should we dive into coding the view. So we will do the same for our custom Card View.

绘制自定义视图时,首先将其分析并将其划分为易于作为单个组件轻松绘制的部分,然后将它们合并以创建完整的视图始终是有益的。 一旦完成此操作,我们就应该开始对视图进行编码了。 因此,我们将对自定义卡片视图执行相同的操作。

分析自定义视图 (Analyzing custom view)

Before analyzing the view it is important that we understand how the views are drawn on the screen. Consider the screen to be a Cartesian Plane with origin — (0, 0) at the top-left corner of the screen. Along with —

在分析视图之前,重要的是我们了解如何在屏幕上绘制视图。 将屏幕视为笛卡尔平面,其原点为(0,0)在屏幕的左上角。 随着 -

  1. Positive X-axis is along the width of the screen in the right direction

    正X轴沿屏幕的宽度沿正确方向
  2. Positive Y-axis is along the height of the screen in the downward direction

    Y轴正值沿屏幕高度在向下方向上
  3. Negative X-axis is along the left direction from the left edge of the screen

    负X轴沿屏幕左边缘的左侧方向
  4. Negative Y-axis is in the upward direction from the top edge of the screen

    负Y轴位于屏幕顶部边缘的上方

So for our analysis, we will consider the same with origin — (0, 0) at the top-left corner of the view frame, and positive x in the right direction along the width of the view and positive y in the downward direction along with the height of the view.

因此,对于我们的分析,我们将考虑原点-(0,0)在视图框架的左上角,在视图的右侧沿宽度方向为正x,在视图的向下沿宽度为正y与视图的高度。

Image for post
Layout guide for the analysis of the view
用于分析视图的布局指南

Card View — Width = N, Height = H

卡片视图-宽度= N,高度= H

Button Slot — Width = N/2, Height = 30

按钮插槽—宽度= N / 2,高度= 30

Thus the rectangular frame of our custom UI is from (0,0) to (N, H)

因此,我们的自定义用户界面的矩形框是从(0,0)到(N,H)

Broadly there are three types of sections in the UI drawing

UI绘图中大致分为三种类型的部分

1. Corner Arcs2. Button Slot Arcs3. Straight Lines

1.角弧2。 按钮槽弧3。 直线

We will now traverse the view starting from the top-right corner and move in the clockwise direction and investigate various sections and define their origin and length.

现在,我们将从右上角开始遍历该视图,并沿顺时针方向移动,并研究各个部分并定义其原点和长度。

  1. Topline — from (30, 0) to (N-30, 0)

    顶线 -从( 30,0 )到(N-30,0)

  2. Top-right arc — the origin of arc at (N-30, 30) and radius 30

    右上角圆弧 -在(N-30,30)和半径30处的圆弧原点

  3. Right line — from (N, 30) to (N, H-30–30)

    右行 -从(N,30)到(N,H-30–30)

  4. Bottom-right arc — the origin of arc at (N-30, H-30–30) and radius 30

    右下角的弧线 -在(N-30,H-30–30)和半径30处的弧线原点

  5. Bottom-right line — from (N-30, H-30) to (3N/4, H-30)

    右下角 -从(N-30,H-30)到(3N / 4,H-30)

  6. Right-buttonSlot arc — the origin of arc at (3N/4–30, H-30) and radius 30

    右按钮槽弧 —在(3N / 4–30,H-30)和半径30处的弧的原点

  7. Bottom-buttonSlot line — from (3N/4 –30, H) to (N/4+30, H)

    底部按钮插槽线 -从(3N / 4 –30,H)到(N / 4 + 30,H)

  8. Left-buttonSlot arc — the origin of arc at (N/4+30, H-30) and radius 30

    左键槽弧 -在(N / 4 + 30,H-30)和半径30处的弧的原点

  9. Bottom-left line — from (N/4, H-30) to (30, H-30)

    左下线 -从(N / 4,H-30)到(30,H-30)

  10. Bottom-left arc — the origin of arc at (30, H-30–30) and radius 30

    左下圆弧 -在(30,H-30–30)和半径30处的圆弧原点

  11. Left line — from (0, H-30–30) to (0, 30)

    左线 -从(0,H-30–30)到(0,30)

  12. Top-left arc — the origin of arc at (30, 30) and radius 30

    左上圆弧 -(30,30)和半径30处的圆弧原点

From the above traversal, it is clear that we can divide our card view into 12 individual sections and then combine them to form the complete view.We can do this by using UIBezierPath, where we can create 12 subpaths and later combine them to form the complete CardView.

通过以上遍历,很明显我们可以将卡片视图分为12个单独的部分,然后将它们组合以形成完整的视图。我们可以使用UIBezierPath做到这一点,我们可以创建12个子路径,然后将它们组合以形成完整的CardView。

Thus it is time to take a deeper look into UIBezierPath

因此,现在该深入了解UIBezierPath

UIBezierPath (UIBezierPath)

Before we start to code a pre-requisite that needs to be addressed is UIBezierPath class. Apple says-

在开始编写代码之前,需要解决的先决条件是UIBezierPath类。 苹果说-

A UIBezierPath object is a wrapper for a CGPathRef data type. Paths are vector-based shapes that are built using line and curve segments. You can use line segments to create rectangles and polygons, and you can use curve segments to create arcs, circles, and complex curved shapes.

UIBezierPath对象是CGPathRef数据类型的包装。 路径是使用线段和曲线段构建的基于矢量的形状。 您可以使用线段创建矩形和多边形,也可以使用曲线段创建圆弧,圆形和复杂的曲线形状。

This is what we need to create vector-based paths. With this class, we can define custom paths that describe any shape, and use those paths to achieve any custom result we want — simple or complex.

这就是我们创建基于矢量的路径所需要的。 通过此类,我们可以定义描述任何形状的自定义路径,并使用这些路径来实现我们想要的任何自定义结果-简单或复杂。

Two different ways this can be done are —

可以通过两种不同的方式来完成此操作-

  1. Using the shape initializers that let us draw pre-defined shapes — init(rect:), init(ovalIn:) etc

    使用形状初始值设定项让我们绘制预定义的形状init(rect:), init(ovalIn:)

  2. Using methods to add paths of different geometry as subpaths — addLine(to:), addArc(_:), append(:) etc

    使用方法将不同几何形状的路径添加为子路径addLine(to:), addArc(_:), append(:)

Note — A bezier path cannot stand on its own, it needs a Core Graphics context where it can be rendered. Context can be passed on in different ways. Here we will pass context by subclassing our custom view from UIView.

注意—贝塞尔曲线路径不能独立存在,它需要可在其中呈现的Core Graphics上下文。 上下文可以以不同的方式传递。 在这里,我们将通过从UIView继承自定义视图的子类来传递上下文。

是时候学习代码了 (Time to dive into code)

Since we now have the required knowledge about the UIBezierPath and have done some fair analysis of our card view we are now ready to dive into code and start defining our new custom view. For this

由于我们现在已经具备有关UIBezierPath的必需知识,并且已经对卡片视图进行了一些公平的分析,因此我们现在准备深入研究代码并开始定义新的自定义视图。 为了这

  1. Start a new Xcode project.

    启动一个新的Xcode项目。
  2. Define the custom class CardView that will inherit from UIView in ViewController.swift as in the below code snippet.

    定义自定义类CardView,该类将从ViewController.swift中的UIView继承,如下面的代码片段所示。
  3. Draw a custom shape for the CardView by overriding the draw(_:) method of the UIView class.

    通过覆盖UIView类的draw(_:)方法为CardView绘制自定义形状。

  4. In the draw(_:) method, create a UIBezierPath and add subpaths to it one by one in the same order as discussed in the above analysis.

    draw(_:)方法中,创建一个UIBezierPath并以与上述分析中讨论的顺序相同的顺序逐一添加子路径。

///
/// Custom card view class
///
class CardView : UIView
{
// init the view with a rectangular frame
override init(frame: CGRect)
{
super.init(frame: frame)
backgroundColor = UIColor.clear
} // init the view by deserialisation
required init?(coder aDecoder: NSCoder)
{
super.init(coder: aDecoder)
backgroundColor = UIColor.clear
} /// override the draw(_:) to draw your own view
///
/// Default implementation - `rectangular view`
///
override func draw(_ rect: CGRect)
{
// Card view corner radius
let cardRadius = CGFloat(30)
// Button slot arc radius
let buttonSlotRadius = CGFloat(30)

// Card view frame dimensions
let viewSize = self.bounds.size
// Effective height of the view
let effectiveViewHeight = viewSize.height - buttonSlotRadius // Get a path to define and traverse
let path = UIBezierPath() // Shift origin to left corner of top straight line
path.move(to: CGPoint(x: cardRadius, y: 0))

// top line
path.addLine(to: CGPoint(x: viewSize.width - cardRadius, y: 0)) // top-right corner arc
path.addArc(
withCenter: CGPoint(
x: viewSize.width - cardRadius,
y: cardRadius
),
radius: cardRadius,
startAngle: CGFloat(Double.pi * 3 / 2),
endAngle: CGFloat(0),
clockwise: true
) // right line
path.addLine(
to: CGPoint(x: viewSize.width, y: effectiveViewHeight)
)

// bottom-right corner arc
path.addArc(
withCenter: CGPoint(
x: viewSize.width - cardRadius,
y: effectiveViewHeight - cardRadius
),
radius: cardRadius,
startAngle: CGFloat(0),
endAngle: CGFloat(Double.pi / 2),
clockwise: true
) // right half of bottom line
path.addLine(
to: CGPoint(x: viewSize.width / 4 * 3, y: effectiveViewHeight)
) // button-slot right arc
path.addArc(
withCenter: CGPoint(
x: viewSize.width / 4 * 3 - buttonSlotRadius,
y: effectiveViewHeight
),
radius: buttonSlotRadius,
startAngle: CGFloat(0),
endAngle: CGFloat(Double.pi / 2),
clockwise: true
)

// button-slot line
path.addLine(
to: CGPoint(
x: viewSize.width / 4 + buttonSlotRadius,
y: effectiveViewHeight + buttonSlotRadius
)
) // button left arc
path.addArc(
withCenter: CGPoint(
x: viewSize.width / 4 + buttonSlotRadius,
y: effectiveViewHeight
),
radius: buttonSlotRadius,
startAngle: CGFloat(Double.pi / 2),
endAngle: CGFloat(Double.pi),
clockwise: true
) // left half of bottom line
path.addLine(
to: CGPoint(x: cardRadius, y: effectiveViewHeight)
) // bottom-left corner arc
path.addArc(
withCenter: CGPoint(
x: cardRadius,
y: effectiveViewHeight - cardRadius
),
radius: cardRadius,
startAngle: CGFloat(Double.pi / 2),
endAngle: CGFloat(Double.pi),
clockwise: true
) // left line
path.addLine(to: CGPoint(x: 0, y: cardRadius)) // top-left corner arc
path.addArc(
withCenter: CGPoint(x: cardRadius, y: cardRadius),
radius: cardRadius,
startAngle: CGFloat(Double.pi),
endAngle: CGFloat(Double.pi / 2 * 3),
clockwise: true
)

// close path join to origin
path.close() // Set the background color of the view
UIColor.gray.set()
path.fill()
}
}

In the above code snippet, we have used —

在上述代码段中,我们使用了-

  1. path.move(to:) — to move to a new position without drawing on the canvas, takes in — a destination point.

    path.move(to :) —移至新位置而不在画布上绘图,则进入—目标点。

  2. path.addLine(to:) — to draw a straight line, takes in — a destination point.

    path.addLine(to :) -绘制一条直线,并接受-一个目的地点。

  3. path.addArc(:) — to draw an arc, takes in — a center for the arc, a radius of the arc, a start angle in radians(π), an end angle in radians(π) and a direction of translation(clockwise/anti-clockwise).

    path.addArc(:) —绘制弧,取入—弧的中心 ,弧的半径 ,以弧度(π)为单位的起始角度,以弧度(π)为单位的终止角度和平移方向 (顺时针/逆时针)。

  4. path.close() — to join the current position to the point of origin and close the figure by drawing a straight line(by default).

    path.close() —将当前位置连接到原点,并通过绘制一条直线(默认情况下)来关闭图形。

Since now we have successfully defined our custom view class — CardView, it is now time to use it.

从现在开始,我们已经成功定义了自定义视图类CardCard,现在该使用它了。

使用自定义视图类 (Using the custom view class)

To use our custom view, for this we will now move to storyboard —

要使用我们的自定义视图,为此,我们现在转到情节提要-

  1. Open Main.storyboard

    打开主板
  2. Remove the default NavigationView and UITableViewController and add a new UIViewController to the canvas.

    删除默认的NavigationView和UITableViewController并将新的UIViewController添加到画布。
  3. Make it the Root view by clicking on the Is initial view controller in Attribute Inspector.

    通过单击“属性检查Is initial view controller中的“ Is initial view controller ,使其成为“ Root view

Image for post
Added a new UIViewController and set it as the initial view controller
添加了一个新的UIViewController并将其设置为初始视图控制器

Once that is done we can start adding UI elements into our UIViewController.

一旦完成,我们就可以开始将UI元素添加到我们的UIViewController中。

  1. Start by adding a new view — UIView to the canvas and rename it to cardView

    首先添加一个新视图— UIView到画布,然后将其重命名为cardView

  2. Set the constraints for the UIView as —

    将UIView的约束设置为—
1. Safe Area.trailing = cardView.trailing + 16 //Trailing constraint
2. cardView.centerY = Safe Area.centerY //Vertical constraint
3. cardView.leading = Safe Area.leading + 16 //Leading constraint
4. cardView.height = 0.5 × height //Height constraint
Image for post
Added auto layout constraints to the UIView
向UIView添加了自动布局约束

Now we have our view ready and setup

现在我们准备好视图并进行设置

In the property inspector on the right panel add the class of our UIView to CardView.

在右侧面板的属性检查器中,将UIView的类添加到CardView。

Image for post
Set the class of the UIView to CardView
将UIView的类设置为CardView

With this, the storyboard setup is done.

这样,情节提要设置就完成了。

We are Done! And that is all we had to do to make our custom view show on the screen. Now run your app and see our custom view. Similar to this —

我们完了! 这就是我们要做的,以便在屏幕上显示我们的自定义视图。 现在运行您的应用程序并查看我们的自定义视图。 与此类似-

Image for post

在卡片视图中添加按钮 (Adding a button to the card view)

To add a UIButton to the view

向视图添加UIButton

  1. Open Main.storyboard file and add a UIButton to the card view

    打开Main.storyboard文件,然后向卡视图添加UIButton
  2. Set up the constraints for the button as —

    将按钮的约束设置为-
1. bottom = Button.bottom + 5      //Bottom constraint
2. Button.centerX = centerX //Horizontal constrain
3. Button.width = 0.47 × width //button width constraint
4. height = 50 //button height constraint

Change the button appearance by changing the background color/tint color

通过更改背景色/淡色来更改按钮外观

Image for post
Add button and its constraints
添加按钮及其约束

To make the corners of the button curve, create an IBOutlet of the button.

要绘制按钮曲线的角,请创建按钮的IBOutlet。

@IBOutlet private weak var button: UIButton!

and add the following line to viewDidLoad() in the ViewController class.

并将以下行添加到ViewController类的viewDidLoad()中。

button.layer.cornerRadius = button.bounds.height / 2

This will curve the corner with a radius equal to half the height.

这将使拐角弯曲的半径等于高度的一半。

Run the app, we will have our desired view.

运行该应用程序,我们将获得所需的视图。

Image for post
Final custom CardView with a button slot
带有按钮插槽的最终定制CardView

So our custom Card View is now ready and it looks awesome! We can use it anywhere we want and play around with it to see what more can be done.

因此,我们的自定义Card View现已准备就绪,看起来很棒! 我们可以在任何需要的地方使用它,并尝试使用它,看看还有什么可以做的。

There is so much more to cover, as this is a huge topic but for the time being thank you for following along, I have tried to keep this as informational as possible.

涉及的内容太多,因为这是一个巨大的话题,但是暂时感谢您的关注,我已尽力使此信息尽可能多。

Suggestions to look for further study and enhancement-

寻求进一步研究和改进的建议-

  1. Modify the CardView class to contain open properties that can be used to customize appearance such as — cornerRadius, backgroundColor, buttonSlotHeight, buttonPadding etc.

    修改CardView类以包含可用于自定义外观的开放属性,例如— cornerRadius, backgroundColor, buttonSlotHeight, buttonPadding etc.

  2. Add the CardView programmatically into the view hierarchy as a subview.

    以编程方式将CardView作为子视图添加到视图层次结构中。
  3. For reading references — I found this very informational and helpful — https://developer.apple.com/library/archive/documentation/2DDrawing/Conceptual/DrawingPrintingiOS/BezierPaths/BezierPaths.html

    为了阅读参考资料-我发现这非常有用,也很有帮助-https: //developer.apple.com/library/archive/documentation/2DDrawing/Conceptual/DrawingPrintingiOS/BezierPaths/BezierPaths.html

翻译自: https://medium.com/@ayusinghi96/draw-custom-shapes-and-views-with-uiberzierpath-ios-1737f5cb975

ios path绘制形状

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值