正确掩码UIView(UICollectionView)

时间:2017-05-12 19:18:12

标签: ios swift svg uikit uibezierpath

好的,我需要屏蔽水平UICollectionView所以它看起来像一个色带。我的web开发人员用一个他用作屏蔽层的SVG完成了它。

以下是我目前的情况:enter image description here

这就是我需要的东西(来自我们的网络应用程序的照片):enter image description here

除了图像间距的细节之外,我有一个像这样的SVG: enter image description here

我可以成功转换为UIBezierPath代码(Paintcode):

let pathPath = UIBezierPath()
pathPath.move(to: CGPoint(x: 0.05, y: 0))
pathPath.addCurve(to: CGPoint(x: 162.02, y: 3.8), controlPoint1: CGPoint(x: 0.05, y: 2.1), controlPoint2: CGPoint(x: 72.57, y: 3.8))
pathPath.addCurve(to: CGPoint(x: 324, y: 0), controlPoint1: CGPoint(x: 251.48, y: 3.8), controlPoint2: CGPoint(x: 324, y: 2.1))
pathPath.addLine(to: CGPoint(x: 324, y: 150.2))
pathPath.addCurve(to: CGPoint(x: 162.02, y: 154), controlPoint1: CGPoint(x: 324, y: 152.3), controlPoint2: CGPoint(x: 251.48, y: 154))
pathPath.addCurve(to: CGPoint(x: 0.05, y: 150.2), controlPoint1: CGPoint(x: 72.57, y: 154), controlPoint2: CGPoint(x: 0.05, y: 152.3))
pathPath.addCurve(to: CGPoint(x: 0, y: 0.17), controlPoint1: CGPoint(x: 0.05, y: 148.1), controlPoint2: CGPoint(x: 0, y: 0.17))
pathPath.usesEvenOddFillRule = true
UIColor.lightGray.setFill()
pathPath.fill()

现在该怎么办?

2 个答案:

答案 0 :(得分:1)

您应该使用UICollectionView的mask属性,方法是将其设置为一个视图,其alpha通道指示要屏蔽的UICollectionView的哪个部分。概括起来,它可能类似于:

// If you don't have a custom subclass of UICollectionView... you can handle the resize in the
// UICollectionViewController or whatever view contoller is handling your view.
//
// If you do have a custom subclass of UICollectionView... you could do something similar 
// in layoutSubviews.

class MyViewController : UICollectionViewController {

    // recreate the mask after the view lays out it's subviews
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

        if let maskImage = createMaskingImage(size: self.view.bounds.size) {
            let maskView = UIView(frame: self.view.bounds)
            maskView.layer.contents = maskImage

            self.view.mask = maskView
        }
    }
}

// create a masking image for a view of the given size
func createMaskingImage(size: CGSize) -> UIImage? {

    let drawingBounds = CGRect(origin: CGPoint.zero, size: size)

    UIGraphicsBeginImageContext(size)

    // We're going to jump down to the level of cgContext for scaling
    // You might be able to do this from the level of UIGraphics, but I don't know how so...
    // Implicitly unwrapped optional, but if we can't get a CGContext we're in trouble

    let cgContext = UIGraphicsGetCurrentContext()!
    let maskingPath = createMaskingPath()
    let pathBounds = maskingPath.bounds;

    cgContext.saveGState()

    // Clearing the image may not strictly be necessary
    cgContext.clear(drawingBounds)

    // Scale the context so that when we draw the path it fits in the drawing bounds
    // Could just use "size" here instead of drawingBounds.size, but I think this makes it a 
    // little more explicit that we're matching up two rects
    cgContext.scaleBy(x: drawingBounds.size.width / pathBounds.size.width,
                      y: drawingBounds.size.height / pathBounds.size.height)
    cgContext.setFillColor(UIColor.lightGray.cgColor)
    cgContext.addPath(maskingPath.cgPath)
    cgContext.fillPath(using: .evenOdd)

    cgContext.restoreGState()

    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return image
}

func createMaskingPath() -> UIBezierPath {
    let path = UIBezierPath()

    path.move(to: CGPoint(x: 0.05, y: 0))
    path.addCurve(to: CGPoint(x: 162.02, y: 3.8), controlPoint1: CGPoint(x: 0.05, y: 2.1), controlPoint2: CGPoint(x: 72.57, y: 3.8))
    path.addCurve(to: CGPoint(x: 324, y: 0), controlPoint1: CGPoint(x: 251.48, y: 3.8), controlPoint2: CGPoint(x: 324, y: 2.1))
    path.addLine(to: CGPoint(x: 324, y: 150.2))
    path.addCurve(to: CGPoint(x: 162.02, y: 154), controlPoint1: CGPoint(x: 324, y: 152.3), controlPoint2: CGPoint(x: 251.48, y: 154))
    path.addCurve(to: CGPoint(x: 0.05, y: 150.2), controlPoint1: CGPoint(x: 72.57, y: 154), controlPoint2: CGPoint(x: 0.05, y: 152.3))
    path.addCurve(to: CGPoint(x: 0, y: 0.17), controlPoint1: CGPoint(x: 0.05, y: 148.1), controlPoint2: CGPoint(x: 0, y: 0.17))

    return path
}

答案 1 :(得分:1)

/*
This is a UICollectionView, which clips normally on the left and right,
but allows some extra space horizontally.
A typical example is you need to clip the scrolling items but you
still need to allow shadows.
*/

import Foundation
import UIKit

class CustomClipCollectionView: UICollectionView {

    private lazy var extraSpaceOnBaseButStillClipSidesNormally: CALayer = {
        let l = CALayer()
        l.backgroundColor = UIColor.black.cgColor
        return l
    }()

    override func layoutSubviews() {
        extraSpaceOnBaseButStillClipSidesNormally.frame = bounds.insetBy(
                          dx: 0, dy: -10)
        layer.mask = extraSpaceOnBaseButStillClipSidesNormally
        super.layoutSubviews()
    }
}