实现一个播放器里的全屏播放功能

视频播放器的核心是:VideoView

使用AndroidStudio设置Activity的全横屏会出现闪退

解决方法:

把运行类的继承改成Activity就可以了

有两种实现全屏的方法 

第一种是配置xml第二种是运行类中编写代码实现

第一种实现方式:

在xml配置一下当前Activity为横屏不可切换竖屏

1、在清单文件AndroidManifest.xml的Activity标签中加入android:screenOrientation="landscape"

2、在清单文件AndroidManifest.xml的application标签中加入android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"

这里的视频文件是网上的链接 所以要记得加入INTERNET权限

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.szh.day10" >

    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" >
        <activity
            android:name=".VideoViewActivity"
            android:label="@string/title_activity_video_view"
            android:screenOrientation="landscape"
          >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

第二种:

在运行类中加入代码实现全屏

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

现在要实现主页的Activity跳转到全屏的Activity播放的话不能在全屏播放的类中加上

requestWindowFeature(Window.FEATURE_NO_TITLE);

会使主页的Activity没有标题 如果就像让它无标题那就设置 这里的类如果不是继承Activity的话 点击播放就会闪退

想实现的效果如下图:


android视频全屏实现 安卓列表视频全屏_android


android视频全屏实现 安卓列表视频全屏_ide_02


主要效果是为了实现全屏的功能 所以不完善其他功能 视频文件也是指定好的网上文件 没有什么缓冲等等

主页面很简单就是一个按钮 点击按钮后打开全屏播放视频

xml布局如下

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.szh.day10.Index">

   <Button
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:text="播放"
       android:onClick="player3"/>

</RelativeLayout>



主页面的Activity如下

package com.example.szh.day10;

import android.content.Intent;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;


public class Index extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_index);
    }
    public void player3(View view){
        Intent intent = new Intent(this,VideoViewActivity.class);
        startActivity(intent);
    }
}

第二个界面全屏功能

已具备的功能:

1、在全屏状态下可以左右滑动定位到影片的进度位置 这里设置的为1秒

2、seekBar控件可以滑动定位到指定视频位置播放 

3、暂停

4、播放

5、停止

6、单击视频播放器的时候回出现控制器 控制器在2秒后隐藏 控制器的显示和隐藏调用了简单的动画效果

代码如下

package com.example.szh.day10;

import android.app.Activity;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.VideoView;

import java.util.Timer;
import java.util.TimerTask;


public class VideoViewActivity extends Activity {

    private VideoView videoView;
    private SeekBar seekBar;
    private Timer timer;//javase中的计时器
    private TimerTask timerTask;//任务栈
    private LinearLayout control;//视频的控制器对应的布局ID
    private int pause = 0;//暂停用来获取暂停时影片的进度
    private int startX;//落下的X坐标
    int seek =0;//左右滑动时更新seek的值修改到SeekBar中
    int up = 0;//计算用户落下的坐标和离开时的坐标可供下面判断左右滑动
    int change = 0;//用户滑动的坐标变化
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_video_view);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        control = (LinearLayout) findViewById(R.id.control);
        seekBar = (SeekBar) findViewById(R.id.sb);
        videoView = (VideoView) findViewById(R.id.videoView);
        //播放地址
        videoView.setVideoPath("http://hc.yinyuetai.com/uploads/videos/common/5BAA0126EA2C38ACF34DA" +
                "07ECF52DCBB.flv?sc\\u003d63348fe3ecf23d32\\u0026br\\u003d549\\u0026vid\\u003d32456" +
                "\\u0026aid\\u003d311\\u0026area\\u003dHT\\u0026vst\\u003d2");
        //开始播放
        videoView.start();
        //setOnPreparedListener数据准备事件,准备好了才给SeekBar赋值
        /*
        * int duration = videoView.getDuration();//获取视频的时长
        * seekBar.setMax(duration);//设置seekBar的最大值为视频的时长
        * 这里的赋值不能写在监听事件以外
        * 之前我写在了timerTask里面导致播放断断续续
        * 写在了videoView.start();之后又获取不到视频的长度
        * 想了许久后发现之前写的MP3播放是需要准备监听事件去解决主线程阻塞的情况,
        * 于是就想 是不是MP4也需要让它先判断是否准备完成、于是上网浏览了下
        * setOnPreparedListener的用法后才知道 视频也是需要这个事件才可以
        *
        * */
        videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {
                int duration = videoView.getDuration();//获取视频的时长
                seekBar.setMax(duration);//设置seekBar的最大值为视频的时长
            }
        });
        /*
        * 新建javase中的计时器和任务栈
        * 任务栈中要实现SeekBar的进度的实时更新
        *
        * */
        timer = new Timer();
        timerTask = new TimerTask() {
            @Override
            public void run() {
                //获取当前视频的时间
                int progess = videoView.getCurrentPosition();
                //设置SeekBar的进度
                seekBar.setProgress(progess);
            }
        };
        //每1秒执行一次 立刻执行
        timer.schedule(timerTask, 0, 1000);
        //SeekBar的滑动事件
        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            //值的改变 不实现这个功能
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {

            }
            //开始触摸SeekBar监听事件不实现这个功能
            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }
            //用户滑动后离开SeekBar调用的事件
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                //获取离开时的值
                int progress = seekBar.getProgress();
                //设置视频从该值开始播放
                videoView.seekTo(progress);
            }
        });

    }
    /*
    * 开始播放按钮
    * */
    public void start(View view){
        //先判断是否暂停
        if(pause!=0){
            videoView.start();
            videoView.seekTo(pause);
            pause=0;
        }else if(!videoView.isPlaying()&&pause==0){
            videoView.start();
        }


    }

    /*
    * 暂停 并把当前视频的时间赋值给pause变量
    * */
    public void pause(View view){
        videoView.pause();
        pause = videoView.getCurrentPosition();
    }
    /*
    * 停止 设置视频到0秒播放并且暂停
    * */
    public void stop(View view){
        videoView.seekTo(0);
        videoView.pause();
    }

    //Activity被销毁后要释放掉资源
    @Override
    protected void onDestroy() {
        timer.cancel();
        timerTask.cancel();
        timer = null;
        timerTask = null;
        super.onDestroy();
    }

//为Activity设置触摸事件
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //event.getAction()获取事件的状态
        switch (event.getAction()){
            //当用户单击屏幕的时候控制被调出
            case MotionEvent.ACTION_DOWN://按下
                //获取用户按下时的X坐标
                startX = (int) event.getX();
                //把判断左右滑动的值归0
                up=0;
                //判断控制器是否隐藏 一开始布局的配置是先让控制隐藏
                if(control.getVisibility()== View.VISIBLE){//如果控制器可见就设置为不可见
                    control.setVisibility(View.INVISIBLE);//隐藏
                    //移动的动画 这里不做详细解析
                    TranslateAnimation ta = new TranslateAnimation(Animation.RELATIVE_TO_SELF
                            ,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0F,Animation.RELATIVE_TO_SELF,1.0F);
                    //动画的时间
                    ta.setDuration(200);
                    //动画开始
                    control.startAnimation(ta);

                }else if(control.getVisibility()== View.INVISIBLE){//如果控制器不可见就设置可见
                    control.setVisibility(View.VISIBLE);//显示
                    //移动的动画 这里不做详细解析
                    TranslateAnimation ta = new TranslateAnimation(Animation.RELATIVE_TO_SELF
                            ,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,1.0f,Animation.RELATIVE_TO_SELF,0f);
                    //动画的时间
                    ta.setDuration(200);
                    //动画开始
                    control.startAnimation(ta);
                    //显示后用户没有再进行页面的任何操作时 2秒后自动隐藏控制器
                    new Thread(){
                        @Override
                        public void run() {
                            try {
                                Thread.sleep(2000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    control.setVisibility(View.INVISIBLE);//隐藏
                                    TranslateAnimation ta = new TranslateAnimation(Animation.RELATIVE_TO_SELF
                                            ,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0F,Animation.RELATIVE_TO_SELF,1.0F);
                                    ta.setDuration(200);
                                    control.startAnimation(ta);
                                }
                            });
                        }
                    }.start();
                }
            break;

            case MotionEvent.ACTION_MOVE://移动
               change  = (int) event.getX();//获取到移动的X轴的值
                up = startX - change;//实时赋值给up变量
            break;
            case MotionEvent.ACTION_UP://离开
                up = 0;
                break;
        }
        //使用startX - change得到的值  结果为负 就是向右移动  反之向左移动
        if(up<0){
            //获取当前视频的播放进度
            int currentPosition = videoView.getCurrentPosition();
            //当前视频的播放进度再加1秒
            seek = currentPosition + 1000;
            //这个值不能大于视频的长度
            if (seek <= videoView.getDuration()) {
                videoView.seekTo(seek);
            }
        }else if(up>0){
            //获取当前视频的播放进度
            int currentPosition = videoView.getCurrentPosition();
            //当前视频的播放进度减1秒
            seek = currentPosition - 1000;
            //这个值不能小于0
            if (seek >= 0) {
                videoView.seekTo(seek);
            }
        }
        return super.onTouchEvent(event);

    }

}

主清单文件如下

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.szh.day10" >

    <uses-permission android:name="android.permission.INTERNET" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
<activity
            android:name=".VideoViewActivity"
            android:label="@string/title_activity_video_view"
            android:screenOrientation="landscape" >
        </activity>
        <activity
            android:name=".Index"
            android:label="@string/title_activity_index" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>



使用工具:AndroidStudio

功能并不完善 以后有时间的话回头继续写 目标把它做成一个功能完善的视频播放器~~~~~~~~~~~~~~~~