【发布时间】:2015-08-08 22:00:13
【问题描述】:
我正在创建一个图像拼贴应用程序。我将拥有多个UIScrollView。滚动视图将具有自定义形状的边界,用户将能够动态更改它们相交的形状的角。滚动视图有 UIImageView 的子视图。
滚动视图是其他 UIView 的子视图。我对每个UIView 应用了CAShapeLayer 掩码。这样我就可以毫无问题地屏蔽滚动视图。
但问题是,我只能滚动最后添加的滚动视图的内容。此外,我可以平移和缩放蒙版的边界。当我触摸作为蒙版的多边形边界内时,我应该只能平移或缩放。
我试过了;
scrollView.clipsToBounds = true
scrollView.layer.masksToBounds = true
但结果是一样的。
很遗憾,我无法发布屏幕截图,但这里是我用来为 UIView 创建掩码的代码:
func createMask(v: UIView, viewsToMask: [UIView], anchorPoint: CGPoint)
{
let frame = v.bounds
var shapeLayer = [CAShapeLayer]()
var path = [CGMutablePathRef]()
for i in 0...3 {
path.append(CGPathCreateMutable())
shapeLayer.append(CAShapeLayer())
}
//define frame constants
let center = CGPointMake(frame.origin.x + frame.size.width / 2, frame.origin.y + frame.size.height / 2)
let bottomLeft = CGPointMake(frame.origin.x, frame.origin.y + frame.size.height)
let bottomRight = CGPointMake(frame.origin.x + frame.size.width, frame.origin.y + frame.size.height)
switch frameType {
case 1:
// First view for Frame Type 1
CGPathMoveToPoint(path[0], nil, 0, 0)
CGPathAddLineToPoint(path[0], nil, bottomLeft.x, bottomLeft.y)
CGPathAddLineToPoint(path[0], nil, anchorPoint.x, bottomLeft.y)
CGPathAddLineToPoint(path[0], nil, anchorPoint.x, anchorPoint.y)
CGPathCloseSubpath(path[0])
// Second view for Frame Type 1
CGPathMoveToPoint(path[1], nil, anchorPoint.x, anchorPoint.y)
CGPathAddLineToPoint(path[1], nil, anchorPoint.x, bottomLeft.y)
CGPathAddLineToPoint(path[1], nil, bottomRight.x, bottomRight.y)
CGPathAddLineToPoint(path[1], nil, bottomRight.x, anchorPoint.y)
CGPathCloseSubpath(path[1])
// Third view for Frame Type 1
CGPathMoveToPoint(path[2], nil, 0, 0)
CGPathAddLineToPoint(path[2], nil, anchorPoint.x, anchorPoint.y)
CGPathAddLineToPoint(path[2], nil, bottomRight.x, anchorPoint.y)
CGPathAddLineToPoint(path[2], nil, bottomRight.x, 0)
CGPathCloseSubpath(path[2])
default:
break
}
for (key, view) in enumerate(viewsToMask) {
shapeLayer[key].path = path[key]
view.layer.mask = shapeLayer[key]
}
}
那么,我怎样才能使滚动视图的行为方式使得它们只会在触摸发生在其相应的蒙版边界内时滚动或缩放内容?
编辑:
根据这个问题的答案:UIView's masked-off area still touchable? 面具只修改你能看到的,而不是你能触摸到的区域。所以我将 UIScrollView 子类化并尝试像这样覆盖hitTest:withEvent: 方法,
protocol CoolScrollViewDelegate: class {
var scrollViewPaths: [CGMutablePathRef] { get set }
}
class CoolScrollView: UIScrollView
{
weak var coolDelegate: CoolScrollViewDelegate?
override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView?
{
if CGPathContainsPoint(coolDelegate?.scrollViewPaths[tag], nil, point, true) {
return self
} else {
return nil
}
}
}
但是通过这个实现,我只能在放大时检查最后一个滚动视图和路径边界的变化。例如,如果我放大图像,hitTest:withEvent: 方法返回 nil。
【问题讨论】:
-
你能改变滚动视图的形状以匹配自定义形状吗?
-
你的意思是我将掩码应用于滚动视图而不是它们的超级视图?如果我这样做,它会导致滚动视图的内容在我滚动时重叠,并且还会在内容中添加空格。
标签: swift uiscrollview mask cashapelayer