2012-11-28 47 views
15

我具有被设置像这样的VideoView: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(); 
    } 
}); 

这个伟大的工程,以及控制器永远留在,但控制器的高度不被考虑在内时,计算放置视频的位置(因为它是垂直居中的)。

我的两个问题,然后是:

  1. 如何让VideoView符合父母的高度但保持宽高比?
  2. 我该如何让VideoView考虑它的控制器的高度?

谢谢。

+0

你说的是WebView还是VideoView?你改变了一半。 –

回答

16

您应该从内置视频视图进行扩展。

拨打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); 
     } 
} 
+1

这一定帮助,但我还需要建立视图是大于屏幕如下:http://stackoverflow.com/questions/3813049/how-to-create-a-view-that-is-bigger-比屏幕 – Kibi

+0

@ ax003d我试过这个videoView.setLayoutParams(params); videoView.setDimensions(params.width,params.width); videoView.getHolder()。setFixedSize(params.width,params.height);但仍然没有设置我的videoview高度 – Erum

+3

这是很好的答案,但不是手动使用setVideoSize(),我会覆盖加载视频的方法: @Override public void setVideoURI(Uri uri)MediaMetadataRetriever retrieve = 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); } – Arthez

3

我用布局解决了这个问题。看起来,它固定在角落时工作得很好,但它导致视频偏斜。为了测试,我将相对布局的背景更改为#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> 
0

我花时间在互联网上搜索我没有找到任何可以应用于默认视频视图的更好的解决方案。所以,我搜索了这将解决我的要求库终于让我找到一个“FullscreenVideoView”(https://github.com/rtoshiro/FullscreenVideoView)这解决了我的要求

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); 
    } 
} 
+1

非常感谢你的这段代码。有用。 – Smeet

+0

不会对银河S3 – Slava

+1

工作在Nexus 5X不工作,以及:( – Slava

2

关于问题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() 
+0

这不是Android的是什么呢? – jobbert

+1

科特林,亲爱的先生:) – user3175580

0

我已经尝试了很多解决方案,而我的视频在1000×1000格式始终,所以我创造了谁知道他们的纵横比人一个简单的解决方案。您加载视频改变高度和通过编程像在此之前

<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的比例在一个RelativeLayout的首先创建一个VideoView这样但您可以使用纵横比来更改高度或宽度。

相关问题