Captura de pantalla de iOS (registro de aprendizaje)

Prefacio

Captura de pantalla larga: es decir, puede tomar una imagen larga que exceda la pantalla. Antes de implementar imágenes largas, primero debemos comprender el funcionamiento de dibujar capturas de pantalla normales en iOS. Sobre esta base se implementan capturas de pantalla largas.

iOS: dibujar capturas de pantalla

 UIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale);
 [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
 UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
 UIGraphicsEndImageContext();
  • UIGraphicsBeginImageContextWithOptions Esta función comienza a crear un contexto de imagen, que tiene tres parámetros:
    size: El tamaño de la imagen que se va a representar
    opaque: si el fondo de la imagen que se va a crear es opaco. SÍ el fondo es negro, NO el fondo es transparente.
    scale: La relación de escala de la imagen que se va a crear. Si se establece en 0, [UIScreen mainScreen].scaleel efecto será el mismo a medida que cambie la resolución de la pantalla del teléfono móvil.
  • Método de llamada renderInContext: renderice la capa de la vista en el contexto de dibujo actual. (Representa la capa y sus subcapas en el contexto especificado).
  • UIGraphicsGetImageFromCurrentImageContext: Devuelve una imagen basada en el contexto del mapa de bits actual.
  • UIGraphicsEndImageContext: Elimina el contexto de gráficos actual basado en mapa de bits de la parte superior de la pila.

Lo anterior es el código de captura de pantalla para iOS. Pero para WKwebVIew (imagen larga), este código no puede capturar la imagen completa. Debido a que WKwebView considera problemas de rendimiento, no cargará lugares que no sean visibles para el usuario, por lo que la captura de pantalla estará incompleta.

WKWebView captura de pantalla larga

Ideas

Primero hablemos de la idea, que también la resumí consultando muchos métodos de implementación en Internet. Podemos ver WKWebViewque hay subvistas en él WKScrollView. Luego podemos cargar el contenido arrastrando ScrollView y capturar la imagen al mismo tiempo. Cuando se arrastra ScrollView hasta el final, todas las capturas de pantalla se pueden unir.

PD: El problema ocurrirá cuando la página tenga una barra flotante. La barra flotante aparecerá en cada captura de pantalla. Por el momento, no se me ocurre una forma de solucionar este problema, pero la idea es cargar todo WKwebVIew y luego tomar una captura de pantalla.

lograr

método externo

/// 对WKWebView进行长截图(没有规避H5悬浮栏)
/// @param webView 需要进行截图的webView
/// @param completionHandler 截图完成回调
 - (void)snapshotForWKWebView:(WKWebView *)webView CaptureCompletionHandler:(void (^)(UIImage * _Nonnull))completionHandler {
    
    
    //1.添加遮罩层
    UIView *snapshotView = [webView snapshotViewAfterScreenUpdates:YES];
    snapshotView.frame = webView.frame;
    [webView.superview addSubview:snapshotView];
    //2.初始化数组
    self.imgArr = [NSMutableArray array];
    //3.进行截图操作
    CGPoint savedCurrentContentOffset = webView.scrollView.contentOffset;
    webView.scrollView.contentOffset = CGPointZero;
    [self createSnapshotForWKWebView:webView offset:0.0 remainingOffset_y:webView.scrollView.contentSize.height comletionBlock:^(UIImage *snapshotImg) {
    
    
        webView.scrollView.contentOffset = savedCurrentContentOffset;
        [snapshotView removeFromSuperview];
        completionHandler(snapshotImg);
    }];
}
  1. Para evitar que los usuarios vean nuestra operación de desplazamiento de captura de pantalla, aquí utilizamos snapshotViewAfterScreenUpdates un método para cubrir la captura de pantalla.
  2. Inicialice imgArrla matriz y luego úsela para almacenar cada parte de la captura de pantalla.
  3. Guarde la WKScrollView.contentOffsetescena actual para que pueda restaurar la "escena del crimen" una vez completada la operación de captura de pantalla.
  4. Configúrelo WKScrollView.contentOffseten CGPointZero y llame al método de captura de pantalla para comenzar a tomar capturas de pantalla.

Cómo tomar capturas de pantalla

/// 绘制WKWebView长截图
/// @param webView 所需要截图的WebView
/// @param offset_y 当前scollView的y偏移量
/// @param reOffset_y 剩余scollView的y偏移量
/// @param completeBlock 回调块
- (void)createSnapshotForWKWebView:(WKWebView *)webView offset:(float)offset_y remainingOffset_y:(float)reOffset_y comletionBlock:(void(^)(UIImage *snapshotImg))completeBlock
{
    
    
    //判断scrollView是否已经滚动到底
    if (reOffset_y>0) {
    
    
        //设置
        [webView.scrollView setContentOffset:CGPointMake(0, offset_y) animated:NO];
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(),^{
    
    
            //对页面进行截图操作
            UIGraphicsBeginImageContextWithOptions(webView.frame.size, YES, [UIScreen mainScreen].scale);
            [webView.layer renderInContext:UIGraphicsGetCurrentContext()];
            UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
            //将截图添加进数组
            [self.imgArr addObject:img];
            //修改offsetY偏移量
            CGFloat newOffset_y = offset_y + webView.scrollView.frame.size.height;
            CGFloat newReOffset_y = reOffset_y - webView.frame.size.height;
            [self createSnapshotForWKWebView:webView offset:newOffset_y remainingOffset_y:newReOffset_y comletionBlock:completeBlock];
            
        });
    }else {
    
    
        //合成截图为最终截图
        UIView * containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, webView.frame.size.width, webView.scrollView.contentSize.height)];
        CGFloat originYOfImgView = 0;
        for (int i = 0; i<self.imgArr.count; i++) {
    
    
            UIImageView * imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, originYOfImgView, webView.frame.size.width, webView.frame.size.height)];
            UIImage * img = self.imgArr[i];
            imgView.image = img;
            originYOfImgView += webView.frame.size.height;
            [containerView addSubview:imgView];
        }
        //添加合成视图
        [webView.superview addSubview:containerView];
        //处理最终合并截图
        UIGraphicsBeginImageContextWithOptions(containerView.frame.size, YES, [UIScreen mainScreen].scale);
        [containerView.layer renderInContext:UIGraphicsGetCurrentContext()];
        UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        //移除合成视图
        [containerView removeFromSuperview];
        //返回截图
        if (completeBlock) {
    
    
            completeBlock(img);
        }
    }
}

  1. Determine scrollViewsi el desplazamiento actual ha llegado al final.
  2. Si no se desplaza hasta el final, configúrelo scrollView.contentOffsetnuevamente en la página siguiente para tomar una captura de pantalla.
  3. Agregue un retraso a la captura de pantalla aquí para asegurarse de que la página esté completamente cargada. Las imágenes capturadas se colocarán en la matriz.
  4. Si scrollViewha llegado al final, utilice una vista de contenedor para unir y mostrar todas las capturas de pantalla.
  5. Finalmente, tome una captura de pantalla de la vista del contenedor para obtener una WKWebViewcaptura de pantalla completa de la página.

Fin

Todavía hay algunos problemas con este método. Si alguien sabe cómo resolver el problema de la barra flotante interceptada varias veces, por favor responda ~

おすすめ

転載: blog.csdn.net/qq_38863196/article/details/126361878