在VideoView中定位视频

59

我已经扩展了VideoView的onMeasure方法,以将视频缩放至适应全屏视图。

具体代码如下:

public void setVideoAspect(int w,int h){
    wVideo=w;
    hVideo=h;
    onMeasure(w, h);
}
 @Override
 protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec)
 {
     super.onMeasure(widthMeasureSpec, heightMeasureSpec);
     if(wVideo!=0 && hVideo!=0)
     setMeasuredDimension(wVideo,hVideo);
 }

我使用屏幕的显示指标(宽度、高度)调用setVideoAspect(),但是这个方法会拉伸视频以适应屏幕。我想保持宽高比。我有一个4:3的视频和3:2的屏幕尺寸。我使用以下代码向视图提供了保留宽高比的测量值:

int height =  (int) (metrics.widthPixels*3/(float)4);
                        int width=  metrics.widthPixels;   
                        mVideoView.setVideoAspect(width,height);
所以这段代码已经能够实现功能,但有一个问题:它给我一个宽度与屏幕相同但高度正确缩放的4:3视频,但它没有将视频居中。(它只是裁剪视频的底部而不是顶部和底部平均裁剪。) 我有一个包含了VideoView的相对布局,其中VideoView的gravity属性设置为center。

你能提供完整的代码吗?我卡住了。 - Sagar
5个回答

136

可以尝试使用 FrameLayout 代替。我不确定为什么,但如果我在代码中使用 LinearRelative,它无法居中,但是 FrameLayout 可以。这是适合将视频调整到屏幕大小、保持比例并居中的 XML 代码:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@drawable/bg">
    <!-- Video player -->
    <VideoView
        android:id="@+id/surface_view"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_gravity="center"/>
</FrameLayout>

1
如果您对Android自动调整视频大小感到满意(如果是横向的,则很可能会垂直填充屏幕,然后按比例调整水平大小),我认为您不需要任何代码。但是,如果您出于任何原因仍需要它,那么使用该代码应该可以正常工作。 - Cameron
2
我不知道为什么,但是当我在谷歌上搜索VideoView中视频对齐的时候,这篇文章并没有出现。直到我开始撰写问题之前,相关答案才被建议给我。谢谢! :) - jlindenbaum
@CameronW 我不介意Android自动为我调整视频大小。但是根据这个链接:https://dev59.com/p2855IYBdhLWcg3wSSKl#4452597,调整大小只能通过代码实现,对吗? - Elad Benda
谢谢@CameronW。好的解决方案。 - KDeogharkar
可以工作了。这是我对Android感到不满的事情之一 - 这不应该有任何影响! - kaay
很好的发现!非常感谢。 - Vlad

14

为了使视频在RelativeLayout中居中,我添加了layout_gravity="center"layout_centerInParent="true"。这在我的Android 4.3手机上有效。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <VideoView android:id="@+id/surface_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:layout_centerInParent="true" />
</RelativeLayout>

1
如果你的VideoView设置为match_parent,那么它将占据RelativeLayout的全部空间,因此android:layout_gravity="center"和android:layout_centerInParent="true"不应该有任何效果。 - Malachiasz
@Malachiasz 在RelativeLayout中,如果我只给match_parent,那么视频只会显示在左侧,但是在应用android:layout_centerInParent之后-->视频会显示在中心。不要让其他人感到困惑。这个答案是有效的。 - Ranjithkumar

10

这适用于任何视频,保持视频的宽高比例。它将视频放置在VideoView内部,并执行类似ImageView的中心裁剪或中心内部操作。

我正在使用一个VideoView来覆盖整个ConstraintLayout。您可以使用任何其他布局,可能宽度和高度都为match_parent。

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <VideoView
        android:id="@+id/videoView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>

在onCreate方法中:

Uri uri = //The uri of your video.
VideoView videoView = findViewById(R.id.videoView);
videoView.setVideoURI(uri);
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
    @Override
    public void onPrepared(MediaPlayer mp) {

        //Get your video's width and height
        int videoWidth = mp.getVideoWidth();
        int videoHeight = mp.getVideoHeight();

        //Get VideoView's current width and height
        int videoViewWidth = videoView.getWidth();
        int videoViewHeight = videoView.getHeight();

        float xScale = (float) videoViewWidth / videoWidth;
        float yScale = (float) videoViewHeight / videoHeight;

        //For Center Crop use the Math.max to calculate the scale
        //float scale = Math.max(xScale, yScale);
        //For Center Inside use the Math.min scale. 
        //I prefer Center Inside so I am using Math.min
        float scale = Math.min(xScale, yScale);

        float scaledWidth = scale * videoWidth;
        float scaledHeight = scale * videoHeight;

        //Set the new size for the VideoView based on the dimensions of the video
        ViewGroup.LayoutParams layoutParams = videoView.getLayoutParams();
        layoutParams.width = (int)scaledWidth;
        layoutParams.height = (int)scaledHeight;
        videoView.setLayoutParams(layoutParams);               
    }
 });

希望这能对某些人有所帮助!

9

以下是 Cameron 给出的程序化答案(如果有人像我一样需要)此代码位于我的代码中 onCreate 方法内(下面的 'this' 指的是该活动)

    FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
            LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);

    FrameLayout fl = new FrameLayout(this);

    fl.setLayoutParams(lp);

    VideoView vv = new VideoView(this);

    FrameLayout.LayoutParams lp2 = new FrameLayout.LayoutParams(lp);

    lp2.gravity = Gravity.CENTER;

    vv.setLayoutParams(lp2);

    fl.addView(vv);

    setContentView(fl);

4

如果您希望在VideoView中获得与ImageView.ScaleType.CENTER_CROP相同的效果,则可以使用以下简单易懂的解决方案。

请查看我在XML和Kotlin版本上的回答: https://dev59.com/WmIk5IYBdhLWcg3wFKlK#59069292

在JAVA中:

videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
    @Override
    public void onPrepared(MediaPlayer mp) {
        float videoRatio = mp.getVideoWidth() / (float) mp.getVideoHeight();
        float screenRatio = videoView.getWidth() / (float) 
        videoView.getHeight();
        float scaleX = videoRatio / screenRatio;
        if (scaleX >= 1f) {
            videoView.setScaleX(scaleX);
        } else {
            videoView.setScaleY(1f / scale);
        }
     }
});

3
很遗憾,它对我没用(为什么?它不能扩展,保持不变)。 - Dyno Cris
哦,我找到了适合我的解决方案 https://dev59.com/5Wgt5IYBdhLWcg3w5har#26587338 - Dyno Cris

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