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

Я работал с демо-камерой camera2 от 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);, это исправило проблему с высотой и дало мне предварительный просмотр на экране из текстурного представления, однако соотношение сторон полностью нарушено и искажено на каждом устройстве, что является стандартным способом исправить это? Я вижу, что многие приложения в магазине игр нашли способ решить эту проблему, но не смогли отследить исправление, любая помощь будет иметь большое значение, спасибо.

3 ответа

Я смог решить проблему, переключив 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);
        }
    }

Ниже приведен код, который мы использовали для измерения предварительного просмотра, который поддерживает размеры предварительного просмотра 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());

}

У меня была аналогичная проблема с реализацией 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 на основе ширины, а не высоты

 if (width < height * mRatioWidth / mRatioHeight) {

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

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

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

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

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

AutoFitTextureView в макете следует использовать wrap_content

    <AutoFitTextureView
        android:id="@+id/texture"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

/**
 * A [TextureView] that can be adjusted to a specified aspect ratio.
 */
class AutoFitTextureView : TextureView {

    constructor(context: Context) : this(context, null)
    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) : super(context, attrs, defStyle)

    private var ratioWidth = 0
    private var ratioHeight = 0

    /**
     * Sets the aspect ratio for this view. The size of the view will be measured based on the ratio
     * calculated from the parameters. Note that the actual sizes of parameters don't matter, that
     * is, calling setAspectRatio(2, 3) and setAspectRatio(4, 6) make the same result.
     *
     * @param width  Relative horizontal size
     * @param height Relative vertical size
     */
    fun setAspectRatio(width: Int, height: Int) {
        require(!(width < 0 || height < 0)) { "Size cannot be negative." }
        ratioWidth = width
        ratioHeight = height
        requestLayout()
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        val width = MeasureSpec.getSize(widthMeasureSpec)
        val height = MeasureSpec.getSize(heightMeasureSpec)
        if (ratioWidth == 0 || ratioHeight == 0) {
            setMeasuredDimension(width, height)
        } else {
            if (width < height * ratioWidth / ratioHeight) {
                setMeasuredDimension(width, width * ratioHeight / ratioWidth)
            } else {
                setMeasuredDimension(height * ratioWidth / ratioHeight, height)
            }
        }
    }

}
Другие вопросы по тегам