I have a RelativeLayout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:foregroundGravity="center"
android:gravity="center"
android:orientation="horizontal" >
<VideoView
android:id="@+id/videoViewPanel"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:layout_centerInParent="true"/>
</RelativeLayout>
And what I need is to show video fullscreen cropped. If I could compare to ImageView, I need to show it as crop_center.
How can I make VideoView not to auto-resize video to fit center, but crop center?
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 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 / scaleX);
}
}
});
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
}
}
And this worked for me. Hope this will help someone.
The solution is to use TextureView
instead of VideoView
(SurfaceView
).TextureView
does not make any manipulations with the content to fit it ti the screen.
Here is the code sample for the solution:
//store the SurfaceTexture to set surface for MediaPlayer
mTextureView.setSurfaceTextureListener(new SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface,
int width, int height) {
FullScreenActivity.this.mSurface = surface;
}
....
Surface s = new Surface(mSurface);
mPlayer = mp;
mp.setSurface(s);
scaleVideo(mp);//<-- this function scales video to run cropped
....
private void scaleVideo(MediaPlayer mPlayer) {
LayoutParams videoParams = (LayoutParams) mTextureView
.getLayoutParams();
DisplayMetrics dm = new DisplayMetrics();
FullScreenActivity.this.getWindowManager().getDefaultDisplay()
.getMetrics(dm);
final int height = dm.heightPixels;
final int width = dm.widthPixels;
int videoHeight = mPlayer.getVideoHeight();
int videoWidth = mPlayer.getVideoWidth();
double hRatio = 1;
hRatio = (height * 1.0 / videoHeight) / (width * 1.0 / videoWidth);
videoParams.x = (int) (hRatio <= 1 ? 0 : Math.round((-(hRatio - 1) / 2)
* width));
videoParams.y = (int) (hRatio >= 1 ? 0 : Math
.round((((-1 / hRatio) + 1) / 2) * height));
videoParams.width = width - videoParams.x - videoParams.x;
videoParams.height = height - videoParams.y - videoParams.y;
Log.e(TAG, "x:" + videoParams.x + " y:" + videoParams.y);
mTextureView.setScaleX(1.00001f);//<-- this line enables smoothing of the picture in TextureView.
mTextureView.requestLayout();
mTextureView.invalidate();
}
I just put video inside ConstraintLayout
with such parameters. This helped stretch video and achieve android:scaleType="centerCrop"
effect.
<VideoView
android:id="@+id/video_view"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_gravity="center_horizontal"
android:layout_width="0dp"
android:layout_height="0dp" />
To crop center in fullscreen you can still use a VideoView. Set the VideoView width and height to match the parent inside a RelativeLayout and adjust it to be bigger than the screen and set his position.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/rootLayout"
tools:context="com.example.Activity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_height="match_parent">
<VideoView
android:id="@+id/video_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:layout_centerVertical="true" />
</RelativeLayout>
</RelativeLayout>
And then in onCreate:
RelativeLayout rootView=(RelativeLayout) findViewById(R.id.rootLayout);
Display display=getWindowManager().getDefaultDisplay();
Point size=new Point();
display.getSize(size);
FrameLayout.LayoutParams rootViewParams = (FrameLayout.LayoutParams) rootView.getLayoutParams();
int videoWidth=864;
int videoHeight=1280;
if ((float)videoWidth/(float)videoHeight<(float)size.x/(float)size.y) {
rootViewParams.width=size.x;
rootViewParams.height=videoHeight*size.x/videoWidth;
rootView.setX(0);
rootView.setY((rootViewParams.height-size.y)/2*-1);
} else {
rootViewParams.width=videoWidth*size.y/videoHeight;
rootViewParams.height=size.y;
rootView.setX((rootViewParams.width-size.x)/2*-1);
rootView.setY(0);
}
rootView.setLayoutParams(rootViewParams);
final VideoView mVideoView=(VideoView)findViewById(R.id.video_view);
mVideoView.setVideoURI(Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.splash));
mVideoView.requestFocus();
mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
mVideoView.start();
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With