Ответ 1
Честно говоря, я бы просто написал свой собственный контроллер. Фактически, я сделал раз.
При этом попробуйте setAnchorView()
- по чтению исходного кода, MediaController
появится в нижней части любого вида привязки.
У меня есть VideoView, который занимает верхнюю половину Activity в портретной ориентации, а нижняя половина экрана показывает некоторые изображения и текст. При запуске Activity я воспроизвожу видеопоток rtsp в виде видео. Я подключил MediaController к VideoView с помощью следующего кода:
MediaController controller = new MediaController(this);
controller.setAnchorView(this.videoView);
controller.setMediaPlayer(this.videoView);
this.videoView.setMediaController(controller);
Когда я нажимаю VideoView, чтобы вызвать MediaController на экране, я ожидал, что элементы управления воспроизведением будут отображаться в нижней области VideoView (внизу MediaController даже в нижней части VideoView). Вместо этого MediaController появляется на экране снизу вниз, накладывая часть графики и текста, которые у меня ниже VideoView.
Есть ли еще несколько шагов, которые нужно предпринять, чтобы заставить MediaController появляться там, где я хочу, чтобы он отображался на экране?
Честно говоря, я бы просто написал свой собственный контроллер. Фактически, я сделал раз.
При этом попробуйте setAnchorView()
- по чтению исходного кода, MediaController
появится в нижней части любого вида привязки.
Настройка представления привязки будет работать только в том случае, если размер видеоизображения известен - он не будет установлен на init. Но вы можете сделать что-то вроде этого:
video.setOnPreparedListener(new OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mp.setOnVideoSizeChangedListener(new OnVideoSizeChangedListener() {
@Override
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
/*
* add media controller
*/
mc = new MediaController(YourActivity.this);
video.setMediaController(mc);
/*
* and set its position on screen
*/
mc.setAnchorView(video);
}
});
}
});
Я нашел очень легкое решение.
Просто оберните videoView в FrameLayout, затем вы можете добавить MediaController к этому FrameLayout из кода, например:
MediaController mc = new MediaController(context);
videoView.setMediaController(mc);
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
lp.gravity = Gravity.BOTTOM;
mc.setLayoutParams(lp);
((ViewGroup) mc.getParent()).removeView(mc);
((FrameLayout) findViewById(R.id.videoViewWrapper)).addView(mc);
EDIT: поскольку я опубликовал этот ответ, я столкнулся с множеством проблем с тем, чтобы заставить его спрятаться и контролировать его размер, поэтому я закончил делать это, я только создал свой собственный макет с элементами управления, с которыми я мог бы анимировать и работать без головные боли
Я сталкиваюсь с той же проблемой в последнее время, используя setAnchorView (videoView), полностью установит контроллер под VideoView вместо зависания в нижней области. Мой VideoView - один третий экран в верхней области, поэтому контроллер в конечном итоге покрывает любой вид в VideoView.
Ниже приводится способ, которым я в конечном итоге делаю это, не создавая полномасштабный пользовательский контроллер (только переопределение onSizeChanged
MediaController для перемещения якоря):
Используйте FrameLayout в качестве привязки для MediaContoller, заверните его вместе с VideoView, как показано ниже:
<RelativeLayout
android:id="@+id/videoLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.3"
android:layout_gravity="center"
android:background="#000000">
<VideoView
android:id="@+id/videoView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true" />
<FrameLayout android:id="@+id/controllerAnchor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
/>
</RelativeLayout>
Создайте собственный MediaController, который будет перемещать FrameLayout вверх (с привязанным к нему MediaController, когда он изменится):
public class MyMediaController extends MediaController
{
private FrameLayout anchorView;
public MyMediaController(Context context, FrameLayout anchorView)
{
super(context);
this.anchorView = anchorView;
}
@Override
protected void onSizeChanged(int xNew, int yNew, int xOld, int yOld)
{
super.onSizeChanged(xNew, yNew, xOld, yOld);
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) anchorView.getLayoutParams();
lp.setMargins(0, 0, 0, yNew);
anchorView.setLayoutParams(lp);
anchorView.requestLayout();
}
}
Используйте специальный контроллер выше вместо стандартного, а затем привяжите его к FrameLayout:
protected void onCreate(Bundle savedInstanceState)
{
//...
videoView = (VideoView) findViewById(R.id.videoView1);
videoController = new MyMediaController(this, (FrameLayout) findViewById(R.id.controllerAnchor));
videoView.setMediaController(videoController);
//...
}
public void onPrepared(MediaPlayer mp)
{
videoView.start();
FrameLayout controllerAnchor = (FrameLayout) findViewById(R.id.controllerAnchor);
videoController.setAnchorView(controllerAnchor);
}
Я использую этот код для его решения.
mediaController.setPadding(0, 0, 0, px);
чтобы установить представление mediacontroller в нужную позицию. Надеюсь, это поможет вам.
//It work good with me
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<VideoView
android:id="@+id/videoview"
android:layout_width="640dp"
android:layout_height="400dp"
android:layout_centerInParent="true" >
</VideoView>
<FrameLayout
android:id="@+id/videoViewWrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" >
</FrameLayout>
</RelativeLayout>
package com.example.videoview;
import android.app.Activity;
import android.content.res.Configuration;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.media.MediaPlayer.OnVideoSizeChangedListener;
import android.os.Bundle;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.MediaController;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.Toast;
import android.widget.VideoView;
public class MainActivity extends Activity {
// private String path = "http://clips.vorwaerts-gmbh.de/VfE_html5.mp4";
private String path = "http://2387227f13276d2e8940-fbe0b8d9df729a57ca0a851a69d15ebb.r55.cf1.rackcdn.com/hero_2012_demo.mp4";
private VideoView mVideoView;
MediaController mc;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (mVideoView != null)
return;
/**
* TODO: Set the path variable to a streaming video URL or a local media
* file path.
*/
mVideoView = (VideoView) findViewById(R.id.videoview);
mVideoView.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
Toast.makeText(MainActivity.this, "The End", Toast.LENGTH_LONG)
.show();
}
});
if (path == "") {
// Tell the user to provide a media file URL/path.
Toast.makeText(
MainActivity.this,
"Please edit MainActivity, and set path"
+ " variable to your media file URL/path",
Toast.LENGTH_LONG).show();
} else {
/*
* Alternatively,for streaming media you can use
* mVideoView.setVideoURI(Uri.parse(path));
*/
mVideoView.setVideoPath(path);
mVideoView
.setMediaController(new MediaController(MainActivity.this));
mVideoView.requestFocus();
mVideoView.setOnPreparedListener(new OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
mp.setOnVideoSizeChangedListener(new OnVideoSizeChangedListener() {
@Override
public void onVideoSizeChanged(MediaPlayer mp,
int width, int height) {
/*
* add media controller
*/
mc = new MediaController(MainActivity.this);
mVideoView.setMediaController(mc);
/*
* and set its position on screen
*/
mc.setAnchorView(mVideoView);
((ViewGroup) mc.getParent()).removeView(mc);
((FrameLayout) findViewById(R.id.videoViewWrapper))
.addView(mc);
mc.setVisibility(View.INVISIBLE);
}
});
mVideoView.start();
}
});
mVideoView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
if (mc != null) {
mc.setVisibility(View.VISIBLE);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mc.setVisibility(View.INVISIBLE);
}
}, 2000);
}
return false;
}
});
}
}
private RelativeLayout.LayoutParams paramsNotFullscreen, paramsFullscreen;
/**
* handle with the configChanges attribute in your manifest
*/
@Override
public void onConfigurationChanged(Configuration newConfig) {
// TODO Auto-generated method stub
super.onConfigurationChanged(newConfig);
if (paramsFullscreen == null) {
paramsNotFullscreen = (RelativeLayout.LayoutParams) mVideoView
.getLayoutParams();
paramsFullscreen = new LayoutParams(paramsNotFullscreen);
paramsFullscreen.setMargins(0, 0, 0, 0);
paramsFullscreen.height = ViewGroup.LayoutParams.MATCH_PARENT;
paramsFullscreen.width = ViewGroup.LayoutParams.MATCH_PARENT;
paramsFullscreen.addRule(RelativeLayout.CENTER_IN_PARENT);
paramsFullscreen.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
paramsFullscreen.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
paramsFullscreen.addRule(RelativeLayout.ALIGN_PARENT_TOP);
paramsFullscreen.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
}
// To fullscreen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
mVideoView.setLayoutParams(paramsFullscreen);
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
mVideoView.setLayoutParams(paramsNotFullscreen);
}
}
@Override
protected void onPause() {
if (mVideoView.isPlaying()) {
mVideoView.pause();
}
super.onPause();
}
@Override
public void onBackPressed() {
if (mVideoView != null) {
mVideoView.stopPlayback();
}
finish();
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.videoview"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.videoview.MainActivity"
android:configChanges="orientation|screenSize"
android:label="@string/app_name"
android:theme="@android:style/Theme.Dialog" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Это первый раз, когда я отвечаю на вопрос в stackoverflow, я только вставляю VideoView внутри FrameLayout с одинаковыми мерами. MediaController будет в нижней части FrameLayout. Это сработало для меня:
main_activity.XML:
<FrameLayout
android:id="@+id/frame_layout_video"
android:layout_centerHorizontal="true"
android:layout_width="wrap_content"
android:layout_height="400dp">
<VideoView
android:id="@+id/video_select"
android:layout_width="wrap_content"
android:layout_height="400dp"
android:adjustViewBounds="true"
android:clickable="true"
android:scaleType="centerCrop"
/>
</FrameLayout>
MainActivity.java:
@Override
public void onClick(View v) {
int i = v.getId();
if(i == R.id.select_video){
selectVideo();
}
private void selectVideo(){
//this code is to get videos from gallery:
Intent galleryIntent = new Intent(Intent.ACTION_GET_CONTENT);
galleryIntent.addCategory(Intent.CATEGORY_OPENABLE);
galleryIntent.setAction(Intent.ACTION_GET_CONTENT);
galleryIntent.setType("video/*");
startActivityForResult(galleryIntent, GALLERY_REQUEST);
MediaController mediaController = new MediaController(this);
mediaController.setAnchorView(mVideo);
//mVideo is the VideoView where I insert the video
mVideo.setMediaController(mediaController);
mVideo.pause();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case 1:
if (resultCode == RESULT_OK) {
mVideoUri = data.getData();
mVideo.setVideoURI(mVideoUri);
mVideo.start();
}
}
}