Щепотка, чтобы увеличить MyTextureView только для размера экрана (ширина, высота) - PullRequest
0 голосов
/ 05 ноября 2018

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

Вот код для моего класса, который получает TextureView:

public class ScaleManager extends BaseInputManager {

    private final TextureView mTargetView;
    private final ScaleGestureDetector mScaleDetector;
    private static final float MIN_SCALE = 1.0f;
    private static final float MAX_SCALE = 5.0f;
    private float mCurrentScale = MIN_SCALE;
    private Matrix mMatrix = new Matrix();
    private float[] mMatrixValues = new float[9];
    private float mPreviousX;
    private float mPreviousY;
    private boolean mIsDragInProgress = false;

    public ScaleManager(TextureView view) {
        mTargetView = view;
        mScaleDetector = new ScaleGestureDetector(view.getContext(), new ScaleListener());
        mScaleDetector.setQuickScaleEnabled(false);
    }


    @Override
    public boolean handle(KeyEvent event) {
        return false;
    }

    @Override
    public boolean handle(MotionEvent event) {
        final int index = event.getActionIndex();
        final int type = event.getToolType(index);
        if (type == MotionEvent.TOOL_TYPE_FINGER || type == MotionEvent.TOOL_TYPE_STYLUS) {
            mScaleDetector.onTouchEvent(event);

            mMatrix.getValues(mMatrixValues);
            boolean isScaling = (mMatrixValues[Matrix.MSCALE_X] != 1.0f && mMatrixValues[Matrix.MSCALE_Y] != 1.0f);
            if (isScaling || mScaleDetector.isInProgress()) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_POINTER_DOWN:
                    case MotionEvent.ACTION_DOWN:
                        if (event.getPointerCount() <= 2) {
                            mPreviousX = event.getX();
                            mPreviousY = event.getY();
                        }

                        if (event.getPointerCount() == 2) {
                            mIsDragInProgress = true;
                        }
                        break;
                    case MotionEvent.ACTION_MOVE:
                        if (event.getPointerCount() == 2) {
                            float x = mMatrixValues[Matrix.MTRANS_X];
                            float y = mMatrixValues[Matrix.MTRANS_Y];

                            float width = mTargetView.getWidth();
                            float height = mTargetView.getHeight();

                            float right = width * mCurrentScale - width;
                            float bottom = height * mCurrentScale - height;

                            float deltaX = event.getX() - mPreviousX;// x difference
                            float deltaY = event.getY() - mPreviousY;// y difference

                            float scaledWidth = Math.round(width * mCurrentScale);// width after applying current scale
                            float scaledHeight = Math.round(height * mCurrentScale);// height after applying current scale
                            //if scaledWidth is smaller than the views width
                            //in other words if the image width fits in the view
                            //limit left and right movement
                            if (scaledWidth < width) {
                                deltaX = 0;
                                if (y + deltaY > 0) {
                                    deltaY = -y;
                                } else if (y + deltaY < -bottom) {
                                    deltaY = -(y + bottom);
                                }

                                //if scaledHeight is smaller than the views height
                                //in other words if the image height fits in the view
                                //limit up and down movement
                            } else if (scaledHeight < height) {
                                deltaY = 0;
                                if (x + deltaX > 0) {
                                    deltaX = -x;
                                } else if (x + deltaX < -right) {
                                    deltaX = -(x + right);
                                }

                                //if the image doesn't fit in the width or height
                                //limit both up and down and left and right
                            } else {
                                if (x + deltaX > 0) {
                                    deltaX = -x;
                                } else if (x + deltaX < -right) {
                                    deltaX = -(x + right);
                                }

                                if (y + deltaY > 0) {
                                    deltaY = -y;
                                } else if (y + deltaY < -bottom) {
                                    deltaY = -(y + bottom);
                                }
                            }

                            //move the image with the matrix
                            mMatrix.postTranslate(deltaX, deltaY);


                            mTargetView.setTransform(mMatrix);
                            mTargetView.invalidate();

                            mPreviousX = event.getX();
                            mPreviousY = event.getY();
                        }
                        break;
                    case MotionEvent.ACTION_POINTER_UP:

                    case MotionEvent.ACTION_UP:
                        if (event.getPointerCount() == 1) {
                            mIsDragInProgress = false;
                        }
                        break;
                }
            }


            return mScaleDetector.isInProgress() || mIsDragInProgress;
        }

        return false;
    }


    private class ScaleListener implements ScaleGestureDetector.OnScaleGestureListener {

        @Override
        public boolean onScaleBegin(ScaleGestureDetector detector) {
            return true;
        }

        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            float width = mTargetView.getWidth();
            float height = mTargetView.getHeight();
            float factor = detector.getScaleFactor();
            float scale = mCurrentScale * factor;
            if (scale > MAX_SCALE) {
                factor = MAX_SCALE / mCurrentScale;
                mCurrentScale = MAX_SCALE;
            } else if (scale < MIN_SCALE) {
                factor = MIN_SCALE / mCurrentScale;
                mCurrentScale = MIN_SCALE;
            } else {
                mCurrentScale = scale;
            }

            if (width * scale <= width || height * scale <= height) {
                mMatrix.postScale(factor, factor, width / 2, height / 2);
            } else {
                mMatrix.postScale(factor, factor, detector.getFocusX(), detector.getFocusY());
            }

            if (factor < 1) {
                float right = width * mCurrentScale - width;
                float bottom = height * mCurrentScale - height;

                mMatrix.getValues(mMatrixValues);
                float x = mMatrixValues[Matrix.MTRANS_X];
                float y = mMatrixValues[Matrix.MTRANS_Y];

                if (x < -right) {
                    mMatrix.postTranslate(-(x + right), 0);
                } else if (x > 0) {
                    mMatrix.postTranslate(-x, 0);
                }

                if (y < -bottom) {
                    mMatrix.postTranslate(0, -(y + bottom));
                } else if (y > 0) {
                    mMatrix.postTranslate(0, -y);
                }
            }



            return true;
        }

        @Override
        public void onScaleEnd(ScaleGestureDetector detector) {
        }
    }


}

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

<com.examples.views.AspectRatioFrameLayout
    android:id="@+id/player_video"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="center"
    android:focusable="true"
    android:focusableInTouchMode="true" />




mSurfaceView = layoutInflater.inflate(R.layout.texture_view, 
player_video_frame, false)

Это класс AspectFrameLayout, который я использую для сохранения соотношения сторон:

public final class AspectRatioFrameLayout extends FrameLayout {


    private static final float MAX_ASPECT_RATIO_DEFORMATION_FRACTION = 0.01f;

    private float mVideoAspectRatio;

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

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


    public void setAspectRatio(float ratio) {
        if (this.mVideoAspectRatio != ratio) {
            this.mVideoAspectRatio = ratio;
            requestLayout();
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (mVideoAspectRatio == 0) {
            // Aspect ratio not set.
            return;
        }

        int width = getMeasuredWidth();
        int height = getMeasuredHeight();
        float viewAspectRatio = (float) width / height;
        float aspectDeformation = mVideoAspectRatio / viewAspectRatio - 1;
        if (Math.abs(aspectDeformation) <= MAX_ASPECT_RATIO_DEFORMATION_FRACTION) {
            // We're within the allowed tolerance.
            return;
        }

        if (aspectDeformation > 0) {
            height = (int) (width / mVideoAspectRatio);
        } else {
            width = (int) (height * mVideoAspectRatio);
        }
        super.onMeasure(
                MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
                MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
        );
    }

}
...