Full screen videoview without stretching the video

老子叫甜甜 提交于 2019-11-26 15:50:35

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

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

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;
            int screenWidth = getWindowManager().getDefaultDisplay().getWidth();
            int screenHeight = getWindowManager().getDefaultDisplay().getHeight();

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

           ...

        }
    });

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

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

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

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.

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!