Android Stack
Android Stack

Reputation: 4314

Full screen videoview without stretching the video

I wonder if I can get a way to let video run via videoview in full screen?

I searched a lot and tried many ways such as:

  1. Apply theme in manifest:

    android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
    

    but that does not force the video to be in full screen.

  2. Apply in activity itself:

    requestWindowFeature(Window.FEATURE_NO_TITLE);  
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,  
        WindowManager.LayoutParams.FLAG_FULLSCREEN);
    

    also does not force the video to be in full screen.

The only way force video to full screen is:

<VideoView android:id="@+id/myvideoview"
    android:layout_width="fill_parent"
    android:layout_alignParentRight="true"
    android:layout_alignParentLeft="true" 
    android:layout_alignParentTop="true" 
    android:layout_alignParentBottom="true" 
    android:layout_height="fill_parent"> 
</VideoView> 

This way it results in full screen video but it stretches the video itself (elongated video) ,

I'm not applying this improper solution to my videoview, so is there is any way to do it without stretching the video?

Video Class:

public class Video extends Activity {
    private VideoView myvid;

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.main);
        myvid = (VideoView) findViewById(R.id.myvideoview);
        myvid.setVideoURI(Uri.parse("android.resource://" + getPackageName() 
            +"/"+R.raw.video_1));
        myvid.setMediaController(new MediaController(this));
        myvid.requestFocus();
        myvid.start();
    }
}

main.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <VideoView
        android:id="@+id/myvideoview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

</LinearLayout>

Upvotes: 32

Views: 89290

Answers (8)

Clay Martin
Clay Martin

Reputation: 249

The current upvoted solution works, but there may be a simpler solution to the original problem. A commenter correctly pointed out that you could resize a VideoView using the same methodology without the cost of converting everything to a SurfaceView. I tested this in one of my apps and it seems to work. Just add the calculated layout parameters to the VideoView in the OnPreparedListener callback:

mInspirationalVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { // mMediaPlayer = mp;

            mp.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() {
                @Override
                public void onSeekComplete(MediaPlayer mp) {
                    if(isPlaying = true) {
                        stopPosition = 0;
                        mp.start();
                        mVideoProgressTask = new VideoProgress();
                        mVideoProgressTask.execute();
                    }
                }
            });


            // so it fits on the screen
            int videoWidth = mp.getVideoWidth();
            int videoHeight = mp.getVideoHeight();
            float videoProportion = (float) videoWidth / (float) videoHeight;


            DisplayMetrics mDisplayMetrics = new DisplayMetrics();
            getWindowManager().getDefaultDisplay().getMetrics(mDisplayMetrics);

            float screenWidth = mDisplayMetrics.widthPixels;
            float screenHeight = mDisplayMetrics.heightPixels;

            float screenProportion = (float) screenWidth / (float) screenHeight;
            android.view.ViewGroup.LayoutParams lp = mInspirationalVideoView.getLayoutParams();

            if (videoProportion > screenProportion) {
                lp.width = screenWidth;
                lp.height = (int) ((float) screenWidth / videoProportion);
            } else {
                lp.width = (int) (videoProportion * (float) screenHeight);
                lp.height = screenHeight;
            }

            mInspirationalVideoView.setLayoutParams(lp);

           ...

        }
    });

Upvotes: 3

Hari Krishnan
Hari Krishnan

Reputation: 21

Here is my function which works for the full screen video without stretching it. It will automatically crop the sides of the video. It worked both portrait and landscape modes.

It was actually taken from the answer.

    public void onPrepared(MediaPlayer mp) {
        int videoWidth = mediaPlayer.getVideoWidth();
        int videoHeight = mediaPlayer.getVideoHeight();

        DisplayMetrics displayMetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        int screenWidth = displayMetrics.widthPixels;
        int screenHeight = displayMetrics.heightPixels;

        float scaleY = 1.0f;
        float scaleX = (videoWidth * screenHeight / videoHeight) / screenWidth;

        int pivotPointX = (int) (screenWidth / 2);
        int pivotPointY = (int) (screenHeight / 2);

        surfaceView.setScaleX(scaleX);
        surfaceView.setScaleY(scaleY);
        surfaceView.setPivotX(pivotPointX);
        surfaceView.setPivotY(pivotPointY);

        mediaPlayer.setLooping(true);
        mediaPlayer.start();
    }

Upvotes: 2

Hiren Patel
Hiren Patel

Reputation: 52790

I have solved this one by Custom VideoView:

I have added VideoView to ParentView in two ways From xml & programatically.

Add Custom class for VideoView named with FullScreenVideoView.java:

import android.content.Context;
import android.util.AttributeSet;
import android.widget.VideoView;

public class FullScreenVideoView extends VideoView {
    public FullScreenVideoView(Context context) {
        super(context);
    }

    public FullScreenVideoView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public FullScreenVideoView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
    }
}

How to bind with xml:

<FrameLayout
   android:id="@+id/secondMedia"
   android:layout_width="match_parent"
   android:layout_height="match_parent">

     <com.my.package.customview.FullScreenVideoView
           android:layout_width="match_parent"
           android:layout_height="match_parent" 
           android:id="@+id/fullScreenVideoView"/>

</FrameLayout>

OR

How to add Programatically VideoView to ParentView:

FullScreenVideoView videoView = new FullScreenVideoView(getActivity());
parentLayout.addView(videoView, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));

Hope this will help you.

Upvotes: -1

Hamiseixas
Hamiseixas

Reputation: 86

Well, I hope it helps FullscreenVideoView

It handles all boring code about surfaceView and fullscreen view and let you focus only in UI buttons.

And you can use the FullscreenVideoLayout if you don't want to build your custom buttons.

Upvotes: 1

caiocpricci2
caiocpricci2

Reputation: 7788

Like this you can set the properties of the video by yourself.

Use a SurfaceView (gives you more control on the view), set it to fill_parent to match the whole screen

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"     
              android:orientation="vertical" 
              android:layout_width="match_parent"
              android:layout_height="fill_parent">

    <SurfaceView
        android:id="@+id/surfaceViewFrame"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_gravity="center" >
    </SurfaceView>
</Linearlayout>

then on your java code get the surface view and add your media player to it

surfaceViewFrame = (SurfaceView) findViewById(R.id.surfaceViewFrame);
player = new MediaPlayer();
player.setDisplay(holder);

set on your media player a onPreparedListener and manually calculate the desired size of the video, to fill the screen in the desired proportion avoiding stretching the video!

player.setOnPreparedListener(new OnPreparedListener() {

        @Override
        public void onPrepared(MediaPlayer mp) {
                    // Adjust the size of the video
    // so it fits on the screen
    int videoWidth = player.getVideoWidth();
    int videoHeight = player.getVideoHeight();
    float videoProportion = (float) videoWidth / (float) videoHeight;       
    int screenWidth = getWindowManager().getDefaultDisplay().getWidth();
    int screenHeight = getWindowManager().getDefaultDisplay().getHeight();
    float screenProportion = (float) screenWidth / (float) screenHeight;
    android.view.ViewGroup.LayoutParams lp = surfaceViewFrame.getLayoutParams();

    if (videoProportion > screenProportion) {
        lp.width = screenWidth;
        lp.height = (int) ((float) screenWidth / videoProportion);
    } else {
        lp.width = (int) (videoProportion * (float) screenHeight);
        lp.height = screenHeight;
    }
    surfaceViewFrame.setLayoutParams(lp);

    if (!player.isPlaying()) {
        player.start();         
    }

        }
    });

I modified this from a tutorial for video streaming that I followed some time ago, can't find it right now to reference it, if someone does please add the link to the answer!

Hope it helps!

EDIT

Ok, so, if you want the video to occupy the whole screen and you don't want it to stretch you will end up with black stripes in the sides. In the code I posted we are finding out what is bigger, the video or the phone screen and fitting it the best way we can.

There you have my complete activity, streaming a video from a link. It's 100% functional. I can't tell you how to play a video from your own device because I don't know that. I'm sure you will find it in the documentation here or here.

public class VideoPlayer extends Activity implements Callback, OnPreparedListener, OnCompletionListener, 
    OnClickListener {   

private SurfaceView surfaceViewFrame;
private static final String TAG = "VideoPlayer";
private SurfaceHolder holder;
private ProgressBar progressBarWait;
private ImageView pause;
private MediaPlayer player; 
private Timer updateTimer;
String video_uri = "http://daily3gp.com/vids/familyguy_has_own_orbit.3gp";  


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.videosample);       


    pause = (ImageView) findViewById(R.id.imageViewPauseIndicator);
    pause.setVisibility(View.GONE);
    if (player != null) {
        if (!player.isPlaying()) {
            pause.setVisibility(View.VISIBLE);
        }
    }


    surfaceViewFrame = (SurfaceView) findViewById(R.id.surfaceViewFrame);
    surfaceViewFrame.setOnClickListener(this);
    surfaceViewFrame.setClickable(false);

    progressBarWait = (ProgressBar) findViewById(R.id.progressBarWait);

    holder = surfaceViewFrame.getHolder();
    holder.addCallback(this);
    holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

    player = new MediaPlayer();
    player.setOnPreparedListener(this);
    player.setOnCompletionListener(this);
    player.setScreenOnWhilePlaying(true);
    player.setDisplay(holder);
}

private void playVideo() {
        new Thread(new Runnable() {
            public void run() {
                try {
                    player.setDataSource(video_uri);
                    player.prepare();
                } catch (Exception e) { // I can split the exceptions to get which error i need.
                    showToast("Error while playing video");
                    Log.i(TAG, "Error");
                    e.printStackTrace();
                } 
            }
        }).start();     
}

private void showToast(final String string) {
    runOnUiThread(new Runnable() {
        public void run() {
            Toast.makeText(VideoPlayer.this, string, Toast.LENGTH_LONG).show();
            finish();
        }
    });
}


public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    // TODO Auto-generated method stub

}

public void surfaceCreated(SurfaceHolder holder) {
    playVideo();
}

public void surfaceDestroyed(SurfaceHolder holder) {
    // TODO Auto-generated method stub

}
//prepare the video
public void onPrepared(MediaPlayer mp) {        
    progressBarWait.setVisibility(View.GONE);

    // Adjust the size of the video
    // so it fits on the screen
    int videoWidth = player.getVideoWidth();
    int videoHeight = player.getVideoHeight();
    float videoProportion = (float) videoWidth / (float) videoHeight;       
    int screenWidth = getWindowManager().getDefaultDisplay().getWidth();
    int screenHeight = getWindowManager().getDefaultDisplay().getHeight();
    float screenProportion = (float) screenWidth / (float) screenHeight;
    android.view.ViewGroup.LayoutParams lp = surfaceViewFrame.getLayoutParams();

    if (videoProportion > screenProportion) {
        lp.width = screenWidth;
        lp.height = (int) ((float) screenWidth / videoProportion);
    } else {
        lp.width = (int) (videoProportion * (float) screenHeight);
        lp.height = screenHeight;
    }
    surfaceViewFrame.setLayoutParams(lp);

    if (!player.isPlaying()) {
        player.start();         
    }
    surfaceViewFrame.setClickable(true);
}

// callback when the video is over
public void onCompletion(MediaPlayer mp) {
    mp.stop();
    if (updateTimer != null) {
        updateTimer.cancel();
    }
    finish();
}

//pause and resume
public void onClick(View v) {
    if (v.getId() == R.id.surfaceViewFrame) {
         if (player != null) {
            if (player.isPlaying()) {
                player.pause();
                pause.setVisibility(View.VISIBLE);
            } else {
                player.start();
                pause.setVisibility(View.GONE);
            }
        }
    }
}

}

Upvotes: 48

Bobbake4
Bobbake4

Reputation: 24857

Have you tried adjusting the underlying surface holder size? Try the code below it should adjust the surface holder to be the same width and height of the screen size. You should still have your activity be full screen without a title bar.

    public class Video extends Activity {
        private VideoView myvid;

        @Override
        public void onCreate(Bundle icicle) {
            super.onCreate(icicle);
            setContentView(R.layout.main);
            myvid = (VideoView) findViewById(R.id.myvideoview);
            myvid.setVideoURI(Uri.parse("android.resource://" + getPackageName() 
                +"/"+R.raw.video_1));
            myvid.setMediaController(new MediaController(this));
            myvid.requestFocus();

            //Set the surface holder height to the screen dimensions
            Display display = getWindowManager().getDefaultDisplay();
            Point size = new Point();
            display.getSize(size);
            myvid.getHolder().setFixedSize(size.x, size.y);

            myvid.start();
        }
    }

Upvotes: 1

Terril Thomas
Terril Thomas

Reputation: 1506

A SurfaceView gives u an optimized drawing surface

public class YourMovieActivity extends Activity implements SurfaceHolder.Callback {
        private MediaPlayer media = null;
        //...

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            media = new MediaPlayer();
            mSurfaceView = (SurfaceView) findViewById(R.id.surface);
            //...
        }
    }

MediaPlayer calls should be wrapped in a try{}.

    @Override
    public void surfaceCreated(SurfaceHolder holder) {

        media.setDataSource("android.resource://" + getPackageName() 
            +"/"+R.raw.video_);
        media.prepare();

            int videoWidth = mp.getVideoWidth();
        int videoHeight = mp.getVideoHeight();

            int screenWidth = getWindowManager().getDefaultDisplay().getWidth();

            android.view.

ViewGroup.LayoutParams layout = mSurfaceView.getLayoutParams();

    layout.width = screenWidth;

    layout.height = (int) (((float)videoHeight / (float)videoWidth) * (float)screenWidth);

    mSurfaceView.setLayoutParams(layout);        

    mp.start();
}

Upvotes: 0

R KiranKumar
R KiranKumar

Reputation: 835

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        videoView1 = (VideoView) findViewById(R.id.videoview);
                String SrcPath = "/mnt/sdcard/final.mp4";
        videoView1.setVideoPath(SrcPath);
        videoView1.setMediaController(new MediaController(this));
        videoView1.requestFocus();      
        videoView1.start();     
    }
}




<VideoView
    android:id="@+id/videoview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_alignParentBottom="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentRight="true"
    android:layout_alignParentTop="true" >
</VideoView>

try this it's working for me

Upvotes: 4

Related Questions