我已经搜索了堆栈交换并谷歌寻求解决方案,但我似乎无法找到一个有效的解决方案。我的相机预览在纵向上可以很好地工作,但是当方向切换到横向时,它不是全屏并且高度失真。我也试图将其作为片段实现
这是我的代码
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();
}
}
对于非常长的帖子感到抱歉,我只是希望尽可能彻底。先谢谢你们!
答案 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);
}