13

How do I take a 1:1 screenshot of UIScrollView visible area? The content may be larger or smaller than UIScrollView bounds as well as half-hidden (I've implemented custom scrolling for smaller content, so it's not in the top-left corner). I've achieved desired result on simulator, but not on device itself:

-(UIImage *)imageFromCombinedContext:(UIView *)background {
      UIImage *image;
      CGRect vis = background.bounds;
      CGSize size = vis.size;
      UIGraphicsBeginImageContext(size);
      [background.layer affineTransform];
      [background.layer renderInontext:UIGraphicsGetCurrentContext()];
      image = UIGraphicsGetImageFromCurrentImageContext();
      UIGraphicsEndImageContext();
      CGImageRef imref = CGImageCreateWithImageInRect([image CGImage], vis);
      image = [UIImage imageWithCGImage:imref];
      CGImageRelease(imref);
      return image;
}
4

8 に答える 8

32

もう 1 つの方法は、 を使用してレイヤの表示領域を調整し、の現在表示されている領域のみcontentOffsetをキャプチャすることです。UIScrollView

UIScrollView *contentScrollView;....//scrollview instance

UIGraphicsBeginImageContextWithOptions(contentScrollView.bounds.size, 
                                       YES, 
                                       [UIScreen mainScreen].scale);

//this is the key
CGPoint offset=contentScrollView.contentOffset;
CGContextTranslateCTM(UIGraphicsGetCurrentContext(), -offset.x, -offset.y); 

[contentScrollView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *visibleScrollViewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

乾杯 :)

于 2013-07-23T20:30:16.697 に答える
6

Abduliam Rehmaniusの回答の迅速なバージョン。

func screenshot() -> UIImage {

        UIGraphicsBeginImageContextWithOptions(self.scrollCrop.bounds.size, true, UIScreen.mainScreen().scale);
        //this is the key
        let offset:CGPoint = self.scrollCrop.contentOffset;
        CGContextTranslateCTM(UIGraphicsGetCurrentContext(), -offset.x, -offset.y);
        self.scrollCrop.layer.renderInContext(UIGraphicsGetCurrentContext()!);
        let visibleScrollViewImage: UIImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return visibleScrollViewImage;
    }

スウィフト 4 バージョン:

func screenshot() -> UIImage {
UIGraphicsBeginImageContextWithOptions(self.scrollCrop.bounds.size, false, UIScreen.main.scale)
        let offset = self.scrollCrop.contentOffset
        let thisContext = UIGraphicsGetCurrentContext()
        thisContext?.translateBy(x: -offset.x, y: -offset.y)
        self.scrollCrop.layer.render(in: thisContext!)
        let visibleScrollViewImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
return visibleScrollViewImage
}
于 2016-03-26T08:33:37.863 に答える
4

私は自分で解決策を見つけました-ビュー全体のスクリーンショットを撮り、それをUIScrollViewフレームのサイズと位置にトリミングしました。

-(UIImage *)imageFromCombinedContext:(UIView *)background 
{
      UIImage *image;
      CGSize size = self.view.frame.size;
      UIGraphicsBeginImageContext(size);
      [background.layer affineTransform];
      [self.view.layer.layer renderInContext:UIGraphicsGetCurrentContext()];
      image = UIGraphicsGetImageFromCurrentImageContext();
      UIGraphicsEndImageContext();
      CGImageRef imgRef = CGImageCreateWithImageInRect([image CGImage],background.frame);
      image = [UIImage imageWithCGImage:imref];
      CGImageRelease(imref);
      return image;
}
于 2012-06-11T09:23:57.197 に答える
3

ジェフリー・サンは正しい答えを持っています。スクロール ビューを別のビュー内に配置するだけです。コンテキストでレンダリングするコンテナー ビューを取得します。終わり。

以下のコードでは、cropView にキャプチャするスクロール ビューが含まれています。解決策は実にシンプルです。

質問とこのページを見つけた理由を理解しているので、スクロールビューのコンテンツ全体は必要ありません-表示されている部分だけです。

func captureCrop() -> UIImage {
    UIGraphicsBeginImageContextWithOptions(self.cropView.frame.size, true, 0.0)
    self.cropView.layer.renderInContext(UIGraphicsGetCurrentContext())
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return image;
}
于 2015-03-09T21:53:56.367 に答える
0

@Abduliam Rehmanius の回答はパフォーマンスが低下します。これUIScrollViewは、大きなコンテンツ領域が含まれている場合、そのコンテンツ領域全体を (目に見える境界の外であっても) 描画するためです。@Concuror の回答には、UIScrollView.

私の解決策は、同じ境界で呼び出されたUIScrollView内部を配置してから、レンダリングすることでした:UIViewcontainerViewcontainerView

containerView.renderInContext(context)
于 2014-10-18T17:39:41.383 に答える