我有建立这样一个VideoView:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/player"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<VideoView
android:id="@+id/video"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:layout_centerVertical="true" />
<ProgressBar
android:id="@+id/loader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true" />
</RelativeLayout>
但VideoView父容器的宽度相匹配,然后将高度根据被加载的影片的宽高比设置。
我想这样做正好相反,我希望VideoView,同时保持长宽比不变符合父母的高度,视频将在两侧被裁剪。
我设法拉伸VideoView以填充父但随后的纵横比不存。
另一件事是,我加入的MediaController像这样的VideoView:
MediaController controllers = new MediaController(this) {
@Override
public void hide() {
if (state != State.Hidden) {
this.show();
}
else {
super.hide();
}
}
};
controllers.setAnchorView(videoView);
videoView.setMediaController(controllers);
videoView.setOnPreparedListener(new OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
controllers.show();
}
});
这个伟大的工程,以及控制器永远留在,但控制器的高度计算时在何处放置视频(因为它是垂直居中)不被考虑。
我的两个问题,然后是:
- 如何让我的VideoView符合父母的高度但保持宽高比?
- 我如何让VideoView考虑到高度的它的控制器?
谢谢。
Answer 1:
您应该扩展内置的视频观看。
呼叫setVideoSize
显示视频视图之前,你可以从视频中提取缩略图获取视频的大小。
所以,当视频视图的onMeasure
被调用时,都mVideoWidth
& mVideoHeight
是> 0。
如果你想占控制器的高度,你可以自己做的onMeasure
方法。
希望会有所帮助。
public class MyVideoView extends VideoView {
private int mVideoWidth;
private int mVideoHeight;
public MyVideoView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyVideoView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public MyVideoView(Context context) {
super(context);
}
public void setVideoSize(int width, int height) {
mVideoWidth = width;
mVideoHeight = height;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Log.i("@@@", "onMeasure");
int width = getDefaultSize(mVideoWidth, widthMeasureSpec);
int height = getDefaultSize(mVideoHeight, heightMeasureSpec);
if (mVideoWidth > 0 && mVideoHeight > 0) {
if (mVideoWidth * height > width * mVideoHeight) {
// Log.i("@@@", "image too tall, correcting");
height = width * mVideoHeight / mVideoWidth;
} else if (mVideoWidth * height < width * mVideoHeight) {
// Log.i("@@@", "image too wide, correcting");
width = height * mVideoWidth / mVideoHeight;
} else {
// Log.i("@@@", "aspect ratio is correct: " +
// width+"/"+height+"="+
// mVideoWidth+"/"+mVideoHeight);
}
}
// Log.i("@@@", "setting size: " + width + 'x' + height);
setMeasuredDimension(width, height);
}
}
Answer 2:
我解决了这个问题与布局。 看来,它工作得很好,当它被钉在角落,但它造成的视频歪斜。 为了测试我改变了我的相对布局的背景#990000看穿红戳。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/relative_parent"
android:background="#000000">
<VideoView
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:focusable="false"
android:focusableInTouchMode="false"
android:id="@+id/videoView" />
</RelativeLayout>
Answer 3:
public class MyVideoView extends VideoView {
private int mVideoWidth;
private int mVideoHeight;
public MyVideoView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyVideoView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public MyVideoView(Context context) {
super(context);
}
@Override
public void setVideoURI(Uri uri) {
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(this.getContext(), uri);
mVideoWidth = Integer.parseInt(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH));
mVideoHeight = Integer.parseInt(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT));
super.setVideoURI(uri);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Log.i("@@@", "onMeasure");
int width = getDefaultSize(mVideoWidth, widthMeasureSpec);
int height = getDefaultSize(mVideoHeight, heightMeasureSpec);
if (mVideoWidth > 0 && mVideoHeight > 0) {
if (mVideoWidth * height > width * mVideoHeight) {
// Log.i("@@@", "image too tall, correcting");
height = width * mVideoHeight / mVideoWidth;
} else if (mVideoWidth * height < width * mVideoHeight) {
// Log.i("@@@", "image too wide, correcting");
width = height * mVideoWidth / mVideoHeight;
} else {
// Log.i("@@@", "aspect ratio is correct: " +
// width+"/"+height+"="+
// mVideoWidth+"/"+mVideoHeight);
}
}
// Log.i("@@@", "setting size: " + width + 'x' + height);
setMeasuredDimension(width, height);
}
}
Answer 4:
关于问题1,我很惊讶,没有人提到可能使用MediaPlayer的缩放模式进行。 https://developer.android.com/reference/android/media/MediaPlayer.html#setVideoScalingMode(int)
它有2种模式。 他们两人总是填充视图区域。 为了得到它,以填补空间,同时保持纵横比,从而裁剪长边,你需要切换到第二模式, VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING
。 解决该问题的一个组成部分。 另一部分是改变VideoView的测量行为,正如一些其他的答案证明。 这是我的方式做的,主要是出于懒惰和不熟悉的元数据API的,其他人使用,欢迎您使用此方法或其他方法来解决该视图的大小。 毯子捕捉确保安全时,这就是所谓的mMediaPlayer存在之前,因为它可以被称为很多次,也回落到原来的行为应该字段名曾经改变。
class FixedSizeVideoView : VideoView {
constructor(ctx: Context) : super(ctx)
constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs)
// rather than shrink down to fit, stay at the size requested by layout params. Let the scaling mode
// of the media player shine through. If the scaling mode on the media player is set to the one
// with cropping, you can make a player similar to AVLayerVideoGravityResizeAspectFill on iOS
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
try {
val mpField = VideoView::class.java.getDeclaredField("mMediaPlayer")
mpField.isAccessible = true
val mediaPlayer: MediaPlayer = mpField.get(this) as MediaPlayer
val width = View.getDefaultSize(mediaPlayer.videoWidth, widthMeasureSpec)
val height = View.getDefaultSize(mediaPlayer.videoHeight, heightMeasureSpec)
setMeasuredDimension(width, height)
}
catch (ex: Exception) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
}
}
}
因此,使用这个类的布局,你只需要改变的缩放模式的媒体播放器上,无论你有机会。 如:
video.setOnPreparedListener { mp: MediaPlayer ->
mp.setVideoScalingMode(MediaPlayer.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING)
mp.isLooping = true
mp.setScreenOnWhilePlaying(false)
}
video.start()
Answer 5:
快速高效的解决办法:
无需创建VideoView延伸的自定义视图。 只需设置足够大的值android:layout_width
。 这将设置widthSpecMode
视频视图的View.MeasureSpec.AT_MOST
然后onMeasure()
VideoView的方法将自动地调整其宽度保持率。
<VideoView
android:id="@+id/video"
android:layout_width="2000dp"
android:layout_height="match_parent" />
Answer 6:
我花费在互联网上我没有找到任何更好的解决方案,可应用于默认视频视图上搜索这个时候。 所以,我搜索了这将解决我的要求库终于让我找到一个“FullscreenVideoView”( https://github.com/rtoshiro/FullscreenVideoView )这解决了我的要求,
Answer 7:
我已经尝试了很多解决方案,而我的视频在1000×1000格式始终,所以我创造了谁知道他们的纵横比人一个简单的解决方案。 首先建立在这样的一个RelativeLayout的VideoView:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/video_holder"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:clipToPadding="false">
<VideoView
android:id="@+id/videoView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true" />
</RelativeLayout>
然后你之前加载视频改变高度和以编程这样的:
int i = videoView.getHeight() > videoView.getWidth() ? videoView.getHeight() : videoView.getWidth();
video_holder.setLayoutParams(new ConstraintLayout.LayoutParams(i, i));
当然,这仅适用于1:1个纵横比的,但你可以只用你的纵横比来改变高度或宽度。
Answer 8:
对于第一个时间的问题回答了我的问题,而不是答案! 我的问题是,我有充分的屏幕上的视频下一个空格。 我设置了layout_height
到match_parent
。 解决的办法是将它设置为wrap_content
,给家长一个黑色的背景。 也就是说,和具有VideoView
在其父垂直居中。
我写了这个作为一个评论,但随即想到有人可能有同样的问题我有,所以这里是作为一个答案也。
Answer 9:
Jobbert在科特林答案,万一有人需要它:
val max = if (videoView.height > videoView.width) videoView.height else videoView.width
videoView.layoutParams = ConstraintLayout.LayoutParams(max, max)
文章来源: VideoView to match parent height and keep aspect ratio