Я хочу создать приложение для камеры с полноэкранным переходом и масштабированием предварительного просмотра камеры с соотношением сторон, поддерживаемым камерой устройства.
Код, который я использую для создания полноэкранного состояния включения / выключения, равен
public void hideSystemUI(boolean isFullScreen) {
if (Build.VERSION.SDK_INT >= 16) {
View decorView = getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_FULLSCREEN;
if (Build.VERSION.SDK_INT >= 19) {
uiOptions = uiOptions | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
}
if (isFullScreen) {
// hide nav bar
uiOptions = uiOptions | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
}
decorView.setSystemUiVisibility(uiOptions);
}
}
Макет приложения
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Main Content -->
<RelativeLayout
android:id="@+id/layout_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#F00">
<augmentedreality.view.ARView
android:id="@+id/camera_preview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- Navigation Buttons -->
<include
layout="@layout/layout_cam_menu"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
</android.support.v4.widget.DrawerLayout>
Я использовал Nexus 4 на эмуляторе, который имеет полноэкранную ширину 1280 пикселей и высоту: 720 пикселей, с шириной панели навигации 1184.
Когда я переключаюсьиз полноэкранного режима выключен, если SurfaceView внутри ArView не масштабирован. FrameLayout и SurfaceView в нем масштабированы правильно, если я масштабирую SurfacView до меньшего размера, чем родительский RelativeLayout, RelativeLayout не масштабируется и остается в полном размере с 1280x720, а некоторая часть остается под панелью навигации.
Установка размеров экрана в поле
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
View parent = ((View) getView().getParent().getParent());
int parentWidth = parent.getWidth();
int parentHeight = parent.getHeight();
mDeviceScreenSize = new Size(parentWidth, parentHeight);
// Set Preview Surface Dimensions
setSize(width, height);
dispatchSurfaceChanged();
Rect rect = holder.getSurfaceFrame();
System.out.println("*****************************");
System.out.println("SurfaceViewPreview surfaceChanged() width: " + width + ", height: " + height);
System.out.println("SurfaceViewPreview surfaceChanged() getWidth(): " + getWidth() + ", getHeight(): " + getHeight());
System.out.println("SurfaceViewPreview surfaceChanged() PARENT width: "
+ ", width: " + parentWidth + ", height: " + parentHeight);
System.out.println("SurfacePreview surfaceChanged() RECT SurfaceFrame WIDTH: "
+ rect.right + ", HEIGHT: " + rect.bottom);
System.out.println("SurfacePreview surfaceChanged() SCREEN width: " + mDeviceScreenSize.width + ", height: " + mDeviceScreenSize.height);
System.out.println("*****************************");
}
Масштабный код для предварительного просмотра камеры и рисования SurfaceViews
public void setPreviewScreenSize(int cameraPreviewWidth, int cameraPreviewHeight) {
float ratio = (float) cameraPreviewWidth / cameraPreviewHeight;
// These values are scaled SurfaceView dimension depending on aspect ratio
int previewWidth;
int previewHeight;
// Landscape
if (mDeviceScreenSize.width > mDeviceScreenSize.height) {
previewWidth = (int) (mDeviceScreenSize.height * ratio);
previewHeight = mDeviceScreenSize.height;
// Preview width is bigger than screen width
if (previewWidth > mDeviceScreenSize.width) {
System.out.println("SurfacePreview setPreviewScreenSize() WIDTH PREVIEW > SCREEN");
previewWidth = mDeviceScreenSize.width;
previewHeight = (int) (previewWidth / ratio);
}
} else {
// Portrait
previewWidth = mDeviceScreenSize.width;
previewHeight = (int) (mDeviceScreenSize.width * ratio);
// Preview height is bigger than screen height
if (previewHeight > mDeviceScreenSize.height) {
System.out.println("SurfacePreview setPreviewScreenSize() HEIGHT PREVIEW > SCREEN");
previewHeight = mDeviceScreenSize.height;
previewWidth = mDeviceScreenSize.width;
}
}
System.out.println("++++++++++++++++++++++");
System.out.println("SurfacePreview setPreviewScreenSize() Camera Preview cameraPreviewWidth: " + cameraPreviewWidth + ", cameraPreviewHeight: " + cameraPreviewHeight);
System.out.println("SurfacePreview setPreviewScreenSize() Screen width: " + mDeviceScreenSize.width + ", height: " + mDeviceScreenSize.height);
System.out.println("SurfacePreview setPreviewScreenSize() getWidth(): " + getWidth() + ", getHeight(): " + getHeight());
System.out.println("SurfacePreview setPreviewScreenSize() ratio " + ratio + ", previewWidth: "
+ previewWidth + ", previewHeight: " + previewHeight);
System.out.println("++++++++++++++++++++++");
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(previewWidth, previewHeight);
params.gravity = Gravity.CENTER;
mSurfaceView.setLayoutParams(params);
if (mPreviewChangeListener != null)
mPreviewChangeListener.onPreviewSizeChanged(previewWidth, previewHeight);
}
Я пытался получить размер окна для DisplayMetrics, но отображать метрики всегдавозвращает размеры с помощью навигационной панели 1184x768 и отображения wih реальные метрики всегда возвращают 1280x768
FullScreen изображение без масштабирования
Изображение с NavigationBar без масштабирования
Изображение с панелью навигации после масштабирования, на этом изображении некоторая часть изображения находится ниже панели навигации