Предварительный просмотр андроидной текстуры во весь экран с правильным соотношением сторон

Я работал с камерой2 api demo из google и, к сожалению, приложение-образец построено для отображения предварительного просмотра текстуры примерно на 70% высота экрана, после осмотра я смог определить, что это вызвано тем, что AutoFitTextureView переопределяет метод onMeasure(), как показано ниже:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int width = MeasureSpec.getSize(widthMeasureSpec);
    int height = MeasureSpec.getSize(heightMeasureSpec);
    if (0 == mRatioWidth || 0 == mRatioHeight) {
        setMeasuredDimension(width, height);
    } else {
        if (width < height * mRatioWidth / mRatioHeight) {
            setMeasuredDimension(width, width * mRatioHeight / mRatioWidth);
        } else {
            setMeasuredDimension(height * mRatioWidth / mRatioHeight, height);
        }
    }
}

Я попытался исправить это, установив правильные высоты и ширину в setMeasuredDimension(width, height);, это зафиксировало проблему с высотой и предоставило мне полноэкранный предварительный просмотр из текстурного изображения, однако соотношение сторон полностью сломано и искажено на каждом устройстве, что это стандартный способ его устранения? Я вижу, что многие приложения в игровом магазине нашли способ решить эту проблему, но havent удалось отследить исправление, любая помощь пройдет долгий путь, спасибо.

Ответ 1

Мне удалось исправить проблему, переключив setMeasuredDimension();

    int width = MeasureSpec.getSize(widthMeasureSpec);
    int height = MeasureSpec.getSize(heightMeasureSpec);
    if (0 == mRatioWidth || 0 == mRatioHeight) {
        setMeasuredDimension(width, height);
    } else {
        if (width < height * mRatioWidth / mRatioHeight) {
            setMeasuredDimension(height * mRatioWidth / mRatioHeight, height);
        } else {
            setMeasuredDimension(width, width * mRatioHeight / mRatioWidth);
        }
    }

Ответ 2

Я позволю вам под кодом, который мы использовали для измерения предварительного просмотра, который поддерживает размеры предварительного просмотра 4: 3, 16: 9 и 1:1. Высота масштабируется, потому что приложение является блоком в портрете, оно не поворачивается к пейзажу.

Надеюсь, это поможет вам или кому-то еще с той же проблемой!

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

    Log.d(TAG, "[onMeasure] Before transforming: " + width + "x" + height);

    int rotation = ((Activity) getContext()).getWindowManager().getDefaultDisplay().getRotation();
    boolean isInHorizontal = Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation;

    int newWidth;
    int newHeight;

    Log.d(TAG, "[onMeasure] Get measured dimensions: " + getMeasuredWidth() + "x" + getMeasuredHeight());

    if (isInHorizontal) {
        newHeight = getMeasuredHeight();
        if (mAspectRatioOneOne) newWidth = getMeasuredHeight();
        else newWidth = (int) (newHeight * mAspectRatio);
    } else {
        newWidth = getMeasuredWidth();
        if (mAspectRatioOneOne) newHeight = getMeasuredWidth();
        else newHeight = (int) (newWidth * mAspectRatio);
    }

    setMeasuredDimension(newWidth, newHeight);
    Log.d(TAG, "[onMeasure] After transforming: " + getMeasuredWidth() + "x" + getMeasuredHeight());

}

Ответ 3

У меня была похожая проблема при использовании Camera2. Я использовал реализацию TextureView в AutoFitTextureView в качестве предварительного просмотра с камеры и хочу скорректировать соотношение сторон. Моя проблема доходила от разных реализаций методов и распространялась на onSurfaceTextureSizeChanged. [1] com.google.android.cameraview.CameraView # onMeasure (..) → [2] com.google.android.cameraview.AutoFitTextureView # onMeasure (..) → [3] onSurfaceTextureSizeChanged (..)

Проблема в том, что по-другому, если [1], чем в [2]. Я заменил в [1]:

if (height < width * ratio.getY() / ratio.getX()) {
от

до

if (!(height < width * ratio.getY() / ratio.getX())) {

потому что [2] имеет, если основано на ширине, а не на высоте

 if (width < height * mRatioWidth / mRatioHeight) {

Проверьте, правильно ли реализованы методы onMeasure (..).

Или вы могли бы сделать как Эдмунд Рохас - выше

Ответ 4

Если вам нужен полноэкранный, неискаженный предварительный просмотр, тогда вам нужно выбрать разрешение предварительного просмотра для камеры, которое соответствует соотношению сторон экрана.

Однако, если размер экрана не является стандартным (в основном, 16: 9 или 4: 3), особенно после вычитания программных кнопок и панели уведомлений (при условии, что вы не полностью полный экран) то единственным вариантом для предварительного просмотра экрана является вырезание некоторых из них.

Вы должны иметь возможность модифицировать матрицу преобразования TextureView, чтобы удалить искажения, посмотрев на ширину и высоту вида, а также на выбранную ширину и высоту предварительного просмотра, но это обязательно отключит некоторые из них.