是否可以从其父视图的边界取消展开单个子视图?

时间:2019-11-07 20:29:32

标签: ios swift uiview uikit clipstobounds

我遇到一种情况,我希望将单个子视图裁剪到其父视图的边界,而将其余子视图 裁剪到其子视图的边界。有没有一种方法可以将某个UIView排除在其超级视图的范围之外。同样,UIView是否可以指定它不想/不希望裁剪到其自己范围的子视图?

就代码而言,我正在使用Koloda创建与Tinder的刷卡类似的UIView。我有一个集合视图,其单元本质上是Koloda视图。每当卡片开始平移时,我都会将其单元格的集合视图的clipsToBounds属性设置为false。这样可以将单元格平移到导航栏上方,而不会被剪切。平移结束后,视图单元格的集合视图的clipsToBounds属性将重新设置为true

import UIKit
import Koloda

class LikedUserCollectionViewCell: UICollectionViewCell {
    @IBOutlet var swipeView: KolodaView!
    var parentVC: MyViewController!
}

extension LikedUserCollectionViewCell: KolodaViewDelegate, KolodaViewDataSource {
    func koloda(_ koloda: KolodaView, viewForCardAt index: Int) -> UIView {
        //return a KolodaView, this code isn't important to the issue
        return KolodaView()
    }

    func kolodaNumberOfCards(_ koloda: KolodaView) -> Int {
        return 1
    }

    func kolodaPanBegan(_ koloda: KolodaView, card: DraggableCardView) {
        self.parentVC.collectionView.bringSubviewToFront(self)
        //Here, instead of unclipping all of the collection view's subviews, I would like to only unclip the one containing the subview that is being panned
        self.parentVC.collectionView.clipsToBounds = false
    }

    func kolodaPanFinished(_ koloda: KolodaView, card: DraggableCardView) {
        //Once the pan is finished, all of the collection view's subviews can be clipped again
        self.parentVC.collectionView.clipsToBounds = true
    }

    func koloda(_ koloda: KolodaView, didSwipeCardAt index: Int, in direction: SwipeResultDirection) {
        //Not relevant to the question
    }
}

问题是,当某些单元格已部分滚动到集合视图之外,但是由于尚未完全滚动到集合视图之外而尚未从集合视图中移除时,它们现在变为集合视图的{{1 }}现在设置为clipsToBounds。这就是为什么我希望能够指示哪个集合视图的子视图被限制到其边界。可以在以下gif中看到此行为:

enter image description here

因此,总而言之,有没有一种方法,而不是通过true从其父视图的边界上取消所有子视图的工作,我只能从其父视图的边界上取消一个子视图的工作? < / p>

2 个答案:

答案 0 :(得分:1)

这里的简单解决方案是,由于您要为单个视图设置例外,因此请不要移动collectionView单元格。拍摄snapshotView并移动快照;它可以在层次结构中的任何其他位置,并且不必是集合视图的子级。您可以使用UIView.convert(from:)将像元坐标转换为适当的父视图的坐标空间,以正确放置快照。

从OP编辑:

我能够通过接受乔什的建议并将代码更新为以下内容来解决我的问题:

import UIKit
import Koloda

class LikedUserCollectionViewCell: UICollectionViewCell {
    @IBOutlet var swipeView: KolodaView!
    var parentVC: MyViewController!
    //DraggableCardView is a custom Koloda class
    var draggableCardView: DraggableCardView!
}

extension LikedUserCollectionViewCell: KolodaViewDelegate, KolodaViewDataSource {
    func koloda(_ koloda: KolodaView, viewForCardAt index: Int) -> UIView {
        //return a KolodaView, this code isn't important to the issue
        return KolodaView()
    }

    func kolodaNumberOfCards(_ koloda: KolodaView) -> Int {
        return 1
    }

    func kolodaPanBegan(_ koloda: KolodaView, card: DraggableCardView) {
        let snapshotView = self.swipeView.snapshotView(afterScreenUpdates: false)!
        snapshotView.accessibilityIdentifier = "snapshotView"
        self.parentVC.view.addSubview(snapshotView)
        snapshotView.frame.origin = self.parentVC.view.convert(swipeView.viewForCard(at: 0)!.frame.origin, from: swipeView)
        draggableCardView = card
        swipeView.viewForCard(at: 0)?.isHidden = true
    }

    func koloda(_ koloda: KolodaView, draggedCardWithPercentage finishPercentage: CGFloat, in direction: SwipeResultDirection) {
        let snapshotView = self.parentVC.view.subviews.first(where: { $0.accessibilityIdentifier == "snapshotView" })!
        snapshotView.frame.origin = self.parentVC.view.convert(draggableCardView.frame.origin, from: swipeView)
    }

    func kolodaPanFinished(_ koloda: KolodaView, card: DraggableCardView) {
        let snapshotView = self.parentVC.view.subviews.first(where: { $0.accessibilityIdentifier == "snapshotView" })!
        draggableCardView = nil
        snapshotView.removeFromSuperview()
        swipeView.viewForCard(at: 0)?.isHidden = false
    }

    func koloda(_ koloda: KolodaView, didSwipeCardAt index: Int, in direction: SwipeResultDirection) {
        //Not relevant to the question
    }
}

答案 1 :(得分:0)

看看您的界面,为什么collectionView在(导航栏)上方?

在这种情况下,只要collectionView在导航栏后面,就不需要任何剪辑。

调用 sendSubview(toBack:collectionView)或将collectionView.layer.zPosition设置为更大的值。