效果图
https://download.csdn.net/download/qq_38355313/10717497
<!-- 相机相关 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
使用的activity添加硬件加速(默认开启,为啥要开启可自行百度)
android:hardwareAccelerated="true"
package com.nxm.interpreter.views; import android.content.Context; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.graphics.PixelFormat; import android.graphics.RectF; import android.graphics.SurfaceTexture; import android.graphics.drawable.BitmapDrawable; import android.hardware.Camera; import android.os.Build; import android.os.Environment; import android.util.AttributeSet; import android.view.Surface; import android.view.TextureView; import android.view.View; import android.view.WindowManager; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; /** * ************************************************************************************************** * 修改日期 修改人 任务名称 功能或Bug描述 * 2018/10/12 10:36 MUZI102 TextureView类目 * ************************************************************************************************** */ public class MyTextureView extends TextureView implements View.OnLayoutChangeListener { public Camera mCamera; private Context context; private Camera.Parameters param; private boolean isCanTakePicture = false; Matrix matrix; Camera camera; int mWidth = 0; int mHeight = 0; int mDisplayWidth = 0; int mDisplayHeight = 0; int mPreviewWidth = 640; int mPreviewHeight = 480; int orientation = 0; public MyTextureView(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; init(); } private void init() { if (null == mCamera) { mCamera = Camera.open(); } this.setSurfaceTextureListener(new SurfaceTextureListener() { @Override public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) { param = mCamera.getParameters(); param.setPictureFormat(PixelFormat.JPEG); param.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); if (!Build.MODEL.equals("KORIDY H30")) { param.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);// 1连续对焦 } else { param.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); } mCamera.setParameters(param); //变形处理 RectF previewRect = new RectF(0, 0, mWidth, mHeight); double aspect = (double) mPreviewWidth / mPreviewHeight; if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { aspect = 1 / aspect; } if (mWidth < (mHeight * aspect)) { mDisplayWidth = mWidth; mDisplayHeight = (int) (mHeight * aspect + .5); } else { mDisplayWidth = (int) (mWidth / aspect + .5); mDisplayHeight = mHeight; } RectF surfaceDimensions = new RectF(0, 0, mDisplayWidth, mDisplayHeight); Matrix matrix = new Matrix(); matrix.setRectToRect(previewRect, surfaceDimensions, Matrix.ScaleToFit.FILL); MyTextureView.this.setTransform(matrix); //<-处理变形 int displayRotation = 0; WindowManager windowManager = (WindowManager) context .getSystemService(Context.WINDOW_SERVICE); int rotation = windowManager.getDefaultDisplay().getRotation(); switch (rotation) { case Surface.ROTATION_0: displayRotation = 0; break; case Surface.ROTATION_90: displayRotation = 90; break; case Surface.ROTATION_180: displayRotation = 180; break; case Surface.ROTATION_270: displayRotation = 270; break; } Camera.CameraInfo info = new Camera.CameraInfo(); Camera.getCameraInfo(0, info); int orientation; if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) { orientation = (info.orientation - displayRotation + 360) % 360; } else { orientation = (info.orientation + displayRotation) % 360; orientation = (360 - orientation) % 360; } mCamera.setParameters(param); mCamera.setDisplayOrientation(orientation); try { mCamera.setPreviewTexture(surfaceTexture); mCamera.startPreview(); isCanTakePicture = true; } catch (Exception e) { e.printStackTrace(); } } @Override public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width, int height) { } @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) { if (mCamera != null) { mCamera.stopPreview(); mCamera.release(); mCamera = null; isCanTakePicture = true; } return true; } @Override public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { } }); } /** * 拍照 */ public void take() { if (mCamera != null && isCanTakePicture) { isCanTakePicture = false; mCamera.takePicture(new Camera.ShutterCallback() { @Override public void onShutter() { } }, null, mPictureCallback); } } public void startPreview() { if (mCamera != null && !isCanTakePicture) { MyTextureView.this.setBackgroundDrawable(null); mCamera.startPreview(); isCanTakePicture = true; } } public void stopPreview() { if (mCamera != null) { mCamera.stopPreview(); } } Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { if (mCamera != null) { mCamera.stopPreview(); new FileSaver(data).save(); } } }; @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { mWidth = right - left; mHeight = bottom - top; } private class FileSaver implements Runnable { private byte[] buffer; public FileSaver(byte[] buffer) { this.buffer = buffer; } public void save() { new Thread(this).start(); } @Override public void run() { try { File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), System.currentTimeMillis() + ".png"); file.createNewFile(); FileOutputStream os = new FileOutputStream(file); BufferedOutputStream bos = new BufferedOutputStream(os); Bitmap bitmap = BitmapFactory.decodeByteArray(buffer, 0, buffer.length); bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos); bos.flush(); bos.close(); os.close(); MyTextureView.this.setBackgroundDrawable(new BitmapDrawable(bitmap)); } catch (Exception e) { e.printStackTrace(); } } } }
1、xml的布局
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <com.nxm.textureviewdemo.MyTextureView android:id="@+id/mytextureview" android:layout_width="match_parent" android:layout_height="match_parent" /> <Button android:id="@+id/paizhai" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="拍照" /> <Button android:id="@+id/yulan" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/paizhai" android:text="预览" /> </RelativeLayout>
2、使用
package com.nxm.textureviewdemo; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; public class MainActivity extends AppCompatActivity { private MyTextureView myTextureView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); myTextureView = findViewById(R.id.mytextureview); findViewById(R.id.paizhai).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { myTextureView.take(); } }); findViewById(R.id.yulan).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { myTextureView.startPreview(); } }); } @Override protected void onStart() { super.onStart(); myTextureView.startPreview(); } @Override protected void onStop() { myTextureView.stopPreview(); super.onStop(); } @Override protected void onDestroy() { myTextureView.releaseTextureView(); super.onDestroy(); } }