开发者

MediaController positioning over VideoView

开发者 https://www.devze.com 2023-01-15 10:01 出处:网络
I have a VideoView that takes up the top half of the Activity in portrait orientation with the bottom half of the screen showing some images and text.I am playing a rtsp video stream in the video view

I have a VideoView that takes up the top half of the Activity in portrait orientation with the bottom half of the screen showing some images and text. I am playing a rtsp video stream in the video view when the Activity starts. I have attached a MediaController to the VideoView via the following code:

    MediaController controller = new MediaController(this);
    controller.setAnchorView(this.videoView);
    controller.setMediaPlayer(this.videoView);
    this.videoView.setMediaController(controller);

When I tap the VideoView to bring up the MediaController on the screen I expected the playback controls to appear overlaying the bottom area of the VideoView (the bottom of the MediaController even with the bottom of the VideoView). Instead the MediaController pops up lower down on the screen, overlaying some of the graphics and text I have below the VideoView.

Are there some additional steps I need to take to get the MediaController to appear where I want it to on the 开发者_如何学JAVAscreen?


Setting the anchor view will only work if the videoview size is known - it will not be upon init. But you can do something like this:

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


I found really easy solution.

Just wrap the videoView in a FrameLayout then you can add the MediaController to that FrameLayout from code, like this:

    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: since I posted this answer I ran into a lot of issues with getting it to hide and with controlling its size so what I ended up doing was I just created my own layout with controls that I could animate and work with without headaches


I encounter the same problem recently, using setAnchorView(videoView) will set the controller fully under VideoView instead hovering on the bottom area of it. My VideoView is one third screen in upper area, so the controller end up covering whatever View under VideoView.

Below is the way I end up doing it without writing full-blown custom controller (only overriding onSizeChanged of MediaController to move anchor up) :

Use FrameLayout as an anchor for MediaContoller, wrap it up together with VideoView as below :

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

Create custom MediaController that will move FrameLayout up (with MediaController that is anchored to it will follow) when its size changed :

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

Use the custom controller above in place of the standard one and then anchor it to the 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);                
}


I use this code to solve it.

mediaController.setPadding(0, 0, 0, px);

to set the mediacontroller view to the position you want. Hope this help you.


Try setAnchorView() -- by my reading of the source code, the MediaController will appear at the bottom of whatever the anchor view is.


Put your video view inside a linear layout

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.hp.videoplayer.MainActivity">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <VideoView
            android:layout_width="300dp"
            android:layout_height="180dp"
            android:id="@+id/player"
            android:layout_marginTop="40dp"
            android:layout_centerHorizontal="true"/>

    </LinearLayout>

</RelativeLayout>


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


I did it by wrapping the VideoView inside a LinearView such that the LinearView has layout_width="match_parent" so that it always stretches to the extent of the screen but layout_height="wrap_content" so that the height of the linear view is always fixed to the height of the content. This way when the video plays the controls are always positioned with the VideoView.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    tools:context=".DisplayClipActivity">

    <VideoView android:id="@+id/episode_clip"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</LinearLayout>

and the code for the Activity:

// create media controller
val mediaController = MediaController(this@DisplayClipActivity)
mediaController.setAnchorView(videoView)
mediaController.setMediaPlayer(videoView)

// video view
videoView.setVideoURI(uri)
videoView.setMediaController(mediaController)
videoView.start()


this is the first time I answer a question in stackoverflow, I only insert a VideoView inside a FrameLayout with same measures both. MediaController will be at the bottom of the FrameLayout. This worked for me:

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


With java 8:

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

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号