如何使用Swift以编程方式填充带有交替条纹图案的UIView?

use*_*509 9 optimization core-graphics cgcontext ios swift

我可以使用图像实现交替条纹图案填充UIColor(patternImage: UIImage(named: "pattern.png")).

但是,如何通过一些简单的紧凑代码以编程方式实现交替条纹图案填充?

以下是我想要实现的两个例子.

使用代码,如何UIView使用Swift 填充不同的交替颜色条纹?

(1)从上到下(90度)运行的双色交替模式?

(2)从左上到右下(45度)运行的三色交替模式?

在此输入图像描述

gar*_*jon 10

UIColor对于我的应用程序来说,创建可用作背景颜色的图案更有帮助且性能更高。

一旦我将其添加为扩展,UIColor我就可以轻松地将其放置在代码中的任何位置,并且即使视图旋转、缩小和增长,它也将始终完美填充!

你像这样使用它:

view.backgroundColor = UIColor.red.patternStripes()
view.backgroundColor = UIColor.red.patternStripes(color2: .darkGray)
view.backgroundColor = UIColor.red.patternStripes(color2: .darkGray, barThickness: 25.0)
Run Code Online (Sandbox Code Playgroud)

并获得这种美丽:

显示对角条纹图案的正方形

这是 UIColor 的扩展:

extension UIColor {
    
    /// make a diagonal striped pattern
    func patternStripes(color2: UIColor = .white, barThickness t: CGFloat = 25.0) -> UIColor {
        let dim: CGFloat = t * 2.0 * sqrt(2.0)

        let img = UIGraphicsImageRenderer(size: .init(width: dim, height: dim)).image { context in

            // rotate the context and shift up
            context.cgContext.rotate(by: CGFloat.pi / 4.0)
            context.cgContext.translateBy(x: 0.0, y: -2.0 * t)

            let bars: [(UIColor,UIBezierPath)] = [
                (self,  UIBezierPath(rect: .init(x: 0.0, y: 0.0, width: dim * 2.0, height: t))),
                (color2,UIBezierPath(rect: .init(x: 0.0, y: t, width: dim * 2.0, height: t)))
            ]

            bars.forEach {  $0.0.setFill(); $0.1.fill() }
            
            // move down and paint again
            context.cgContext.translateBy(x: 0.0, y: 2.0 * t)
            bars.forEach {  $0.0.setFill(); $0.1.fill() }
        }
        
        return UIColor(patternImage: img)
    }
}
Run Code Online (Sandbox Code Playgroud)

基本上,我正在创建一个临时绘图空间,供一个小矩形进行绘制。我用一种图案来绘制它,重复时该图案将在所有侧面无缝匹配。然后我拍了一张照片并告诉我UIColor将其用作图案。

诀窍是,您必须使图案图像足够大,以便将每个条形绘制两次。结果是条形厚度 * 2 * sqrt(2)。

我知道我可能会因为风格而受到一些打击。这是我的想法:

  1. 我使用了一个字母变量,例如t,这不是很具有描述性。我的辩护:我认为这使得方程更具可读性,并且当它仅限于接下来的几行时感觉还可以。
  2. 元组。与#1相同
  3. 使用小数(4.0而不仅仅是4)。我不想使用小数,但我发现使用小数的编译时间更好。在更大的项目中,它可以产生巨大的影响。我也承认它读起来可能不太漂亮,但对类型的明确性甚至可以对人类有所帮助。

3 种颜色: 我刚刚意识到原来的问题是要求 3 种颜色,所以这里有一个版本......

首先,数学:

在此输入图像描述

更新的代码:

extension UIColor {
    
    /// make a diagonal striped pattern
    func pattern3Stripes(color2: UIColor, color3: UIColor, barThickness t: CGFloat = 25.0) -> UIColor {
        let sqrt2: CGFloat = sqrt(2.0)
        let dim: CGFloat = t * 3.0 * sqrt2
        let size: CGSize = .init(width: dim, height: dim)
        
        let img = UIGraphicsImageRenderer(size: size).image { context in
            
            // rotate the context and shift up
            context.cgContext.rotate(by: CGFloat.pi / 4.0)
            context.cgContext.translateBy(x: 0.0, y: -3.0 * t)
            
            let bars: [(UIColor,UIBezierPath)] = [
                (self,  UIBezierPath(rect: .init(x: 0.0, y: 0.0, width: dim * sqrt2, height: t))),
                (color2,UIBezierPath(rect: .init(x: 0.0, y: t, width: dim * sqrt2, height: t))),
                (color3,UIBezierPath(rect: .init(x: 0.0, y: 2.0 * t, width: dim * sqrt2, height: t)))
            ]
            
            bars.forEach {  $0.0.setFill(); $0.1.fill() }
            
            // move down and paint again
            context.cgContext.translateBy(x: 0.0, y: 3.0 * t)
            bars.forEach {  $0.0.setFill(); $0.1.fill() }
        }
        
        return UIColor(patternImage: img)
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

    view.backgroundColor = UIColor.green.pattern3Stripes(color2: .white, color3: .red, barThickness: 25.0)
Run Code Online (Sandbox Code Playgroud)

结果:

在此输入图像描述


use*_*509 5

使用下面的代码可以实现具有条纹图案的视图填充,条纹图案具有可调节的条带宽度和旋转的两个,三个或更多个颜色条纹.此代码提供了下面示例图像中显示的三色条纹图案.

脚步:

  1. 将以下代码添加到ViewController.swift
  2. 将UIView添加到Storyboard.
  3. 在故事板上为UIView添加新的对齐约束; 在Container = 0中水平,在Container中垂直= 0.
  4. 在Identity Inspector中,将UIView自定义类设置为"colorStripesView".
  5. 将Storyboard上的UIView连接到代码中的viewPattern IBOutlet.

码:

    ////   ViewController.swift

    //// 1. Add the below code to ViewController.swift
    //// 2. Add a UIView to Storyboard.
    //// 3. Add new alignment contstraints to the UIView on the Storyboard; Horizontally in Container = 0, Vertically in Container = 0.
    //// 4. In the Identity Inspector, set the UIView custom class to 'colorStripesView'.
    //// 5. Connect the UIView on the Storyboard to the viewPattern IBOutlet in the code.

    import UIKit

    class ViewController: UIViewController {
        @IBOutlet weak var viewPattern: UIView!

        override func viewDidLoad() {
            super.viewDidLoad()

            //// Extend width and height constraints by factor of 2 for viewPattern rotation.
            let widthConstraint = NSLayoutConstraint(item: viewPattern, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: (max(view.bounds.height, view.bounds.width)*2))
            viewPattern.addConstraint(widthConstraint)
            let heightConstraint = NSLayoutConstraint(item: viewPattern, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: (max(view.bounds.height, view.bounds.width)*2))
            viewPattern.addConstraint(heightConstraint)

            //// Rotate pattern 0 degrees - vertical.
            //viewPattern.transform = CGAffineTransformMakeRotation(CGFloat(M_PI*0/180))
            //// Rotate pattern 45 degrees - diagonal top right to bottom left.
            //viewPattern.transform = CGAffineTransformMakeRotation(CGFloat(M_PI*45/180))
            //// Rotate pattern 90 degrees - horizontal.
            //viewPattern.transform = CGAffineTransformMakeRotation(CGFloat(M_PI*90/180))
            //// Rotate pattern 135 degrees - diagonal top left to bottom right.
            viewPattern.transform = CGAffineTransformMakeRotation(CGFloat(M_PI*135/180))

            //// Set view color
            viewPattern.backgroundColor = UIColor.clearColor()
        }

        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
        }
    }

    class colorStripesView: UIView {
        override func drawRect(rect: CGRect) {
            //// Set pattern tile colors width and height; adjust the color width to adjust pattern.
            let color1 = UIColor(red: 255/255, green: 255/255, blue: 10/255, alpha: 1.0)
            let color1Width: CGFloat = 10
            let color1Height: CGFloat = 10

            let color2 = UIColor(red: 0/255, green: 0/255, blue: 254/255, alpha: 1.0)
            let color2Width: CGFloat = 10
            let color2Height: CGFloat = 10

            let color3 = UIColor(red: 0/255, green: 128/255, blue: 128/255, alpha: 1.0)
            let color3Width: CGFloat = 10
            let color3Height: CGFloat = 10

            //// Set pattern tile orientation vertical.
            let patternWidth: CGFloat = (color1Width + color2Width + color3Width)
            let patternHeight: CGFloat = min(color1Height, color2Height, color3Height)

            //// Set pattern tile size.
            let patternSize = CGSize(width: patternWidth, height: patternHeight)

            //// Draw pattern tile
            let context = UIGraphicsGetCurrentContext()
            UIGraphicsBeginImageContextWithOptions(patternSize, false, 0.0)

            let color1Path = UIBezierPath(rect: CGRect(x: 0, y: 0, width: color1Width, height: color1Height))
            color1.setFill()
            color1Path.fill()

            let color2Path = UIBezierPath(rect: CGRect(x: color1Width, y: 0, width: color2Width, height: color2Height))
            color2.setFill()
            color2Path.fill()

            let color3Path = UIBezierPath(rect: CGRect(x: color1Width + color2Width, y: 0, width: color3Width, height: color3Height))
            color3.setFill()
            color3Path.fill()

            let image = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()

            //// Draw pattern in view
            UIColor(patternImage: image).setFill()
            CGContextFillRect(context, rect)
        }
    }
Run Code Online (Sandbox Code Playgroud)

模拟器:

在此输入图像描述