VideoView不会缩放内容以匹配其父级

时间:2014-05-14 19:34:36

标签: android

我正在使用DraggablePanel库(https://github.com/pedrovgs/DraggablePanel)来促进类似YouTube的视频播放器。如果您不熟悉此功能,它基本上允许用户将当前播放的视频缩小为停靠在屏幕一角的小缩略图。

不幸的是(我不确定这是上述库的问题)我注意到如果我在VideoView的父视图上应用X和Y缩放,VideoView本身将不会调整其内容的大小以匹配

参见下面的截图,其中VideoView处于自然规模,然后将其父视图缩小到约0.6:0.6。您应该注意到,在缩放的屏幕截图中,VideoView已裁剪其内容,而不是调整大小以适应。

VideoView properly scaled 1:1

VideoView parent scaled to 0.6:0.6

因此我试图在VideoView上强制宽度和高度,因为其父级的比例已经改变。互联网上有一些关于覆盖VideoView尺寸的例子 - 但这是我的简单版本:

public class ScalableVideoView extends VideoView {

    private int mVideoWidth;
    private int mVideoHeight;

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

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

    public ScalableVideoView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mVideoWidth = 0;
        mVideoHeight = 0;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        if (mVideoWidth > 0 && mVideoHeight > 0) {
            // If a custom dimension is specified, force it as the measured dimension
            setMeasuredDimension(mVideoWidth, mVideoHeight);
        } else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }

    public void changeVideoSize(int width, int height) {
        mVideoWidth = width;
        mVideoHeight = height;

        getHolder().setFixedSize(width, height);

        requestLayout();
        invalidate();
    }

}

包含VideoView的片段负责在收到DraggablePanel库关于比例变化的通知时调用它的changeVideoSize。此时,我根据提供的比例值计算一对新的宽度和高度。 (比例从0f到1f)

public void setVideoViewScale(float scaleX, float scaleY) {
        if (mMaxVideoWidth == 0) {
            mMaxVideoWidth = mVideoView.getWidth();
        }

        if (mMaxVideoHeight == 0) {
            mMaxVideoHeight = mVideoView.getHeight();
        }

        if (mMaxVideoWidth > 0) {

            mVideoView.changeVideoSize((int) (scaleX * mMaxVideoWidth),
                    (int) (scaleY * mMaxVideoHeight));
        }
    }

不幸的是,这会导致一些非常有趣的结果。似乎VideoView的视频部分正在适当缩放 - 但VideoView的边界似乎缩放太快(导致视频缩小和裁剪)。

ScalingVideoView at 0.5 scale

有关进一步演示,请参阅以下两个视频:

我还将此示例项目上传到GitHub,以便您可以看到完整的代码: https://github.com/npike/so_scalevideoview

2 个答案:

答案 0 :(得分:3)

我的应用程序遇到了同样的问题,所以我举了更简单的示例,并尝试修复它。
这是解决问题的代码。将changeVideoSize(int width,int height)方法编辑为:

public void changeVideoSize(int width, int height){
    mVideoWidth = width;
    mVideoHeight = height;

    RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(width, height);
    lp.addRule(RelativeLayout.CENTER_HORIZONTAL, RelativeLayout.TRUE);
    lp.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
    setLayoutParams(lp);

    requestLayout();
    invalidate();
}

如果视图无效,则会强制VideoView使用新的布局参数重绘整个视图。

答案 1 :(得分:1)

我相信VideoView不支持缩放。在DraggablePanel附带的示例应用程序中,有一个VideoSampleActivity,它演示了一个可拖动的视频。为了实现缩放等效果,top_view_resize属性在activity_video_sample.xml中设置为true:

  <com.github.pedrovgs.DraggableView
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:draggable_view="http://schemas.android.com/apk/res-auto"
  android:id="@+id/draggable_view"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  draggable_view:top_view_id="@+id/video_view"
  draggable_view:bottom_view_id="@+id/iv_thumbnail"
  draggable_view:top_view_x_scale_factor="@dimen/x_scale_factor"
  draggable_view:top_view_y_scale_factor="@dimen/y_scale_factor"
  draggable_view:top_view_height="@dimen/top_fragment_height"
  draggable_view:top_view_margin_right="@dimen/top_fragment_margin"
  draggable_view:top_view_margin_bottom="@dimen/top_fragment_margin"
  draggable_view:enable_minimized_horizontal_alpha_effect="false"
  draggable_view:top_view_resize="true"
  android:background="@color/black">

将top_view_resize设置为true会导致TransformerFactory返回ResizeTransformer而不是ScaleTransformer。 ResizeTransformer使用setLayoutParams()来调整关联的View的大小,ScaleTransformer应用比例因子。

您应该能够将top_view_resize设置为true,而不是尝试缩放VideoView。

注意:如果使用DraggablePanel(支持顶部和底部片段)而不是DraggableView,则您当前无法访问嵌套在DraggablePanel内的DraggableView的top_view_resize属性。我认为这是一个错误,我希望我可以使用Pedro在DraggablePanel上公开top_view_resize属性,该属性将其值传递给嵌套的DraggableView。由于这个错误,DraggablePanel总是使用默认的Transformer,它是ScaleTransformer - 它不适用于VideoView。