您的位置:首页 > 其它

利用VideoView简单实现视频播放 包括 横竖屏切换 声音 亮度 暂停

2017-05-04 21:35 996 查看
          利用Google给的原组件VideoView来简单的实现视频播放.包括播放,暂停,横竖屏切换,声音的改变,屏幕亮度的改变,当声音改变时,会自动调用系统给的声音条,而当滑动亮度的时候需要自己给写个seekbar.

         由于如果刚开始我想让视频在竖屏的时候充满整个屏幕,当在布局中写上mach_parent的时候,他不会充满屏幕,所以我重写了一个类,让它继承VideoView,重写onMeasure方法,在这个里边会获取设备的宽高,然后设置给它.

public class FullVideoView extends VideoView {

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

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//必须得注掉 不然的话就会默认的返回布局中的宽高
//        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//获取设备中的的总宽高
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);

//将这些值返回到布局当中使得可以使用
setMeasuredDimension(widthMeasureSpec,heightMeasureSpec);
}
}


       进入布局的设置  把你所有需要的设置上

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_video"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.fei.advanceseven.VideoActivity">

<FrameLayout
android:id="@+id/video_container"
android:layout_width="match_parent"
android:layout_height="240dp">
<com.example.fei.advanceseven.widget.FullVideoView
android:id="@+id/videoView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

<!-- 播放的控制器 :
屏幕中间有播放暂停的按钮
屏幕的底部,播放时间,总时间,seekBar
是否全屏按钮
-->

<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<SeekBar
android:visibility="gone"
android:id="@+id/brightness_display"
android:layout_marginTop="20dp"
android:layout_width="200dp"
android:layout_gravity="center_horizontal"
android:layout_height="wrap_content"/>
<CheckBox
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center"
android:id="@+id/pause_play"
android:button="@null"
android:gravity="center"
android:background="@drawable/pause_play_selector"
/>

<LinearLayout
android:id="@+id/bottem_controller"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_gravity="bottom"
android:orientation="horizontal"
>
<TextView
android:id="@+id/current_position"
android:layout_width="50dp"
android:layout_height="match_parent"
android:text="00:00"
android:textColor="#fff"
android:gravity="center"
android:layout_marginLeft="5dp"
/>
<SeekBar
android:id="@+id/progress_controller"
android:layout_width="0dp"
android:layout_gravity="center"
android:layout_height="match_parent"
android:layout_weight="1"
/>
<TextView
android:id="@+id/duration"
android:gravity="center"
android:text="29:59"
android:textColor="#fff"
android:layout_width="50dp"
android:layout_height="match_parent"/>
<CheckBox
android:id="@+id/full_screen_controller"
android:layout_width="40dp"
android:button="@null"
android:gravity="center"
android:background="@drawable/full_screen_selector"
android:layout_height="40dp"/>
</LinearLayout>

</FrameLayout>
</FrameLayout>
</RelativeLayout>


         进入主界面的代码设置,上边基本上都备注上每一步的原理  里边还包含了当点击回退键的时候让它在2秒内连续点击时退出程序.

public class VideoActivity extends AppCompatActivity implements MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, CompoundButton.OnCheckedChangeListener,Handler.Callback, SeekBar.OnSeekBarChangeListener {

private FullVideoView mFullVideoView;
private TextView curent_position,duration;
private CheckBox pause_play,full_screen_controller;

//VideoView的容器
private FrameLayout video_container;

private String video_url = "http://ips.ifeng.com/video19.ifeng.com/video09/2017/05/02/4604457-102-1119.mp4";

private Handler mHandler = new Handler(this);

private SeekBar progress_ctroller;

private LinearLayout bottem_controller;
private int mHeight;

private SeekBar bright_display;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video);

initView();

}

public SeekBar getBright_display() {
return bright_display;
}

private void initView() {

//设置亮度的seekbar
bright_display = (SeekBar) findViewById(R.id.brightness_display);

mFullVideoView = (FullVideoView) findViewById(R.id.videoView);

//时间控件
curent_position = (TextView) findViewById(R.id.current_position);
duration = (TextView) findViewById(R.id.duration);
// 2 设置暂停
pause_play = (CheckBox) findViewById(R.id.pause_play);
pause_play.setOnCheckedChangeListener(this);
// 3 是否全屏
full_screen_controller = (CheckBox) findViewById(R.id.full_screen_controller);
full_screen_controller.setOnCheckedChangeListener(this);

// 5 设置SeekBard 并设置他的点击事件
progress_ctroller = (SeekBar) findViewById(R.id.progress_controller);
progress_ctroller.setOnSeekBarChangeListener(this);

//        mFullVideoView.setVideoPath(video_url);
mFullVideoView.setVideoURI(Uri.parse("android.resource://"+getPackageName()+ File.separator+R.raw.music_video));
// 1, 设置mFullVideoView的点击事件  是指预加载和加载错误
mFullVideoView.setOnPreparedListener(this);
mFullVideoView.setOnErrorListener(this);

bottem_controller = (LinearLayout) findViewById(R.id.bottem_controller);

// 4 设置最外层frameLayout的点击事件
video_container = (FrameLayout) findViewById(R.id.video_container);

//因为设置点击事件,他的事件分发就会被消费掉,使得下边的ontouth没用  因为他没有返回值 默认是消费掉

//        video_container.setOnClickListener(new View.OnClickListener() {
//            @Override
//            public void onClick(View view) {
//                bottem_controller.setVisibility(View.VISIBLE);
//                mHandler.sendEmptyMessageDelayed(PAUSE_AUTO_DISAPPEAR,3000);
//            }
//        });
video_container.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction()){
case MotionEvent.ACTION_DOWN:
//checkBox和LinearLayout显示
pause_play.setVisibility(View.VISIBLE);
bottem_controller.setVisibility(View.VISIBLE);
mHandler.sendEmptyMessageDelayed(PAUSE_AUTO_DISAPPEAR,3000);
break;
}

return false;//不修改 点击事件还会继续传递
}
});

//handler发送消息  3秒之后播放和暂停的按钮消失
mHandler.sendEmptyMessageDelayed(PAUSE_AUTO_DISAPPEAR,3000);
}

@Override
public void onPrepared(MediaPlayer mediaPlayer) {

//当刚进入时让按钮默认是选中状态,视屏默认是播放状态
pause_play.setChecked(true);//让视屏进行播放

}

@Override
public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
//当视屏播放错误时,弹出一个对话框
AlertDialog.Builder builder = new AlertDialog.Builder(this);

builder.setIcon(R.mipmap.ic_launcher);
builder.setMessage("无法播放");
builder.setTitle("问题");
builder.setNegativeButton("取消",null);
builder.create().show();

return true;
}

//checkBox状态栏发生改变的监听  两个checkbox的状态栏
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean user) {
switch (compoundButton.getId()){
case R.id.pause_play:
if (user){//用户选中 视频播放 显示成暂停的图标
//首先视频播放
mFullVideoView.start();
//修改播放的时间 handler帮助每隔一秒更新播放进度
mHandler.sendEmptyMessageDelayed(UPDATE_PROGRESS,1000);

}else {
mFullVideoView.pause();
//移除 不让他继续去发送handler
mHandler.removeMessages(UPDATE_PROGRESS);
}
break;
case R.id.full_screen_controller:
if (user){//用户点击了  全屏展示
//设置全屏
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
//设置手机屏幕横向
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

//需要修改VieoView 的高度  如果不修改 当它横屏时不会去充满整个屏幕
//首先获得原来的高度
mHeight = video_container.getHeight();
//重新制定高度
ViewGroup.LayoutParams params = video_container.getLayoutParams();
params.height = ViewGroup.LayoutParams.MATCH_PARENT;

video_container.setLayoutParams(params);

}else {//从全屏状态回去
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
//还原之前的高度
ViewGroup.LayoutParams portrait_params = video_container.getLayoutParams();
portrait_params.height = mHeight;
video_container.setLayoutParams(portrait_params);
}
break;
}
}

//更新进度的标志
public static final int UPDATE_PROGRESS = 1;
public static final int PAUSE_AUTO_DISAPPEAR = 2;//播放和暂停按钮设置
public static final int BRIGHTNESS_DISPLAY_DISAPPEAR = 3;
@Override
public boolean handleMessage(Message message) {
switch (message.what){
case UPDATE_PROGRESS://更新进度
//视频总时间  设置它的总时间是多少
int duration = mFullVideoView.getDuration();
if (progress_ctroller.getMax()==100){
progress_ctroller.setMax(duration);
}
CharSequence format = DateFormat.format("mm:ss", duration);
this.duration.setText(format);

//设置当前播放的进度 并将当前的播放进度设置文本中

int currentPosition = mFullVideoView.getCurrentPosition();
CharSequence current_position = DateFormat.format("mm:ss", currentPosition);
this.curent_position.setText(current_position);

//设置seekbar的当前进度
progress_ctroller.setProgress(currentPosition);
mHandler.sendEmptyMessageDelayed(UPDATE_PROGRESS,1000);
break;
case PAUSE_AUTO_DISAPPEAR:
bottem_controller.setVisibility(View.GONE);
pause_play.setVisibility(View.GONE);
break;
case BRIGHTNESS_DISPLAY_DISAPPEAR:
bright_display.setVisibility(View.GONE);
break;
}
return true;
}

//seekbar点击事件实现的方法 当拉动的时候使得视屏也跟着动
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
if (b){
mFullVideoView.seekTo(i);
}
}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {

}

@Override
public void onStopTrackingTouch(SeekBar seekBar) {

}

private  boolean isLandscape;

//横竖屏回调的方法 当没法在返回事件中写的时候 应该去重写这个方法,当横竖屏切换时必然会回调该方法
@Override
public void onConfigurationChanged(Configuration newConfig) {
switch (newConfig.orientation){
case Configuration.ORIENTATION_LANDSCAPE://横屏
isLandscape = true;
break;
case Configuration.ORIENTATION_PORTRAIT://竖屏
isLandscape = false;
break;
}
super.onConfigurationChanged(newConfig);
}

private long last_time = 0;
//点击回退键  如果是全屏,点击时首先回到竖屏
@Override
public void onBackPressed() {

Log.e("flag", "onBackPressed: +aaaaaaaaaaaaaaaaaaaaaaaaaa" );
//判断是否是横屏
if (isLandscape){
//设置屏幕为竖屏
full_screen_controller.setChecked(false);
}else {
//超过两秒
if (System.currentTimeMillis()-last_time>2000){
Toast.makeText(this,"再次点击退出程序",Toast.LENGTH_LONG).show();
last_time = System.currentTimeMillis();
}else {
super.onBackPressed();
}

}

}
private float laxt_x,laxt_y;
//手指在屏幕上滑动时 快进 快退 声音 屏幕亮度
@Override
public boolean onTouchEvent(MotionEvent event) {
if (isLandscape){//手机横屏
switch (event.getAction()){
case MotionEvent.ACTION_DOWN://手指按下
//手指按下 记录
laxt_x = event.getX();
laxt_y = event.getY();
break;
case MotionEvent.ACTION_MOVE://手指在屏幕上移动
//如果在x轴方向移动的变化大于y轴  快进 快退
float x = event.getX();
float y = event.getY();
if (Math.abs(x-laxt_x)>Math.abs(y-laxt_y)){//快进,退
if (Math.abs(x-laxt_x)>10){
int widthPixels = this.getResources().getDisplayMetrics().widthPixels;
float xDelta = x - laxt_x;
if (x-laxt_x>10){//进
forwa(xDelta,widthPixels);
}else if (x-laxt_x<-10){//退

backward(xDelta,widthPixels);// 该值是负数
}
}
}else {//视屏亮度
//手机屏幕左半部分 修改亮度
if (Math.abs(y-laxt_y)>10){//用户有意识进行滑动
float yDilta = y - laxt_y;
//y轴方向的总高度
int heightPixels = this.getResources().getDisplayMetrics().heightPixels;

if (x<this.getResources().getDisplayMetrics().widthPixels/2){
//
if (y-laxt_y>10){
LightnessController.turnDown(this,yDilta,heightPixels);
}else if (y-laxt_y<-10){
LightnessController.turnUp(this,yDilta,heightPixels);
}
}else {
//手机屏幕右半部分 修改声音
if (y-laxt_y>10){//向下移动 声音降低
AudioController.turnDown(this,yDilta,heightPixels);
}else if (y-laxt_y<-10){//向上移动,声音反放打
AudioController.turnup(this,yDilta,heightPixels);
}
}
}

}

break;
case MotionEvent.ACTION_UP:
//修改手指滑动的位置
laxt_x = event.getX();
laxt_y = event.getY();
mHandler.sendEmptyMessageDelayed(BRIGHTNESS_DISPLAY_DISAPPEAR,1000);
break;
}
}else {//竖屏展示

}
return super.onTouchEvent(event);
}

private void backward(float xDelta, int widthPixels) {
int duration = mFullVideoView.getDuration();
int currentPosition = mFullVideoView.getCurrentPosition();
float durationDelta = xDelta / widthPixels * duration;//负数

int video_move_position = (int) Math.max(0, currentPosition + durationDelta);
mFullVideoView.seekTo(video_move_position);

progress_ctroller.setProgress(video_move_position);
//当前播放的时间
curent_position.setText(DateFormat.format("mm:ss",video_move_position));
}

//视屏快进
private void forwa(float xDelta, int widthPixels) {
int duration = mFullVideoView.getDuration();
int currentPosition = mFullVideoView.getCurrentPosition();
float durationDelta = xDelta / widthPixels * duration;
//参数二是相加得到的  有可能大于视屏的总长度
int video_move_position = (int) Math.min(duration, currentPosition + durationDelta);
mFullVideoView.seekTo(video_move_position);
//移动seekbar
progress_ctroller.setProgress(video_move_position);
//当前播放的时间
curent_position.setText(DateFormat.format("mm:ss",video_move_position));

}

//程序退出  将handler中所发送的消息移除
@Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeMessages(UPDATE_PROGRESS);
}
}


     由于主页面代码太多,所以给横屏设置亮度和声音的代码都写到了另外一个类中,主页面只声明了方法.

     以下是在另外一个类中设置声音的代码

public class AudioController {
public static void turnDown(Context context, float yDilta, int heightPixels) {
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);

//当前音量
int streamVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);

//获取最大英两
int streamMaxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
//计算音量的改变量
float streamDelta = yDilta / heightPixels * streamMaxVolume;

//改变后的音量
int changeStreamVolume = (int) Math.max(0, streamVolume - streamDelta);

//将改变后的音量设置给西屯
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC,changeStreamVolume,AudioManager.FLAG_SHOW_UI);
}

public static void turnup(Context context, float yDilta, int heightPixels) {
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);

//当前音量
int streamVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);

//获取最大英两
int streamMaxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
//计算音量的改变量
float streamDelta = yDilta / heightPixels * streamMaxVolume;

//改变后的音量
int changeStreamVolume = (int) Math.min(streamMaxVolume, streamVolume - streamDelta);

//将改变后的音量设置给西屯
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC,changeStreamVolume,AudioManager.FLAG_SHOW_UI);
}
}


         以下是在另外一个类中,设置亮度的代码

public class LightnessController {
public static void turnDown(Context context, float yDilta, int heightPixels) {
//获取系统当前的亮度
try {
int current_brightness = Settings.System.getInt(context.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS);

//计算亮度的改变值
int brightnessDelta = (int) (yDilta / heightPixels * 255);
//亮度最下,不能小于25
int changedBrightness = Math.max(25, current_brightness - brightnessDelta);
//修改屏幕的亮度
WindowManager.LayoutParams attributes = ((Activity) context).getWindow().getAttributes();//窗体的属性集合

attributes.screenBrightness = changedBrightness*1.0f/255;
((Activity) context).getWindow().setAttributes(attributes);
//当前的亮度设置给系统
Settings.System.putInt(context.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS,changedBrightness);
//获取SeekBar
SeekBar bright_display = ((VideoActivity) context).getBright_display();
if (bright_display.getMax()!=255){
bright_display.setMax(255);
}
bright_display.setVisibility(View.VISIBLE);
bright_display.setProgress(changedBrightness);
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
}

}

public static void turnUp(Context context, float yDilta, int heightPixels) {
//获取系统当前的亮度
try {
int current_brightness = Settings.System.getInt(context.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS);

//计算亮度的改变值
int brightnessDelta = (int) (yDilta / heightPixels * 255);
//亮度最下,不能小于25
int changedBrightness = Math.min(255, current_brightness - brightnessDelta);
//修改屏幕的亮度
WindowManager.LayoutParams attributes = ((Activity) context).getWindow().getAttributes();//窗体的属性集合

attributes.screenBrightness = changedBrightness*1.0f/255;
((Activity) context).getWindow().setAttributes(attributes);
//当前的亮度设置给系统
Settings.System.putInt(context.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS,changedBrightness);

//获取SeekBar
SeekBar bright_display = ((VideoActivity) context).getBright_display();
if (bright_display.getMax()!=255){
bright_display.setMax(255);
}
bright_display.setVisibility(View.VISIBLE);
bright_display.setProgress(changedBrightness);

} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
}
}
}


 

                                                           如果哪里可以优化  尽请留言交流

    
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐