相机预览横向视图不全屏

时间:2015-02-01 02:51:38

标签: android

我已经搜索了堆栈交换并谷歌寻求解决方案,但我似乎无法找到一个有效的解决方案。我的相机预览在纵向上可以很好地工作,但是当方向切换到横向时,它不是全屏并且高度失真。我也试图将其作为片段实现

这是我的代码

CameraFragment.java

public class CameraFragment extends Fragment implements SurfaceHolder.Callback, Camera.PictureCallback {
public static final String TAG = CameraFragment.class.getSimpleName();

private static final int PICTURE_SIZE_MAX_WIDTH = 1280;
private static final int PREVIEW_SIZE_MAX_WIDTH = 640;

private int cameraId;
private Camera camera;
private SurfaceHolder surfaceHolder;
private CameraFragmentListener listener;
private int displayOrientation;
private int layoutOrientation;

private CameraOrientationListener orientationListener;

@Override
public void onAttach(Activity activity){
    super.onAttach(activity);

    if(!(activity instanceof CameraFragmentListener)){
        throw new IllegalArgumentException("Must implement CameraFragmentListener interface");
    }

    listener = (CameraFragmentListener)activity;
    orientationListener = new CameraOrientationListener(activity);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    CameraPreview previewView = new CameraPreview(getActivity());

    previewView.getHolder().addCallback(this);

    return previewView;
}

@Override
public void onResume() {
    super.onResume();

    orientationListener.enable();

    try {
        camera = Camera.open(cameraId);
    } catch (Exception exception) {
        Log.e(TAG, "Can't open camera with id " + cameraId, exception);

        listener.onCameraError();
        return;
    }
}

@Override
public void onPause() {
    super.onPause();

    orientationListener.disable();

    if(camera != null) {
        stopCameraPreview();
        camera.release();
    }
}

private synchronized void startCameraPreview() {
    determineDisplayOrientation();
    setupCamera();

    try {
        camera.setPreviewDisplay(surfaceHolder);
        camera.startPreview();
    } catch (Exception exception) {
        Log.e(TAG, "Can't start camera preview due to Exception", exception);

        listener.onCameraError();
    }
}

private synchronized void stopCameraPreview() {
    try {
        camera.stopPreview();
    } catch (Exception exception) {
        Log.i(TAG, "Exception during stopping camera preview");
    }
}

public void determineDisplayOrientation() {
    Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
    Camera.getCameraInfo(cameraId, cameraInfo);

    int rotation = getActivity().getWindowManager().getDefaultDisplay().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 displayOrientation;

    if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
        displayOrientation = (cameraInfo.orientation + degrees) % 360;
        displayOrientation = (360 - displayOrientation) % 360;
    } else {
        displayOrientation = (cameraInfo.orientation - degrees + 360) % 360;
    }

    this.displayOrientation = displayOrientation;
    this.layoutOrientation  = degrees;

    camera.setDisplayOrientation(displayOrientation);
}

public void setupCamera() {
    Camera.Parameters parameters = camera.getParameters();

    Camera.Size bestPreviewSize = determineBestPreviewSize(parameters);
    Camera.Size bestPictureSize = determineBestPictureSize(parameters);

    parameters.setPreviewSize(bestPreviewSize.width, bestPreviewSize.height);
    parameters.setPictureSize(bestPictureSize.width, bestPictureSize.height);

    camera.setParameters(parameters);
}

private Camera.Size determineBestPreviewSize(Camera.Parameters parameters) {
    List<Camera.Size> sizes = parameters.getSupportedPreviewSizes();

    return determineBestSize(sizes, PREVIEW_SIZE_MAX_WIDTH);
}

private Camera.Size determineBestPictureSize(Camera.Parameters parameters) {
    List<Camera.Size> sizes = parameters.getSupportedPictureSizes();

    return determineBestSize(sizes, PICTURE_SIZE_MAX_WIDTH);
}

protected Camera.Size determineBestSize(List<Camera.Size> sizes, int widthThreshold) {
    Camera.Size bestSize = null;

    for (Camera.Size currentSize : sizes) {
        boolean isDesiredRatio = (currentSize.width / 4) == (currentSize.height / 3);
        boolean isBetterSize = (bestSize == null || currentSize.width > bestSize.width);
        boolean isInBounds = currentSize.width <= PICTURE_SIZE_MAX_WIDTH;

        if (isDesiredRatio && isInBounds && isBetterSize) {
            bestSize = currentSize;
        }
    }

    if (bestSize == null) {
        listener.onCameraError();

        return sizes.get(0);
    }

    return bestSize;
}

public void takePicture(){
    orientationListener.rememberOrientation();

    camera.takePicture(null, null, this);
}

@Override
public void onPictureTaken(byte[] data, Camera camera){
    Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);

    int rotation = (displayOrientation + orientationListener.getRememberedOrientation() + layoutOrientation) % 360;

    if(rotation != 0){
        Bitmap oldBitmap = bitmap;

        Matrix matrix = new Matrix();
        matrix.postRotate(rotation);

        bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
        oldBitmap.recycle();
    }
    listener.onPictureTaken(bitmap);
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    this.surfaceHolder = holder;

    startCameraPreview();
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    //fragment handles release
}
}

CameraFragmentListener.java

public interface CameraFragmentListener {
public void onCameraError();

public void onPictureTaken(Bitmap bitmap);
}

CameraOrientationListener.java

public class CameraOrientationListener extends OrientationEventListener {
private int currentNormalizedOrientation;
private int rememberNormalizedOrientation;

public CameraOrientationListener (Context context){
    super(context, SensorManager.SENSOR_DELAY_NORMAL);
}

@Override
public void onOrientationChanged(int orientation) {
    if(orientation != ORIENTATION_UNKNOWN){
        currentNormalizedOrientation = normalize(orientation);
    }
}

private int normalize(int degrees){
    if(degrees > 315 || degrees <= 45)
        return 0;
    if(degrees > 45 && degrees <= 135)
        return 90;
    if(degrees > 135 && degrees <= 225)
        return 180;
    if(degrees > 225 && degrees <= 315)
        return 270;

    throw new RuntimeException("Wrong bruh");
}

public void rememberOrientation(){
    rememberNormalizedOrientation = currentNormalizedOrientation;
}

public int getRememberedOrientation(){
    return rememberNormalizedOrientation;
}
}

CameraPreview.java

public class CameraPreview extends SurfaceView {
private static final double ASPECT_RATIO = 3.0 / 4.0;

public CameraPreview(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

public CameraPreview(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public CameraPreview(Context context) {
    super(context);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int height = MeasureSpec.getSize(heightMeasureSpec);
    int width = MeasureSpec.getSize(widthMeasureSpec);

    if (width > height * ASPECT_RATIO) {
        width = (int) (height * ASPECT_RATIO + .5);
    } else {
        height = (int) (width / ASPECT_RATIO + .5);
    }

    setMeasuredDimension(width, height);
}
}

CameraActivity.java

public class CameraActivity extends Activity implements CameraFragmentListener {
public static final String TAG = CameraActivity.class.getSimpleName();

private static final int PICTURE_QUALITY = 90;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_camera);
}

@Override
public void onCameraError(){
    Toast.makeText(this, getString(R.string.toast_error_camera_preview), Toast.LENGTH_SHORT).show();

    finish();
}

public void takePicture(View view){
    view.setEnabled(false);

    CameraFragment fragment = (CameraFragment)getFragmentManager().findFragmentById(R.id.camera_fragment);

    fragment.takePicture();
}

public void onPictureTaken(Bitmap bitmap){
    File mediaStorageDir = new File(
            Environment.getExternalStoragePublicDirectory(
                    Environment.DIRECTORY_PICTURES
            ),
            getString(R.string.app_name)
    );

    if (!mediaStorageDir.exists()) {
        if (!mediaStorageDir.mkdirs()) {
            showSavingPictureErrorToast();
            return;
        }
    }

    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    File mediaFile = new File(
            mediaStorageDir.getPath() + File.separator + "MUSTACHE_"+ timeStamp + ".jpg"
    );

    try {
        FileOutputStream stream = new FileOutputStream(mediaFile);
        bitmap.compress(CompressFormat.JPEG, PICTURE_QUALITY, stream);
    } catch (IOException exception) {
        showSavingPictureErrorToast();

        Log.w(TAG, "IOException during saving bitmap", exception);
        return;
    }

    MediaScannerConnection.scanFile(
            this,
            new String[] { mediaFile.toString() },
            new String[] { "image/jpeg" },
            null
    );

    Intent intent = new Intent(this, PhotoActivity.class);
    intent.setData(Uri.fromFile(mediaFile));
    startActivity(intent);

    finish();
}

private void showSavingPictureErrorToast() {
    Toast.makeText(this, getText(R.string.toast_error_save_picture), Toast.LENGTH_SHORT).show();
}
}

对于非常长的帖子感到抱歉,我只是希望尽可能彻底。先谢谢你们!

1 个答案:

答案 0 :(得分:0)

如果您希望全屏预览,则应在调用setContentView之前在活动中设置全屏标记:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

    setContentView(R.layout.activity_camera);
}