Android VideoView 中的纵向视频不会占用整个屏幕宽度

Posted

技术标签:

【中文标题】Android VideoView 中的纵向视频不会占用整个屏幕宽度【英文标题】:Portrait video in Android VideoView will not take up whole width of the screen 【发布时间】:2015-02-06 00:32:42 【问题描述】:

我的布局中有一个 VideoView,在这个 VideoView 中我试图播放一个垂直方向的视频。我的印象是,这是一个打算以纵向显示的纵向视频,事情再简单不过了。男孩,我错了吗。

这是我的 Java 代码:

videoView1 = (VideoView) findViewById(R.id.videoView1);


        videoView1.setVideoPath("android.resource://" + getPackageName() + "/"
                + R.raw.video);
        videoView1.setOnCompletionListener(new OnCompletionListener() 

            @Override
            public void onCompletion(MediaPlayer mp) 
                videoView1.start();
            
        );
videoView1.start();

这是我的 videoview 元素的 .xml(顺便说一句,它在 RelativeLayout 中):

 <VideoView
        android:id="@+id/videoView1"
        android:layout_
        android:layout_
        android:layout_alignParentBottom="true"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_centerInParent="true"
        android:layout_marginLeft="0dp"
        android:layout_marginRight="0dp" />

我真正期望在公园散步时遇到的最令人惊讶的事情是,无论我做什么,视频确实会拉伸以填满屏幕的高度(因此 layout_alignParentTop 和 layout_alignParentBottom 显然可以正常工作) 但该死的东西不会填满屏幕的宽度!(是的,我很沮丧)所以这个已经垂直的视频在屏幕中间被拉伸成一个类似丝带的结构.

我添加了marginLeft 和marginRight 属性,拼命地尝试看看它是否可以工作,但没有!大吃一惊,我删除了 centerInParent 属性,但又没有。我什至创建了一个自定义 VideoView,覆盖了 onMeasure,但仍然一无所获。

我尝试以编程方式设置 VideoView 的 LayoutParams。你猜怎么着,没用。

【问题讨论】:

RelativeLayout 的宽度和高度参数是什么(videoView1 的父级)? 它们都设置为 match_parent。 尝试在清单中添加android:theme="@android:style/Theme.NoTitleBar.Fullscreen" 【参考方案1】:

我创建了这个简单的 VideoView 子类,它在保持宽高比的同时全屏显示,您可以找到 Gist here 以获得最新版本,但这里有一个示例:

/**
 * Subclass of VideoView to enable video scaling
 * CustomAttribute: "scaleType": "normal", "centerCrop", "fill"
 * <p>
 * Add this stylable:
 * <declare-styleable name="IntroVideoView">
 * <attr name="scaleType" format="integer">
 * <flag name="normal" value="0" />
 * <flag name="centerCrop" value="1" />
 * <flag name="fill" value="2" />
 * </attr>
 * </declare-styleable>
 * <p>
 * Created by joaquimley on 13/01/2017.
 */

public class IntroVideoView extends VideoView 

    private static final int SCALE_TYPE_NORMAL = 0;
    private static final int SCALE_TYPE_CENTER_CROP = 1;
    private static final int SCALE_TYPE_FILL = 2;

    private int mScaleType;
    private int mHorizontalAspectRatioThreshold;
    private int mVerticalAspectRatioThreshold;

    public IntroVideoView(Context context) 
        this(context, null, 0);
    

    public IntroVideoView(Context context, AttributeSet attrs) 
        this(context, attrs, 0);
    

    public IntroVideoView(Context context, AttributeSet attrs, int defStyleAttr) 
        super(context, attrs, defStyleAttr);
        TypedArray attributes = context.getTheme().obtainStyledAttributes(attrs, R.styleable.IntroVideoView, 0, 0);
        mScaleType = attributes.getInt(R.styleable.IntroVideoView_scaleType, SCALE_TYPE_NORMAL);
    

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (mScaleType == SCALE_TYPE_CENTER_CROP) 
            applyCenterCropMeasure(widthMeasureSpec, heightMeasureSpec);
         else if (mScaleType == SCALE_TYPE_FILL) 
            applyFillMeasure(widthMeasureSpec, heightMeasureSpec);
         // else default/no-op
    

    @Override
    public void layout(int l, int t, int r, int b) 
        if (mScaleType == SCALE_TYPE_CENTER_CROP) 
            applyCenterCropLayout(l, t, r, b);
         else 
            super.layout(l, t, r, b);
        
    

    private void applyCenterCropLayout(int left, int top, int right, int bottom) 
        super.layout(left + mHorizontalAspectRatioThreshold, top + mVerticalAspectRatioThreshold, right
                + mHorizontalAspectRatioThreshold, bottom + mVerticalAspectRatioThreshold);
    

    private void applyCenterCropMeasure(int widthMeasureSpec, int heightMeasureSpec) 
        int videoWidth = getMeasuredWidth();
        int videoHeight = getMeasuredHeight();

        int viewWidth = getDefaultSize(0, widthMeasureSpec);
        int viewHeight = getDefaultSize(0, heightMeasureSpec);

        mHorizontalAspectRatioThreshold = 0;
        mVerticalAspectRatioThreshold = 0;
        if (videoWidth == viewWidth) 
            int newWidth = (int) ((float) videoWidth / videoHeight * viewHeight);
            setMeasuredDimension(newWidth, viewHeight);
            mHorizontalAspectRatioThreshold = -(newWidth - viewWidth) / 2;
         else 
            int newHeight = (int) ((float) videoHeight / videoWidth * viewWidth);
            setMeasuredDimension(viewWidth, newHeight);
            mVerticalAspectRatioThreshold = -(newHeight - viewHeight) / 2;

        
    

    private void applyFillMeasure(int widthMeasureSpec, int heightMeasureSpec) 
        int width = getDefaultSize(0, widthMeasureSpec);
        int height = getDefaultSize(0, heightMeasureSpec);
        setMeasuredDimension(width, height);
    

以及自定义属性的样式:

<resources>
    <declare-styleable name="IntroVideoView">
        <attr name="scaleType" format="integer">
            <flag name="normal" value="0" />
            <flag name="centerCrop" value="1" />
            <flag name="fill" value="2" />
        </attr>
    </declare-styleable>
</resources>

【讨论】:

请同时指定如何在布局中引用它? 什么意思?您只需将此(与任何其他)自定义视图添加到您的布局文件中。 当然。真正的罪魁祸首是没有使用onConfigurationChanged 好的,如果对你有帮助别忘了转发。【参考方案2】:

没关系,我是个白痴。我很确定即使是菜鸟视频编辑也不会犯这种错误(我什至不是菜鸟),但是在旋转视频后,由于纵横比,纵向视频的侧面添加了黑条,并且这就是为什么视频不会填满屏幕宽度的原因——因为那里有黑条!事实证明,在裁剪黑条后,视频可以完美拉伸 - 就像以前一样,但黑条消失了!

【讨论】:

以上是关于Android VideoView 中的纵向视频不会占用整个屏幕宽度的主要内容,如果未能解决你的问题,请参考以下文章

android studio中的纵向到横向视频视图和控制器重启问题

以纵向模式在videoview中全屏制作视频[重复]

Android VideoView 方向,如 Youtube 应用程序

在纵向上垂直居中 VideoView

Android videoview控件不显示视频,只播放音频

播放 VideoView 的不同纵向和横向布局