Can you limit UIView Clip Subviews to certain sides of a view?
Asked Answered
N

4

8

I have a UIScrollView that contains other subviews that are partially drawn outside of the scrollview. These views extend vertically above the scrollview. Is it possible to only allow the subviews to be drawn outside the top of the scrollview, and not allow them drawn outside of the left and right sides of the scrollview?

What is happening, is that when I manually scroll left and right, the subviews are being drawn outside of the scrollview because of the content size. Once the subview's are scroll outside of the scrollview's frame, I want to clip the subviews.

Any suggestions or is this possible?

Nero answered 9/2, 2014 at 23:16 Comment(0)
B
13

I've managed to achieve this effect by using the layer's mask property and a CALayer. The following snippet clips only views from the top and the left side of a view:

let maskLayer = CALayer()
maskLayer.backgroundColor = UIColor.black.cgColor
maskLayer.frame = CGRect(x: 0, y: 0, width: 2000, height: 2000)
aView.layer.mask = maskLayer

Note that I'm using the arbitrary number 2000 as the far right and lower bounds for clipping, so you'll need to adjust the number depending on how far you want your other views to clip.

Beget answered 2/12, 2015 at 1:13 Comment(3)
What would be the frame, if you want to clip top-bottom, but not left-right ?Guardant
@RoNiT you need to keep the edges of the rect you want to clip against the edges of the view you will be adding the mask to, so try CGRectMake(-2000, 0, 2000, aView.bounds.height)Beget
just use the handy ".inset" command here, to modify the current frameNaumann
N
2

Limit clip to certain sides of a view:

It's common to do this on table or collection views for example:

/*
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()
    }
}

Note! You turn off the normal "clip to bounds" feature, when using this. The ".mask" system for clipping is different and separate from the "clip to bounds" system.

Naumann answered 28/8, 2019 at 13:18 Comment(0)
V
0

You can't specify individual sides you'd like to clip, but you could basically fake this by placing a new UIView alongside the edge you wanted to clip (and so effectively clipping it). Alternatively you could think about ways to change your view hierarchy so that you don't have to clip subviews at all (perhaps by adjusting the scroll view's bounds and layout in some way).

Vibes answered 9/2, 2014 at 23:20 Comment(2)
I do have a UIView alongside the edge. Both that view and the scrollview both have .7 alpha levels, so that trick won't work unfortunately.Nero
You can't specify individual sides you'd like to clip - you very easily can, you just set the mask.Naumann
A
0

Here's how I implemented Max Chuquimia's nice solution in Objective-C:

CALayer* maskLayer = [CALayer layer];
maskLayer.backgroundColor = [UIColor blackColor].CGColor;
maskLayer.frame = CGRectMake(0,-100,
                            parentView.frame.size.width, parentView.frame.size.height + 100);
parentView.layer.mask = maskLayer;

Any part of the parent view or its children which is not covered by black pixels in the mask will be clipped.

In this snippet, we clip left and right, but leave 100 points on top and below the parent view for children to overflow. (the mask is bigger than the parent view)

Ammonify answered 31/5, 2018 at 14:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.