2012-11-28 2 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를 늘리지 만 종횡비는 유지되지 않습니다.

또 다른 한가지는, 나는이 같은 VideoView를 지켜 보면서로를 MediaController를 추가 해요되어

:

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- than-the-screen – 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 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); } – 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

인터넷에서 검색하는 데 시간이 오래 걸립니다. 기본 비디오보기에 적용 할 수있는 더 나은 솔루션을 찾지 못했습니다. 그래서 난 내 요구 사항을 해결할 라이브러리를 검색 마침내 나는 질문 1에 대해서는

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

, 나는 아무도 MediaPlayer를의 확장 모드의 사용 가능성을 언급하지 않았다 놀란다 한 'FullscreenVideoView'(https://github.com/rtoshiro/FullscreenVideoView)이 해결 내 요구 사항을 발견 . https://developer.android.com/reference/android/media/MediaPlayer.html#setVideoScalingMode(int)

두 가지 모드가 있습니다. 둘 다 항상 뷰 영역을 채 웁니다.종횡비를 유지하면서 공간을 채우려면 긴면을 자르기 위해 두 번째 모드 인 VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING으로 전환해야합니다. 그것은 문제의 한 부분을 해결합니다. 다른 부분은 다른 답변의 일부처럼 비디오 뷰의 측정 동작을 변경하는 것입니다. 이것은 내가 게으름에서 벗어난 방법이며 다른 사람들이 사용하는 메타 데이터 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

이것은 안드로이드가 아닙니다. – jobbert

+1

Kotlin, 친애하는 선생님 :) – user3175580

0

내 비디오는 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> 

을 사용하면 비디오가 높이를 변경하고 프로그래밍이 등을로드하기 전에 : 1 화면 비율의 : 물론

int i = videoView.getHeight() > videoView.getWidth() ? videoView.getHeight() : videoView.getWidth(); 
    video_holder.setLayoutParams(new ConstraintLayout.LayoutParams(i, i)); 

이 단 1 작동 높이나 너비를 변경하려면 가로 세로 비율을 사용할 수 있습니다.

관련 문제