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 的重力设置为中心。

4

5 回答 5

136

尝试使用 aFrameLayout代替。我不知道为什么,但如果我在我的代码中使用Linearor Relative,它不会居中,但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>
于 2011-01-31T19:46:27.993 回答
14

为了使视频在RelativeLayout中居中,我添加了两个layout_gravity="center"ad 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>
于 2013-08-15T22:58:56.093 回答
9

卡梅伦以编程方式回答(以防像我这样的人需要它)此代码在我的代码中活动的 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);
于 2013-11-29T11:35:35.597 回答
9

这适用于任何保持视频纵横比的视频。它将视频定位在 VideoView 内,并像 ImageView 一样执行 Center Crop 或 Center Inside。

我正在使用 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);               
    }
 });

希望它可以帮助某人!

于 2018-12-05T22:23:28.300 回答
4

如果您正在寻找与ImageView.ScaleType.CENTER_CROPVideoView 中的功能相同的效果,那么

这是一个简单易行的解决方案

在此处查看我的 XML 和 Kotlin 版本答案: https ://stackoverflow.com/a/59069292/6255841

在 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);
        }
     }
});
于 2019-11-27T11:37:48.043 回答