VideoView无法按比例缩放内容以适应其父容器

5
我正在使用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个回答

3

我也遇到了App的同样问题,于是我采用了您的示例,这个示例更加简单,尝试着解决它。
以下是修复问题的代码。请修改你的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
我相信VideoView不支持缩放。在DraggablePanel附带的示例应用程序中,有一个VideoSampleActivity,演示了可拖动的视频。为了实现像缩放这样的效果,在activity_video_sample.xml中将top_view_resize属性设置为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 应用缩放因子。
与其尝试缩放 VideoView,您应该能够将 top_view_resize 设置为 true。
注意:如果您使用 DraggablePanel(支持顶部和底部片段)而不是 DraggableView,则当前无法访问嵌套在 DraggablePanel 中的 DraggableView 的 top_view_resize 属性。我认为这是一个错误,并希望能够与 Pedro 合作,在 DraggablePanel 上公开 top_view_resize 属性,以将其值传递到嵌套的 DraggableView。由于此错误,DraggablePanel 总是使用默认的 Transformer,即 ScaleTransformer -- 这不适用于 VideoView。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接