2012-11-28 145 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這樣但您可以使用縱橫比來更改高度或寬度。

相關問題