美文网首页
RN 中截屏react-native-view-shot

RN 中截屏react-native-view-shot

作者: liluo风 | 来源:发表于2018-11-27 16:13 被阅读0次

应用场景:

对应用中的某一个界面进行截屏并保存(Android 和 IOS)

(特殊情况是对该截屏进行图片拼接,本实例中拼接的资源图片是本地图片,拼接图片仅针对Android端)

1、导入截图、文件存储库文件
import { captureScreen, captureRef } from 'react-native-view-shot';
import RNFS from 'react-native-fs';
import RNFetchBlob from 'rn-fetch-blob';
2、在构造函数中创建
this.mainViewRef = React.createRef();
3、在render()中的控件中
 <View style={styles.containerView} ref={this.mainViewRef}>
</View>
4、截屏的方法
 async shareScreenShot() {
    const { makingImage } = this.state;
    if (makingImage) return;

    this.setState({ makingImage: true }, async () => {
      try {
        const captureConfig = {
          format: 'png',
          quality: 0.7,
          // result: Platform.OS==='ios'? 'data-uri':'base64',
          // result: 'tmpfile',
          result: 'base64',
          width: 750,
        };
        let imgBase64 = '';
        try {
          imgBase64 = await captureScreen(captureConfig);
        } catch (e) {
          try {
            imgBase64 = await captureRef(this.mainViewRef.current, captureConfig);
          } catch (ex) {
            throw ex;
          }
        }
        this.imgBase64 = imgBase64;
        this.setState({ showTitle: true });
        const screenShotShowImg = `data:image/png;base64,${this.imgBase64}`;
        //FIXME screenShotShowImg可直接在Image中展示
        // console.log('this.screenShotShowImg====', this.screenShotShowImg);
        this.saveImage(screenShotShowImg);
      } catch (e) {
        Alert.alert(`截图失败,请稍后再试${e.toString()}`);
        console.log(e);
      } finally {
        this.setState({ makingImage: false });
      }
    });
  }
5、保存该截图(base64格式的图片)
  async saveImage(screenShotShowImg) {
      Toast.showShortCenter('图片保存中...');
      if (IS_IOS) {
        CameraRoll.saveToCameraRoll(screenShotShowImg).then((result) => {
          Toast.showShortCenter(`保存成功!地址如下:\n${result}`);
        }).catch((error) => {
          Toast.showShortCenter(`保存失败!\n${error}`);
        });
      } else {
      //调用该方法是 对 截屏的图片进行拼接,仅限Android端拼接,IOS的我不会,切此处的base64Img是未进行拼接‘data:image/png;base64’字段的base64图片格式
      // await NativeModules.UtilsModule.contactImage(base64Img).then((newImg) => {
      //   // console.log('path====', newImg);
      //   const screenShotShowImg = `data:image/png;base64,${newImg}`;
      //
      // }, (ex) => {
      //   console.log('ex====', ex);
      // });
        //不经过拼接直接保存到相册
        this.saveForAndroid(screenShotShowImg, (result) => {
          Toast.showShortCenter(`保存成功!地址如下:\n${result}`);
        }, () => {
          Toast.showShortCenter('保存失败!');
        });
      }
      
    }

  saveForAndroid(base64Img, success, fail) {
    const dirs = RNFS.ExternalDirectoryPath; // 外部文件,共享目录的绝对路径(仅限android)
    const downloadDest = `${dirs}/${((Math.random() * 10000000) || 0)}.png`;
    const imageDatas = base64Img.split('data:image/png;base64,');
    const imageData = imageDatas[1];
    RNFetchBlob.fs.writeFile(downloadDest, imageData, 'base64').then((result) => {
      console.log('result=====', result);
      try {
        CameraRoll.saveToCameraRoll(downloadDest).then((e1) => {
          console.log('success', e1);
          success && success(e1);
        }).catch((e2) => {
          console.log('failed', e2);
          Alert.alert('没有读写权限。请在[设置]-[应用权限]-[XX应用]开启');
        });
      } catch (e3) {
        console.log('catch', e3);
        fail && fail();
      }
    });
  }

6、Android原生的图片拼接调用

         /**
         * 拼接图片
         * @param base64Img
         * @param promise
         */
        @ReactMethod
        public void contactImage(String base64Img,Promise promise){
            try {
    
                ImageUtils imageUtils = new ImageUtils(getReactApplicationContext());
                //拼接图片后转化成文件存储
                String path = imageUtils.processImage(base64Img);
                //将拼接后的图片转化成Bitmap
                Bitmap bitmap = imageUtils.decodeUriAsBitmap(path);
                //将Bitmap文件转化成Base64格式
                String newBase64Img = imageUtils.bitmapToBase64(bitmap);
                promise.resolve(newBase64Img);
            }catch (Exception e){
                promise.reject(e);
            }
        }

7、Android原生的图片拼接工具类

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
import android.webkit.MimeTypeMap;
import android.webkit.URLUtil;

import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ImageUtils {
    private String TAG = "ImageUtils";
    private static  Context context;
    public ImageUtils(Context context){
        this.context = context;
    }
    /**
     * 图片处理
     * @param image
     * @return
     */
    public String processImage(String image) {
        if (TextUtils.isEmpty(image)) {
            return "";
        }
        if(URLUtil.isHttpUrl(image) || URLUtil.isHttpsUrl(image)) {
            return saveBytesToFile(getBytesFromURL(image), getExtension(image));
        } else if (isBase64(image)) {
            return saveBitmapToFile(decodeBase64ToBitmap(image));
        } else if (URLUtil.isFileUrl(image) || image.startsWith("/") ){
            File file = new File(image);
            return file.getAbsolutePath();
        } else if(URLUtil.isContentUrl(image)) {
            return saveBitmapToFile(getBitmapFromUri(Uri.parse(image)));
        } else {
            return saveBitmapToFile(BitmapFactory.decodeResource(context.getResources(),getDrawableFileID(image)));
        }
    }
    /**
     * 获取Drawble资源的文件ID
     * @param imageName
     * @return
     */
    private int getDrawableFileID(String imageName) {
        ResourceDrawableIdHelper sResourceDrawableIdHelper = ResourceDrawableIdHelper.getInstance();
        int id = sResourceDrawableIdHelper.getResourceDrawableId(context,imageName);
        return id;
    }

    /**
     * 获取链接指向文件后缀
     *
     * @param src
     * @return
     */
    public static String getExtension(String src) {
        String extension = null;
        try {
            URL url = new URL(src);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            String contentType = connection.getContentType();
            extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(contentType);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return extension;
    }
    /**
     * 检查图片字符串是不是Base64
     * @param image
     * @return
     */
    public boolean isBase64(String image) {
        try {
            byte[] decodedString = Base64.decode(image, Base64.DEFAULT);
            Bitmap bitmap = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
            if (bitmap == null) {
                return false;
            }
            return true;
        } catch (Exception e) {
            return false;
        }
    }
    /**
     * 将 byte[] 保存成文件
     * @param bytes 图片内容
     * @param ext 扩展名
     * @return
     */
    private String saveBytesToFile(byte[] bytes, String ext) {
        File pictureFile = getOutputMediaFile(ext);
        if (pictureFile == null) {
            return null;
        }
        try {
            FileOutputStream fos = new FileOutputStream(pictureFile);
            fos.write(bytes);
            fos.close();
        } catch (FileNotFoundException e) {
            Log.d(TAG, "File not found: " + e.getMessage());
        } catch (IOException e) {
            Log.d(TAG, "Error accessing file: " + e.getMessage());
        }
        return pictureFile.getAbsolutePath();
    }

    /**
     * 根据图片的URL转化成 byte[]
     * @param src
     * @return
     */
    private static byte[] getBytesFromURL(String src) {
        try {
            URL url = new URL(src);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoInput(true);
            connection.connect();
            InputStream input = connection.getInputStream();
            byte[] b = getBytes(input);
            return b;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    private static byte[] getBytes(InputStream inputStream) throws Exception {
        byte[] b = new byte[1024];
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        int len = -1;
        while ((len = inputStream.read(b)) != -1) {
            byteArrayOutputStream.write(b, 0, len);
        }
        byteArrayOutputStream.close();
        inputStream.close();
        return byteArrayOutputStream.toByteArray();
    }
    /**
     * 根据uri生成Bitmap
     * @param uri
     * @return
     */
    private Bitmap getBitmapFromUri(Uri uri) {
        try{
            InputStream inStream = context.getContentResolver().openInputStream(uri);
            Bitmap bitmap = BitmapFactory.decodeStream(inStream);
            return  bitmap;
        }catch (FileNotFoundException e) {
            Log.d(TAG, "File not found: " + e.getMessage());
        }
        return null;
    }
    /**
     * 将bitmap 保存成文件
     * @param bitmap
     * @return
     */
    private String saveBitmapToFile(Bitmap bitmap) {

        Bitmap  bm = BitmapFactory.decodeResource( context.getResources(), R.drawable.otherImg);
        Bitmap mergeBitmap = mergeBitmap(bitmap,bm);

        File pictureFile = getOutputMediaFile();
        if (pictureFile == null) {
            return null;
        }
        try {
            FileOutputStream fos = new FileOutputStream(pictureFile);
            mergeBitmap.compress(Bitmap.CompressFormat.PNG, 90, fos);
            fos.close();
        } catch (FileNotFoundException e) {
            Log.d(TAG, "File not found: " + e.getMessage());
        } catch (IOException e) {
            Log.d(TAG, "Error accessing file: " + e.getMessage());
        }
        return pictureFile.getAbsolutePath();

    }
    /**
     * 将Base64解码成Bitmap
     * @param Base64String
     * @return
     */
    private Bitmap decodeBase64ToBitmap(String Base64String) {
        byte[] decode = Base64.decode(Base64String,Base64.DEFAULT);
        Bitmap bitmap = BitmapFactory.decodeByteArray(decode, 0, decode.length);
        return  bitmap;
    }
    /**
     * 生成文件用来存储图片
     * @return
     */
    private File getOutputMediaFile(){
        return getOutputMediaFile("jpg");
    }

    private File getOutputMediaFile(String ext){
        ext = ext != null ? ext : "jpg";
        File mediaStorageDir = context.getExternalCacheDir();
        if (! mediaStorageDir.exists()){
            if (! mediaStorageDir.mkdirs()){
                return null;
            }
        }
        String timeStamp = new SimpleDateFormat("ddMMyyyy_HHmm").format(new Date());
        File mediaFile;
        String mImageName="RN_"+ timeStamp +"." + ext;
        mediaFile = new File(mediaStorageDir.getPath() + File.separator + mImageName);
        Log.d("path is",mediaFile.getPath());
        return mediaFile;
    }
    /**
     * @return 拼接图片
     */
    private Bitmap mergeBitmap(Bitmap firstBitmap, Bitmap secondBitmap) {

        int width =firstBitmap.getWidth();
        int width2 = secondBitmap.getWidth();
        int height2 = secondBitmap.getHeight();

        // 对share图片缩放处理
        Matrix matrix = new Matrix();
        float scale = ((float) width) / width2;
        matrix.setScale(scale, scale);
        Bitmap newSecondBitmap = Bitmap.createBitmap(secondBitmap, 0, 0, width2,
                height2, matrix, true);

        //拼接图片
        int height = firstBitmap.getHeight() + newSecondBitmap.getHeight();
        Bitmap result = Bitmap.createBitmap(width, height,firstBitmap.getConfig());
        Canvas canvas = new Canvas(result);
        canvas.drawBitmap(firstBitmap, 0, 0, null);
        canvas.drawBitmap(newSecondBitmap,0, firstBitmap.getHeight(), null);
        return result;
    }

    public Bitmap decodeUriAsBitmap(String path){
        Bitmap bitmap = null;
        try{
            File file = new File(path);
            if(file.exists()){
                bitmap = BitmapFactory.decodeFile(path);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return bitmap;
    }

    public String bitmapToBase64(Bitmap bitmap){
        String result = null;
        ByteArrayOutputStream baos = null;
        try{
            if(bitmap != null){
                baos = new ByteArrayOutputStream();
                bitmap.compress(Bitmap.CompressFormat.PNG,100,baos);
                baos.flush();
                baos.close();

                byte[] bitmapBytes = baos.toByteArray();
                result = Base64.encodeToString(bitmapBytes,Base64.DEFAULT);
            }
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            try{
                if( baos != null ){
                    baos.flush();
                    baos.close();
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }

        return result;
    }

}

相关文章

  • RN 第三方组件

    rn-splash-screen 解决白屏 react-native-view-shot 截屏 "react-na...

  • RN 中截屏react-native-view-shot

    应用场景: 对应用中的某一个界面进行截屏并保存(Android 和 IOS) (特殊情况是对该截屏进行图片拼接,本...

  • React Native 截屏组件

    React Native 截屏组件:react-native-view-shot,可以截取当前屏幕或者按照当前页面...

  • android 截屏实现

    Android 截屏分为四种:View 截屏、WebView 截屏、系统截屏 和 adb 截屏 1、View 截屏...

  • Android 截屏方式整理

    Android 实现截屏方式整理 可能的需求: 截自己的屏 截所有的屏 带导航栏截屏 不带导航栏截屏 截屏并编辑选...

  • 你知道吗?Word也可以截屏

    你用过Wor中的截屏工具吗?在日常工作中,我们经常会借助QQ,微信或是其他工具截屏,其实Word也是可以截屏的,今...

  • 截屏小姐,你还好么?

    生活中,认识一个截屏小姐,为什么叫他截屏小姐呢,当然了,因为她喜欢截屏。 你看,这篇文章写了怎样...

  • Android surfaceView,TextureView、

    TextureView截屏 surfaceView截屏 root 截图

  • Quartz 2D (2)

    1、圆形图片裁剪 2、实现手机屏幕截屏功能(把控制器中View的内容截屏生成一张新的图片) 3、图片截屏 4、图片...

  • iOS截屏和读取

    除了直接使用手机按键截屏,在App中我们也可以通过代码去实现截屏功能。以下是我的工程里封装的截屏方法,在此记录一下...

网友评论

      本文标题:RN 中截屏react-native-view-shot

      本文链接:https://www.haomeiwen.com/subject/qmdjqqtx.html