22

In Android's VideoView, is there any way to achieve the same effect as ImageView.ScaleType.CENTER_CROP?

That is, I want my VideoView to play the video such that it fills the entire screen without distortion. If the video aspect ratio does not exactly fit the screen's, then it should be cropped rather than distorted.

The following solution will fill the screen, but does not maintain the video's aspect ratio: https://stackoverflow.com/a/6927300/1068656

And this solution maintains the video's aspect ratio, but will not fill the entire screen (video is scaled until the longer side hits the screen's edge thereby introducing bars on the side): https://stackoverflow.com/a/4855315/1068656

Community
  • 1
  • 1
Gus
  • 2,531
  • 4
  • 22
  • 28
  • No, you need to set it manually, you need to do some mathematical calculation with your surface view and video view to adjust the preview size. – Daud Arfin Jul 31 '12 at 09:01
  • 1
    If your app supports only api 14 and above you can use TextureView and then this lib - https://github.com/dmytrodanylyk/video-crop – oznus Oct 24 '14 at 15:56
  • This solution works for CENTER_CROP OR CENTER_INSIDE https://stackoverflow.com/a/53641686/6082973 – Carlitos Dec 06 '18 at 02:55

4 Answers4

15

Although it is too late, but it might help someone else looking for the same problem. The following answer maintains the aspect ratio(videoProportion). The extra part of the videoview is cropped by the Phone's view.

private void setDimension() {
     // Adjust the size of the video
     // so it fits on the screen
     float videoProportion = getVideoProportion();
     int screenWidth = getResources().getDisplayMetrics().widthPixels;
     int screenHeight = getResources().getDisplayMetrics().heightPixels;
     float screenProportion = (float) screenHeight / (float) screenWidth;
     android.view.ViewGroup.LayoutParams lp = videoView.getLayoutParams();

     if (videoProportion < screenProportion) {
         lp.height= screenHeight;
         lp.width = (int) ((float) screenHeight / videoProportion);
     } else {
         lp.width = screenWidth;
         lp.height = (int) ((float) screenWidth * videoProportion);
     }
     videoView.setLayoutParams(lp);
 }

// This method gets the proportion of the video that you want to display.
// I already know this ratio since my video is hardcoded, you can get the  
// height and width of your video and appropriately generate  the proportion  
//    as :height/width 
private float getVideoProportion(){
  return 1.5f;
}
Deepak Negi
  • 893
  • 10
  • 19
  • Really it's working great. No need to find other code. Thanks negi – parik dhakan Jul 27 '16 at 07:47
  • There is one problem with this solution - when used in a viewpager, the resized view 'spills over' to the next page, since in portrait a landscape video will set the videoview to be extremely wide. Is there a way to center-crop after resize? – galaxigirl May 14 '17 at 06:29
  • You can wrap the VideoView in a View with the dimensions of page. – Deepak Negi Jul 28 '17 at 12:49
  • This resulted in only showing the left/top of the video which didn't suit my needs. To show the center part I added `videoView.translationX = -(lp.width - screenWidth) / 2f videoView.translationY = -(lp.height - screenHeight) / 2f` – Sam Liddle Nov 25 '22 at 16:09
15

In Android's VideoView, here is a simple and easy way to achieve the same effect as ImageView.ScaleType.CENTER_CROP

XML

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">

    <VideoView
        android:id="@+id/videoView"
        android:layout_width="@dimen/dimen_0dp"
        android:layout_height="@dimen/dimen_0dp"
        android:visibility="gone"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

In Kotlin:

videoView.setOnPreparedListener { mediaPlayer ->
    val videoRatio = mediaPlayer.videoWidth / mediaPlayer.videoHeight.toFloat()
    val screenRatio = videoView.width / videoView.height.toFloat()
    val scaleX = videoRatio / screenRatio
    if (scaleX >= 1f) {
        videoView.scaleX = scaleX
    } else {
        videoView.scaleY = 1f / scaleX
    }
}

In 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);
      }
   }
});

And this worked for me. Hope this will help someone.

Nabin
  • 1,451
  • 3
  • 19
  • 26
2

ConstraintLayout has an attribute app:layout_constraintDimensionRatio for this purpose.

<androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <VideoView
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintDimensionRatio="4:3" <!-- w:h -->
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</ConstraintLayout>

See the official documentation for more details

Entreco
  • 12,738
  • 8
  • 75
  • 95
0

Here is code for adjust Video UI as per video Size

 <androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_centerInParent="true"
    android:layout_marginStart="10dp"
    android:layout_marginTop="10dp"
    android:layout_marginEnd="10dp"
    android:layout_marginBottom="10dp">
    <VideoView
        android:id="@+id/videoPlayer"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        />
</androidx.constraintlayout.widget.ConstraintLayout>
Nimesh Patel
  • 1,394
  • 13
  • 26