1

我已经用 TextureView 实现了我的自定义 CamerView,效果很好。尽管在某些设备(例如Motorolla G4 - MarshMallow)中,Lenovo KNote - Lollipop Camera Preview 会闪烁,屏幕上会出现绿色方形视图。

这是我的 CameraTextureView

public class CameraTextureView extends TextureView implements TextureView.SurfaceTextureListener {
private static final String TAG = CameraTextureView.class.getSimpleName();
private Camera mCamera;
private List<Camera.Size> mSupportedPreviewSizes;
private Camera.Size mPreviewSize;
private SurfaceTexture mSurfaceTexture;
private Handler mHandler;
private Context mContext;

public void setCamera(Camera mCamera) {
    try {
        this.mCamera = mCamera;
        if (mCamera == null) {
            return;
        }
        startCameraPreview();
    } catch (Exception e) {
        FileLog.e(TAG, e);
    }
}

public Camera getCamera() {
    return mCamera;
}

public CameraTextureView(Context context, Camera mCamera) {
    super(context);
    try {
        this.setSurfaceTextureListener(this);
        this.mCamera = mCamera;
        this.mSurfaceTexture = getSurfaceTexture();
        this.mHandler = new Handler();
        mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
        this.mContext = context;
    } catch (Exception e) {
        FileLog.e(TAG, e);
    }
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    try {
        final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);

        if (mSupportedPreviewSizes != null) {
            mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
        }

        float ratio;
        if (mPreviewSize.height >= mPreviewSize.width)
            ratio = (float) mPreviewSize.height / (float) mPreviewSize.width;
        else
            ratio = (float) mPreviewSize.width / (float) mPreviewSize.height;

        setMeasuredDimension(width, ApplicationLoader.getPreferences().isToShowTeamList() == true ? (int) (width * ratio) : height);
    } catch (Exception e) {
        FileLog.e(TAG, e);
    }
}

private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
    try {
        final double ASPECT_TOLERANCE = 0.1;
        double targetRatio = (double) h / w;

        if (sizes == null) return null;

        Camera.Size optimalSize = null;
        double minDiff = Double.MAX_VALUE;

        int targetHeight = h;

        for (Camera.Size size : sizes) {
            double ratio = (double) size.width / size.height;
            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }

        if (optimalSize == null) {
            minDiff = Double.MAX_VALUE;
            for (Camera.Size size : sizes) {
                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }
        }
        return optimalSize;
    } catch (Exception e) {
        FileLog.e(TAG, e);
    }
    return null;
}

public void startCameraPreview() {
    try {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    mCamera.setPreviewTexture(getSurfaceTexture());
                    Camera.Parameters parameters = mCamera.getParameters();
                    parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
                    parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
                    parameters.setRotation(90);
                    mCamera.setDisplayOrientation(90);
                    mCamera.setParameters(parameters);
                    mCamera.startPreview();
                } catch (Exception e) {
                    FileLog.e(TAG, e);
                }
            }
        };

        Thread thread = new Thread(runnable);
        thread.start();
    } catch (Exception e) {
        FileLog.e(TAG, e);
    }
}

private void setCameraDisplayOrientation(Context mContext, android.hardware.Camera camera) {
    try{
        android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
        /*int rotation = mContext.getWindowManager().getDefaultDisplay().getRotation();*/
        Display display = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
        int rotation = display.getRotation();
        int degrees = 0;
        switch (rotation) {
            case Surface.ROTATION_0:
                degrees = 0;
                break;
            case Surface.ROTATION_90:
                degrees = 90;
                break;
            case Surface.ROTATION_180:
                degrees = 180;
                break;
            case Surface.ROTATION_270:
                degrees = 270;
                break;
        }

        int result;
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360;
            result = (360 - result) % 360; // compensate the mirror
        } else { // back-facing
            result = (info.orientation - degrees + 360) % 360;
        }
        camera.setDisplayOrientation(result);
    }catch(Exception e){
        FileLog.e(TAG, e.toString());
    }
}

@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
    startCameraPreview();
}



@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}

@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
    return false;
}

@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
}

虽然在截图时它在截图上看起来很正常。

4

0 回答 0