Änderung der Android VideoView-Ausrichtung mit gepuffertem Video
Ich versuche, die im wesentlichen repliziert die Funktionalität der neuesten YouTube-app in den Android marketplace. Wenn ein video ansehen, es gibt zwei separate layouts, die man im portrait die zusätzliche info, und eine Landschaft bietet eine Vollbildansicht des Videos.
YouTupe-app im portrait-Modus
YouTube-app im landscape-Modus
(Sorry für die Zufälligkeit des Fotos, aber Sie waren die ersten Bilder die ich finden konnte, der das eigentliche layout)
Dies ist ziemlich einfach zu tun, die in der Regel - geben Sie einfach ein Alternatives layout im layout-land und alles wird gut. Die Sache, dass die YouTube-app ist wirklich gut (und was ich versuche zu replizieren, ist die Ausrichtung ändern, wird das video weiter abgespielt und nicht auf re-Puffer von Anfang an.
Habe ich herausgefunden, dass das überschreiben onConfigurationChange() und setzt neue LayoutParameters wird mir erlauben, die Größe des Videos, ohne dass ein rebuffer - aber das video wird nach dem Zufallsprinzip Skala zu unterschiedlichen breiten/Höhen bei der Drehung der Bildschirm mehrere Male. Ich habe versucht dabei alle Arten von invalidate() ruft auf der VideoView, versucht, Sie anzurufen, RequestLayout() auf dem parent-RelativeLayout container und versucht einfach so viele verschiedene Dinge, wie ich kann, aber ich kann nicht scheinen, um es richtig zu arbeiten. Jede Beratung würde sehr geschätzt werden!
Hier ist mein code:
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
questionText.setVisibility(View.GONE);
respond.setVisibility(View.GONE);
questionVideo.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
} else {
questionText.setVisibility(View.VISIBLE);
respond.setVisibility(View.VISIBLE);
Resources r = getResources();
int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 150.0f, r.getDisplayMetrics());
questionVideo.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, height));
}
}
EDIT: ich habe entdeckt, dass in logcat einige interessante Ausgabe, die kommt, wenn mein video gedreht, das scheint die Täter - obwohl ich keine Ahnung habe, wie es zu lösen ist:
Logcat-Ausgabe wenn die Größe richtig (nimmt ganze Fenster)
beachten Sie die h=726
12-13 15:37:35.468 1262 1270 I ActivityManager: Config changed: { scale=1.0 imsi=310/4 loc=en_US touch=3 keys=1/1/2 nav=1/1 orien=2 layout=34 uiMode=17 seq=210}
12-13 15:37:35.561 1262 1268 I TIOverlay: Position/X0/Y76/W480/H225
12-13 15:37:35.561 1262 1268 I TIOverlay: Adjusted Position/X1/Y0/W403/H225
12-13 15:37:35.561 1262 1268 I TIOverlay: Rotation/90
12-13 15:37:35.561 1262 1268 I Overlay : v4l2_overlay_set_position:: w=480 h=224
12-13 15:37:35.561 1262 1268 I Overlay : v4l2_overlay_set_position:: w=402 h=726
12-13 15:37:35.561 1262 1268 I Overlay : dumping driver state:
12-13 15:37:35.561 1262 1268 I Overlay : output pixfmt:
12-13 15:37:35.561 1262 1268 I Overlay : w: 432
12-13 15:37:35.561 1262 1268 I Overlay : h: 240
12-13 15:37:35.561 1262 1268 I Overlay : color: 7
12-13 15:37:35.561 1262 1268 I Overlay : UYVY
12-13 15:37:35.561 1262 1268 I Overlay : v4l2_overlay window:
12-13 15:37:35.561 1262 1268 I Overlay : window l: 1
12-13 15:37:35.561 1262 1268 I Overlay : window t: 0
12-13 15:37:35.561 1262 1268 I Overlay : window w: 402
12-13 15:37:35.561 1262 1268 I Overlay : window h: 726
Logcat-Ausgabe wenn die Größe falsch (nimmt kleinen Teil der Vollbild)
beachten Sie die h=480
12-13 15:43:00.085 1262 1270 I ActivityManager: Config changed: { scale=1.0 imsi=310/4 loc=en_US touch=3 keys=1/1/2 nav=1/1 orien=2 layout=34 uiMode=17 seq=216}
12-13 15:43:00.171 1262 1268 I TIOverlay: Position/X0/Y76/W480/H225
12-13 15:43:00.171 1262 1268 I TIOverlay: Adjusted Position/X138/Y0/W266/H225
12-13 15:43:00.171 1262 1268 I TIOverlay: Rotation/90
12-13 15:43:00.179 1262 1268 I Overlay : v4l2_overlay_set_position:: w=480 h=224
12-13 15:43:00.179 1262 1268 I Overlay : v4l2_overlay_set_position:: w=266 h=480
12-13 15:43:00.179 1262 1268 I Overlay : dumping driver state:
12-13 15:43:00.179 1262 1268 I Overlay : output pixfmt:
12-13 15:43:00.179 1262 1268 I Overlay : w: 432
12-13 15:43:00.179 1262 1268 I Overlay : h: 240
12-13 15:43:00.179 1262 1268 I Overlay : color: 7
12-13 15:43:00.179 1262 1268 I Overlay : UYVY
12-13 15:43:00.179 1262 1268 I Overlay : v4l2_overlay window:
12-13 15:43:00.179 1262 1268 I Overlay : window l: 138
12-13 15:43:00.179 1262 1268 I Overlay : window t: 0
12-13 15:43:00.179 1262 1268 I Overlay : window w: 266
12-13 15:43:00.179 1262 1268 I Overlay : window h: 480
Vielleicht jemand weiß, was 'Overlay' ist und warum es nicht immer die richtige Höhe?
InformationsquelleAutor der Frage Mark G. | 2010-12-13
Du musst angemeldet sein, um einen Kommentar abzugeben.
War ich in der Lage, um das problem einzugrenzen, um die onMeasure Funktion in der VideoView Klasse. Durch die Schaffung einer Kind-Klasse und überschreiben der onMeasure Funktion, ich war in der Lage, um die gewünschte Funktionalität zu erhalten.
Dann innerhalb meiner Tätigkeit habe ich nur die folgenden:
Die Zeile:
ist der Schlüssel, um diese Arbeit zu machen. Wenn Sie die setDimensions nennen, ohne diesen Kerl, der das video noch nicht seine Größe.
Die einzige andere Sache, die Sie tun müssen, ist sicherzustellen, dass Sie rufen setDimensions() in der onCreate () - Methode, wie gut oder dein video startet nicht, die Pufferung, wie das video wird nicht ziehen auf eine Fläche von beliebiger Größe.
Einen letzten Schlüssel Teil - wenn Sie sich jemals gewundert, warum die VideoView nicht auf rotation, Größenänderung, die Sie benötigen, um die Dimensionen, die Sie sind Größenänderung, sind entweder genau gleich auf den sichtbaren Bereich oder weniger, als es ist. Ich hatte ein wirklich großes problem, wo ich war, die Einstellung der VideoView Breite/Höhe, um die gesamte display-Größe, wenn ich noch die notification-bar/Titelleiste auf dem Bildschirm und es war nicht die Größe des VideoView überhaupt. Einfach entfernen Sie die Benachrichtigungsleiste und die Titelleiste das problem behoben.
Hoffentlich hilft jemand in der Zukunft!
EDIT: (Juni 2016)
Diese Antwort ist sehr alt (ich glaube android 2.2/2.3) und ist wahrscheinlich nicht so relevant wie die anderen Antworten unten! Schauen Sie zuerst, es sei denn, du bist dev-ing auf ältere Android 🙂
InformationsquelleAutor der Antwort Mark G.
Zunächst alle, vielen Dank für Ihre umfangreichen Antworten.
Ich hatte das gleiche problem, die Videos würden die meisten der Zeit, werden kleiner, oder größer, oder verzerrt innerhalb der VideoView nach einer Drehung.
Ich habe versucht, Ihre Lösung, aber ich habe auch versucht, zufällige Dinge, und durch Zufall habe ich bemerkt, dass wenn mein VideoView konzentriert sich auf seine Eltern, wird es magisch an sich funktioniert (kein custom VideoView benötigt oder nichts).
Um genauer zu sein, mit diesem layout habe ich das problem reproduzieren, das die meiste Zeit:
Mit diesem layout habe ich nie das problem (plus das video zentriert ist, das ist, wie es sein sollte, sowieso ;):
Funktioniert es auch mit
wrap_content
stattmatch_parent
(das video findet noch alle den Raum), das macht nicht viel Sinn für mich.Eh, ich habe keine Erklärung dafür - das sieht aus wie ein VideoView bug zu mir.
InformationsquelleAutor der Antwort BoD
Hier ist eine wirklich einfache Möglichkeit das zu erreichen, was Sie wollen mit minimalem code:
AndroidManifest.xml:
Hinweis: Bearbeiten Sie bei Bedarf für Ihre API umfasst diese 10+, aber niedriger APIs erfordern das entfernen der "screenSize|screenLayout|uiMode" - Teil dieser Zeile
In der "OnCreate" Methode, in der Regel unter "super.onCreate", fügen Sie hinzu:
Und dann irgendwo, meist an der Unterseite, hinzufügen:
Dadurch wird die Größe des Videos auf Vollbild wenn die Ausrichtung geändert hat, ohne die Wiedergabe zu unterbrechen, und erfordert nur das überschreiben der Konfiguration.
InformationsquelleAutor der Antwort LoungeKatt
VideoView verwendet, was heißt ein overlay, das ist ein Bereich, wo das video gerendert ist. Das overlay ist hinter dem Fenster halten der VideoView. VideoView Schläge ein Loch in sein Fenster, so dass das overlay sichtbar ist. Dann hält Sie es in sync mit dem layout (zB. wenn Sie verschieben oder ändern der Größe VideoView, das overlay bewegt und in der Größe verändert).
Da ist ein Fehler irgendwo in der layout-phase, das macht die überlagerung der vorherigen Größe von VideoView.
Um es zu beheben, Unterklasse VideoView und überschreiben onLayout:
und die überlagerung wird die korrekte Größe von VideoView-layout-Abmessungen.
InformationsquelleAutor der Antwort Zapek
Replikation der YouTube-app
Ich es geschafft, erstellen Sie ein Beispiel-Projekt, das nicht erforderlich
android:configChanges="orientation"
oder eine benutzerdefinierteVideoView
. Die daraus resultierende Erfahrung ist identisch wie der YouTube-app Griffe rotation während der video-Wiedergabe. In anderen Worten, das video nicht müssen angehalten werden, re-gepuffert, oder reloaded, und nicht überspringen oder löschen von audio-frames, wenn das Gerät die Orientierung ändert.Optimale Methode
Diese Methode verwendet ein TextureView und seiner begleitenden
SurfaceTexture
als eine Senke für dieMediaPlayer
's aktuelle video-frame. Seit ein SurfaceTexture verwendet eine GL-textur-Objekt (einfach auf die eine Zahl aus der GL Kontext) glauben, dass es okay ist, behalten Sie einen Verweis auf eine SurfaceTexture durch änderungen an der Konfiguration. Die TextureView selbst wird zerstört und neu erstellt während der Konfiguration zu ändern (zusammen mit der backing-Aktivität) und den neu erstellten TextureView ist einfach, aktualisiert mit den SurfaceTexture Referenz, bevor es angeschlossen wird.Habe ich einen voll funktionsfähiges Beispiel zeigen, wie und Wann initialisiert werden Ihr MediaPlayer und eine mögliche MediaController, und ich werde markieren die interessanten Teile, die relevant zu dieser Frage unten:
Da die Lösung verwendet ein beibehalten Fragment eher als eine Aktivität, mit der änderungen an der Konfiguration manuell vornehmen, können Sie voll nutzen, die Konfiguration von spezifischen Ressourcen-inflation-system, als wären Sie natürlich. Leider, wenn Ihre minimale sdk ist unter API 16, Sie wird im wesentlichen muss man
TextureView
(was ich nicht getan habe).Schließlich, wenn Sie interessiert sind, Kasse meine anfängliche Frage Details: mein ursprünglicher Ansatz, das Android media-stack, warum es nicht funktioniert hat, und die Alternative Problemumgehung.
InformationsquelleAutor der Antwort dcow
verwenden :
Auch vergessen Sie nicht, fügen Sie die Zeile unten, um Ihre Aktivität im Manifest:
InformationsquelleAutor der Antwort Rudi
Nahm ich Beispiele von einigen der Antworten hier und habe versucht zu tun, es auf meine Weise. Sieht aus wie eine einfache Lösung.
onConfigurationChange innen ein fragment.Wo das video angezeigt wird im fullscreen im Querformat.Beachten Sie, dass ich ausblenden der Aktionsleiste.
und hier ist mein layout-Datei
Habe ich ein weiteres relativelayout unter diesen, die nicht in diesem layout. Aber das würde keinen Unterschied machen.
InformationsquelleAutor der Antwort Prakash
siehe mein Beispiel-code, es funktioniert für mich
sind und nicht neu erstellen, anzeigen, ändern, wenn die Orientierung
Landschaft
mein source-code hier
InformationsquelleAutor der Antwort vuhung3990
Während Mark37 (sehr nützlich) Antwort funktioniert, ist es erforderlich die Einstellung der Dimensionen manuell (über setDimensions). Dies kann in Ordnung sein, in einer app, wo Sie die gewünschten Maße im Voraus bekannt sind, aber wenn Sie wollen, dass die Aussicht, um zu bestimmen, die Größe automatisch auf der Grundlage der video - Parametern (z.B. um sicherzustellen, dass der ursprüngliche Seitenverhältnis wird beibehalten), ein anderer Ansatz ist erforderlich.
Glück, es stellt sich heraus, das setDimensions Teil ist nicht wirklich notwendig. VideoView ist onMeasure beinhaltet bereits alle notwendigen Logik, so dass, anstatt sich auf jemanden zu setDimensions, ist es möglich, rufen Sie einfach super.onMeasure, und verwenden Sie dann die Ansicht getMeasuredWidth/getMeasuredHeight, um die Feste Größe.
So, die VideoViewCustom Klasse wird einfach:
Diese version erfordert keinen zusätzlichen code im Aufrufer, und übernimmt die volle Vorteil der VideoView bestehenden onMeasure Umsetzung.
Dies ist in der Tat ziemlich ähnlich wie die Ansatz vorgeschlagen von Zapek, die macht im Grunde das gleiche, nur mit onLayout statt onMeasure.
InformationsquelleAutor der Antwort Tomty
Ich versucht, den code von anderen Antworten, aber es hat nicht mein problem zu lösen, denn wenn ich gedreht, den Bildschirm schnell, meine video-Größe gestoßen. Also ich benutze teilweise Ihren code, die ich in einem thread die updates der Fenster sehr schnell.
So, hier ist mein code:
In dieser Art und Weise, die video-Größe wird immer rechts (in meinem Fall).
InformationsquelleAutor der Antwort Curio