2012-11-28 5 views
15

Ich habe eine Videoview, die sich wie diese festgelegt ist:Videoview Mutterhöhe entsprechen und das Seitenverhältnis halten

<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> 

Aber die Videoview passt die Breite des übergeordneten Container, und dann wird die Höhe eingestellt nach der Seitenverhältnis des geladenen Films.
Ich möchte genau das Gegenteil tun, ich möchte das VideoView die Höhe des Elternteils entsprechen, während das Seitenverhältnis beibehalten wird, wird das Video an den Seiten abgeschnitten.

Ich habe es geschafft, das VideoView zu strecken, um das Elternteil zu füllen, aber dann wird das Seitenverhältnis nicht beibehalten.

Eine andere Sache ist, ich MediaController- zum Videoview wie folgt ich hinzufügen:

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(); 
    } 
}); 

Dies funktioniert gut, und die Controller immer bleiben, aber die Höhe der Controller wird nicht berücksichtigt werden, wenn Berechnen, wo das Video platziert werden soll (da es vertikal zentriert ist).

Meine zwei Fragen dann sind:

  1. Wie kann ich die Videoview die Höhe des Eltern entsprechen noch das Seitenverhältnis halten?
  2. Wie kann ich den VideoView die Höhe seiner Controller berücksichtigen?

Danke.

+0

Sprechen Sie über ein WebView oder VideoView? Du wechselst ungefähr auf halbem Weg nach unten. –

Antwort

16

Sie sollten von der integrierten Videoansicht aus erweitert werden.

Rufen Sie setVideoSize an, bevor die Videoansicht angezeigt wird. Sie können die Videogröße aus dem aus dem Video extrahierten Miniaturbild abrufen.

, so dass, wenn die Video Ansicht des onMeasure genannt wird, sowohl mVideoWidth & mVideoHeight sind> 0

Wenn Sie die Höhe von Controllern berücksichtigen möchten, können Sie es tun, um sich in der onMeasure Methode.

Hoffnung wird helfen.

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

Dies half definitiv, aber ich musste auch die Ansicht einrichten, um größer als der Bildschirm zu sein, wie hier: http://stackoverflow.com/questions/3813049/how-to-create-a-view-that-is-bigger- als der Bildschirm – Kibi

+0

@ ax003d Ich habe versucht, diese videoView.setLayoutParams (params); videoView.setDimensions (params.width, params.width); videoView.getHolder(). SetFixedSize (params.width, params.height); aber immer noch nicht meine videoview height – Erum

+3

Dies ist eine nette Antwort, aber statt setVideoSize() manuell zu verwenden, würde ich Methode überschreiben, die Video laden: @Override öffentlichen void setVideoURI (Uri uri) { MediaMetadataRetriever Retriever = neue MediaMetadataRetriever (); retriever.setDataSource (this.getContext(), uri); mVideoWidth = Ganzzahl.parseInt (retriever.extractMetadata (MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)); mVideoHeight = Ganzzahl.parseInt (retriever.extractMetadata (MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)); super.setVideoURI (uri); } – Arthez

3

Ich löste dieses Problem mit Layout. Es scheint, dass es gut funktionierte, wenn es an den Ecken befestigt wurde, aber es verursachte das Video, um zu verdrehen. Um zu testen, änderte ich den Hintergrund meines relativen Layouts auf # 990000, um zu sehen, wie das Rot durchstößt.

<?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

Ich verbringe Zeit auf dieser Suche im Internet Ich habe keine bessere Lösung gefunden, die für die Standard-Videoansicht gelten kann. Also suchte ich nach Bibliotheken, die meine Anforderung lösen schließlich fand ich eine ‚FullscreenVideoView‘ (https://github.com/rtoshiro/FullscreenVideoView) diese gelöst meine Anforderung

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

Vielen Dank für diesen Code. Es klappt. – Smeet

+0

Funktioniert nicht auf Galaxy S3 – Slava

+1

Funktioniert auch nicht auf Nexus 5X :( – Slava

2

Zu Frage 1: Ich bin überrascht, niemand die mögliche Verwendung des Skalierungsmodus des Mediaplayer erwähnt . https://developer.android.com/reference/android/media/MediaPlayer.html#setVideoScalingMode(int)

Es hat 2 Modi. Beide füllen immer den Sichtbereich.Um den Platz unter Beibehaltung des Seitenverhältnisses zu füllen und somit die lange Seite zu beschneiden, müssen Sie in den zweiten Modus wechseln, VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING. Das löst einen Teil des Problems. Der andere Teil besteht darin, das Messverhalten von VideoView zu ändern, wie einige der anderen Antworten zeigen. Dies ist die Art, wie ich es gemacht habe, hauptsächlich aus Faulheit und nicht vertraut mit den Metadaten-APIs, die die anderen verwenden. Sie können diese Methode oder eine der anderen Methoden verwenden, um die Größe der Ansicht zu korrigieren. Der pauschale Catch sorgt für Sicherheit, wenn dieser vor dem mMediaPlayer aufgerufen wird, wie es oft genannt wird, und greift auch auf altes Verhalten zurück, sollte sich der Feldname jemals ändern.

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) 
     } 
    } 
} 

So diese Klasse im Layout verwenden, ändern Sie einfach den Skalierungsmodus auf den Medien-Player, wo Sie eine Chance haben. Wie zum Beispiel:

 video.setOnPreparedListener { mp: MediaPlayer -> 
      mp.setVideoScalingMode(MediaPlayer.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING) 
      mp.isLooping = true 
      mp.setScreenOnWhilePlaying(false) 
     } 
     video.start() 
+0

Dies ist nicht Android ist es? – jobbert

+1

Kotlin, lieber Herr :) – user3175580

0

Ich habe viele Lösungen ausprobiert, während mein Video in 1000 * 1000-Format war immer, also habe ich eine einfache Lösung für Menschen geschaffen, die ihre Seitenverhältnis kennen. Erstellen Sie zunächst eine Videoview in einem RelativeLayout wie folgt aus:

<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> 

Dann, bevor Sie das Video die Höhe laden ändern und mit programmatisch wie folgt aus:

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

Natürlich funktioniert dies nur mit 1: 1 Seitenverhältnis des aber Sie könnten einfach Ihr Seitenverhältnis verwenden, um entweder die Höhe oder die Breite zu ändern.

Verwandte Themen