Позиционирование медиаконтроллера над видеообзором


У меня есть VideoView, который занимает верхнюю половину активности в портретной ориентации с нижней половиной экрана, показывая некоторые изображения и текст. Я играю видеопоток 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, чтобы появиться там, где я хочу, чтобы на экране?

8 56

8 ответов:

честно говоря, я бы просто написать свой собственный контроллер. На самом деле,Я сделал один раз.

как говорится, попробуйте setAnchorView() -- по моему чтению исходного кода,MediaController появится в нижней части любого вида привязки.

настройка вида якорь будет работать только если размер видео просмотр, как известно, - это не при инициализации. Но вы можете сделать что-то вроде этого:

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 Медиаконтроллера для перемещения якоря вверх):

используйте 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();
            }
    }
}

С java 8:

videoView.setOnPreparedListener(mediaPlayer ->
    mediaPlayer.setOnVideoSizeChangedListener(
        (player, width, height) -> {
            MediaController controller = new MediaController(YourActivity.this);
            videoView.setMediaController(controller);
            controller.setAnchorView(videoView);
        }
    )
);