洞察探讨小游戏SDK接入的最佳实践以及对企业跨平台开发的优势
1186
2022-09-10
Swift 3.0 iOS 如何绘制 1px 宽的描边
自定义 UIView 绘制 1px 边框描边
我也是初学者,在研究如何制作 1px 的圆角矩形边框时整了半天,也查了半天,终于整出来了,分享下给新手们。 推荐教程 斯坦福大学 和 iOS 10 swift 教程 ,可以直接在 iTunes U 中-,国内-的话,需要代理才会快, 不然特别慢 每个视频在 1.2G左右 90分钟( 这个讲的特别系统
1, 原理 pt 与 px
苹果手机的原始尺寸是 375 x 667, 也是最初手机的屏幕尺寸,后来的手机都是以这个为原始值缩放的。 比如 iphone 6/7 屏幕是 750 x 1334 正好是这个长宽的 2 倍 iPhone 6/7 和 iPhone 6/7 Plus 都是它的 3倍 在 UI 中,我们是以 pt (point 即 点) 为单位的,要获取当前手机 1pt 是多少 px 用下面的方法获得
1pt = 1px ( iPhone 5s 之前 )1pt = 2px ( iPhone 6/7 )1pt = 3px ( iPhone 6/7 Plus )
let screenScale = UIScreen.main.scale// 如上所说 iPhone 6/7 上该值是 2.0
知道了这个之后,我们就可以计算出1px 在屏幕上所占的距离是多少,也就是
let 1pxWidth = 1 / UIScreen.main.scale
2,自定义 UIView 圆角矩形+描边
下面是基础知识了,不知道的可以再百度搜搜别的教程,这里只是讲1px的事,我只注释一些地方 这里假设你已经知道如何自己绘制东西了
// 因为我们要做一个能在 `StoryBoard` 中使用的 `UIView`var radius: CGFloat = 10 // 圆角var lineWidth: CGFloat = 1 // 描边宽度var lineColor: UIColor = UIColor.orange // 描边颜色var fillColor: UIColor = UIColor.white // 填充颜色let contentRect = self.bounds //绘制圆角矩形的「面板」大小let path = UIBezierPath(roundedRect: contentRect, cornerRadius: radius) //创建圆角矩形路径path.lineWidth = lineWidth //设置描边颜色lineColor.setStroke() //设置描边颜色fillColor.setFill() //设置填充颜色path.fill() //填充path.stroke() //描边
这样得出的结果是这样的,有没有发现有点问题,继续看下面
3,解决描边问题
其实代码都是对的,只是描边的时候它会以路径为中心向两边描边,如图: 黑线是 Bounds, 它只会显示Bounds 内的东西。所以描边被裁掉了外面的问题
那么如何解决呢? 答案: 在绘制的时候定义 圆角矩形的绘制边界小于现在的 Bounds
let contentRect = self.boundslet path = UIBezierPath(roundedRect: contentRect, cornerRadius: radius) // 也就是定义 该方法中的参数 roundedRect 小一些// 幸运的是 CGRect 里有一个方法可以实现向内部偏移 insetBy(dx: CGFloat, dy: CGFloat)// 左右收缩 dx 大小, 上下收缩 dy 大小let contentRect = self.bounds.insetBy(dx: lineWidth/2, dy: lineWidth/2)// 如上,向内收缩描边的一半大小,这样可以在占满两个 Bounds 的同时描边正常。
现在是这样的: (黑边只是为了标明 Bounds,那个是没有的,不要在意)
4, 背景问题
是不是感觉到这了就没什么问题了? 其实还是有问题的,在使用中就会发现 问题是这样的: 如果你在一个非纯白背景中使用这个自定义的 UIView,你就会发现会出现下面这样的情况
我们设置了自己的 填充色 和 描边色, 那么为什么四角还是白色的呢? 其实我们还需要设置一个地方,就是设置初始背景色是透明,然后再在上面绘制东西 也就是 UIColor.clear //透明色
这个需要写在 init() 方法中 说几点先: 因为我们是自定义的 UIView 我们需要重写 init(frame: CGRect) 和 init(coder: NSCoder) 两个方法,我们的背景设置就写在这两个方法中。
override init(frame: CGRect) { super.init(frame: frame) self.backgroundColor = UIColor.clear // 设置背景透明}required init?(coder: NSCoder) { // 注意,这个init 方法是 required 而且是 Optional 值 super.init(coder: coder) self.backgroundColor = UIColor.clear // 设置背景透明}
然后我们得到我们需要的结果了
总结:完整代码
说了这么多希望你能有自己思路了,现在可以在 StoryBoard 中嵌套这个 UIView 得到你想要的结果了。 这里还说一下,现在这个代码是可以在 StoryBoard 中设置参数的, 如果不了解,百度 @IBDesinable
效果如图
import UIKit@IBDesignable // 让该UIView 可以显示在 StoryBoard 中class RoundedRectView: UIView { // MARK: - 设置参数 @IBInspectable // 该关键字让该参数可以显示在 StoryBoard 的右边设置面板中 var radius: CGFloat = 10 { didSet{ setNeedsDisplay() } } @IBInspectable var lineWidth: CGFloat = 1 / UIScreen.main.scale { //初始值也设为 1px didSet{ lineWidth = lineWidth / UIScreen.main.scale setNeedsDisplay() // 我们如果想调用 Draw() 方法的时候使用这个方法,!!!不能直接调用draw()方法!!! } } @IBInspectable var lineColor: UIColor = UIColor.lightGray { didSet{ setNeedsDisplay() } } @IBInspectable var fillColor: UIColor = UIColor.white { didSet{ setNeedsDisplay() } } //MARK: - Draw() override func draw(_ rect: CGRect) { let contentRect = self.bounds.insetBy(dx: lineWidth/2, dy: lineWidth/2) let path = UIBezierPath(roundedRect: contentRect, cornerRadius: radius) path.lineWidth = lineWidth lineColor.setStroke() fillColor.setFill() path.fill() path.stroke() } override init(frame: CGRect) { super.init(frame: frame) self.backgroundColor = UIColor.clear } required init?(coder: NSCoder) { super.init(coder: coder) self.backgroundColor = UIColor.clear }}
使用效果图: 1px 描边
其它用处
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~