Exclude View from Screenshot

2019-02-11 01:18发布

This is how I take a screenshot of my view:

UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0)
view.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

However, in the view, there is a UIVisualEffectsView which I'd like to exclude from the screenshot.
I tried hiding the UIVisualEffectsView just before taking the screenshot and un-hiding it afterwards but I don't want the user to see that process. (which he does if I simply hide the view because the iPad is too slow and it looks like the screen is flickering...)

Any ideas? Thanks in advance!

3条回答
【Aperson】
2楼-- · 2019-02-11 01:49

Maybe the simplest solution would be not to include your unwanted view into the hierarchy of the taken as screenshot view. You could simply put it on top of it.

查看更多
我只想做你的唯一
3楼-- · 2019-02-11 01:51

Oh, actually, just following code (swift 4) can work. That is, create a context, and add the item you want in the snapshot. No need to add view in real screen.

Note: currentView is the view which snapshot based on, commonly, it will be view of whole screen. And addViews are the views you want to add.

func takeSnapShot(currentView: UIView , addViews: [UIView], hideViews: [UIView]) -> UIImage {


    for hideView in hideViews {
        hideView.isHidden = true
    }

    UIGraphicsBeginImageContextWithOptions(currentView.frame.size, false, 0.0)

    currentView.drawHierarchy(in: currentView.bounds, afterScreenUpdates: true)
    for addView in addViews{
        addView.drawHierarchy(in: addView.frame, afterScreenUpdates: true)
    }

    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    for hideView in hideViews {
        hideView.isHidden = false
    }

    return image!
}
查看更多
聊天终结者
4楼-- · 2019-02-11 02:03

I would take advantage of the snapshotViewAfterScreenUpdates() method

This method very efficiently captures the current rendered appearance of a view and uses it to build a new snapshot view. You can use the returned view as a visual stand-in for the current view in your app.

Therefore you can use it in order to display an overlay UIView of the complete un-altered view hierarchy to the user while rendering a version of the hierarchy with your changes underneath it.

The only caveat is that if you're capturing a view controller's hierarchy, you'll have to create a 'content view' subview in order to prevent the overlay view from being rendered in your screenshot where you make the changes to the hierarchy. You'll then want to add your view hierarchy that you want to render to this 'content view'.

So your view hierarchy will want to look something like this:

UIView // <- Your view
    overlayView // <- Only present when a screenshot is being taken
    contentView // <- The view that gets rendered in the screenshot
        view(s)ToHide // <- The view(s) that get hidden during the screenshot

Although, if you are able to add the overlayView to the view's superview - instead of to the view itself – you don't need to mess about with the hierarchy at all. For example:

overlayView // <- Only present when a screenshot is being taken
UIView // <- Your view – You can render this in the screenshot
    view(s)ToHide // <- The view(s) that get hidden during the screenshot
    otherViews // <- The rest of your hierarchy

Something like this should achieve the desired result:

// get a snapshot view of your content
let overlayView = contentView.snapshotViewAfterScreenUpdates(true)

// add it over your view
view.addSubview(overlayView)

// do changes to the view heirarchy
viewToHide.hidden = true

// begin image context
UIGraphicsBeginImageContextWithOptions(contentView.frame.size, false, 0.0)

// render heirarchy
contentView.drawViewHierarchyInRect(contentView.bounds, afterScreenUpdates: true)

// get image and end context
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

// reverse changes to the view heirarchy
viewToHide.hidden = false

// remove the overlay view
overlayView.removeFromSuperview()
查看更多
登录 后发表回答