基于VideoView自定义控制面板的视频播放器

本文实例为大家分享了VideoView原生自定义视频播放器的具体代码,供大家参考,具体内容如下

项目用到的技术点和亮点

  • VideoView封装视频播放工具类
  • 自定义视频控制面板
  • 手势识别器的使用

1. VideoView封装视频播放工具类

视频播放这些其实都挺简单的,VideoView这个类都提供了相应方法,详细见代码 代码都比较简单,不过需要注意的是要在主线程中更新视频面板的UI信息。

/********************************************************
 * 视频业务类
 * 最后修改时间:2017/9/23
 * @author zlc
 *
 *********************************************************/
package com.zlc.video;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.media.MediaPlayer;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.VideoView;
public class VideoBusiness implements MediaPlayer.OnPreparedListener,MediaPlayer.OnCompletionListener,MediaPlayer.OnErrorListener{

 private Activity activity;
 private WakeLock mWakeLock;
 public VideoView mVideoView;
 private VideoController mController;

 /**播放状态枚举,有三种播放状态:空闲,正在准备*/
 private enum PLAYER_STATUS {
  IDLE, PREPARING,PAUSED, PREPARED,RESUMED,STOPPED
 }
 /**当前播放状态*/
 public PLAYER_STATUS mPlayerStatus = PLAYER_STATUS.IDLE;

 /**播放信息异步处理方法,用于更新进度*/
 /**事件标志*/
 private int mLastPos;

 public VideoBusiness(Activity activity){
  this.activity = activity;
  // 保持屏幕高亮
  PowerManager pm = (PowerManager) activity.getSystemService(Context.POWER_SERVICE);
  mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, "Test");
 }

 //初始化视频播放器
 public void initVideo(VideoView videoView,VideoController controller,String sourceUrl){

  this.mVideoView = videoView;
  this.mController = controller;
  mController.setVideoBusiness(this);
  Log.e("msg","设置播放地址 = "+sourceUrl);
  mVideoView.setOnPreparedListener(this);
  mVideoView.setOnCompletionListener(this);
  mVideoView.setOnErrorListener(this);
  mVideoView.setVideoPath(sourceUrl); //设置播放地址

 }

 //开始播放
 public void startPlay(){
  if (null != mWakeLock && (!mWakeLock.isHeld())) {
   mWakeLock.acquire();
  }
  if(null != mVideoView) {
   Log.e("msg", "播放");
   mVideoView.start();
   mPlayerStatus = PLAYER_STATUS.PREPARING;
  }
 }

 /**
  * 暂停播放
  */
 public void pause() {
  if (null != mWakeLock) {
   mWakeLock.release();
  }
  if(null != mVideoView && mVideoView.isPlaying()){
   mVideoView.pause();
   mPlayerStatus = PLAYER_STATUS.PAUSED;
   mLastPos = getCurrentTime();
  }
 }

 /**
  * 继续播放
  */
 public void resume(){
  if (null != mWakeLock) {
   mWakeLock.acquire();
  }
  if(null != mVideoView){
   //mVideoView.resume();
   mVideoView.seekTo(mLastPos);
   mVideoView.start();
   mPlayerStatus = PLAYER_STATUS.RESUMED;
  }
 }

 /**
  * 停止播放
  */
 public void stop() {

  if (null != mWakeLock) {
   mWakeLock.release();
  }
  if(null != mVideoView){
   mLastPos = getCurrentTime();
   mVideoView.stopPlayback();
   mPlayerStatus = PLAYER_STATUS.STOPPED;
  }
 }

 /**
  * 判断是否正在播放
  * @return
  */
 public boolean isPlaying(){
  return mVideoView!=null && mVideoView.isPlaying();
 }

 /**
  * 是否暂停
  */
 public boolean isPause(){
  return mPlayerStatus == PLAYER_STATUS.PAUSED;
 }

 /**
  * 释放资源
  */
 public void release(){
  if (null != mWakeLock) {
   mWakeLock.release();
   mWakeLock = null;
  }
  if(null != mVideoView){
   mVideoView.stopPlayback();
   mVideoView = null;
  }
 }

 @Override
 public void onCompletion(MediaPlayer mediaPlayer) {
  Log.e("onCompletion","视频播放完了");
  mController.showLong();
  mController.setProgress(0);
  mLastPos = 0;
  mPlayerStatus = PLAYER_STATUS.IDLE;
  removeUIMessage();
 }

 @Override
 public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
  Log.e("onError","视频播放报错了");
  return false;
 }

 @Override
 public void onPrepared(MediaPlayer mediaPlayer) {
  Log.e("onPrepared","视频准备好了");
  if (mPlayerStatus!= PLAYER_STATUS.PAUSED){
   int totalTime = getTotalTime();
   mController.setTotalTime(totalTime);
   mController.setProgress(0);
   mController.setMaxProgress(totalTime);
   mPlayerStatus = PLAYER_STATUS.PREPARED;
   sendUIMessage();
  }
 }

 /**
  * 进度条拖拽播放
  * @param time
  */
 public void seekToPlay(int time){
  int totalSecond = getTotalTime();
  int tempTime = time > totalSecond ? totalSecond : time;
  mVideoView.seekTo(tempTime);
  sendUIMessage();
 }

 //视频暂停播放 播放大按钮点击事件
 public void playVideo(ImageView id_btn_video_play, ImageView img){
  if(isPlaying()){
   pause();
   id_btn_video_play.setVisibility(View.VISIBLE);
   img.setImageResource(R.drawable.video_pause);
   mPlayerStatus = PLAYER_STATUS.PAUSED;
   mUIHandler.sendEmptyMessageDelayed(UI_EVENT_UPDATE_CURRPOSITION, 500);
  }else if(isPause()){
   resume();
   id_btn_video_play.setVisibility(View.GONE);
   img.setImageResource(R.drawable.video_play);
   mPlayerStatus = PLAYER_STATUS.RESUMED;
  }else{
   img.setImageResource(R.drawable.video_play);
   id_btn_video_play.setVisibility(View.GONE);
   startPlay();
   mPlayerStatus = PLAYER_STATUS.PREPARING;
  }
 }

 private boolean isCurrentLandscape = false; //是不是横屏
 //横竖屏切换按钮点击方法
 public void toggleScreenDir(View v){
  if (isCurrentLandscape) {// 如果当前是横屏,则切换为竖屏,然后把按钮为变为变大的图标
   activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
   if(v instanceof ImageView){
    ((ImageView)v).setImageResource(R.drawable.zuidahua_2x);
   }
  } else {// 如果当前是竖屏,则切换为横屏,然后把按钮为变为变小的图标
   activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
   if(v instanceof ImageView){
    ((ImageView)v).setImageResource(R.drawable.xiaohua_2x);
   }
  }
  isCurrentLandscape = !isCurrentLandscape;
 }

 public UIHandler mUIHandler = new UIHandler(Looper.getMainLooper());
 public final int UI_EVENT_UPDATE_CURRPOSITION = 1; //更新进度信息
 public boolean isSeekBarEnable = true;

 class UIHandler extends Handler{
  public UIHandler(Looper mainLooper) {
   super(mainLooper);
  }

  @Override
  public void handleMessage(Message msg) {
   switch (msg.what) {
    //更新进度及时间
    case UI_EVENT_UPDATE_CURRPOSITION:
     if (isSeekBarEnable) {
      int currentPosition = getCurrentTime();
      String timeString = mController.getTimeString(currentPosition);
      //Log.e("handleMessage",timeString);
      if(isPlaying()) {
       mController.setProgress(currentPosition);
       mUIHandler.sendEmptyMessageDelayed(
         UI_EVENT_UPDATE_CURRPOSITION, 200);
      }
     }
     break;
   }
  }
 }

 public void sendUIMessage(){
  mUIHandler.sendEmptyMessage(UI_EVENT_UPDATE_CURRPOSITION);
 }

 public void removeUIMessage(){
  mUIHandler.removeMessages(UI_EVENT_UPDATE_CURRPOSITION);
 }

 //获取视频总时间
 public int getTotalTime(){
  return mVideoView==null ? 0 : mVideoView.getDuration();
 }

 //获取视频当前时间
 public int getCurrentTime(){
  return mVideoView==null ? 0 : mVideoView.getCurrentPosition();
 }
}

2. 手势识别器的使用

//1. 创建手势识别器
 progressGestureDetector = new GestureDetector(mContext,new ProgressGestureListenr());

//2.复写GestureDetector.OnGestureListener的6个方法
boolean onDown(MotionEvent e) //用户按下屏幕就会触发

void onShowPress(MotionEvent e) ////down事件发生而move或则up还没发生前触发该事件

boolean onSingleTapUp(MotionEvent e) //一次点击up事件

boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) //在屏幕上拖动事件

void onLongPress(MotionEvent e) //长按事件

 boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) //滑动手势事件

 //3 onTouch中拦截
 @Override
 public boolean onTouch(View view, MotionEvent event) {

  return progressGestureDetector.onTouchEvent(event);
 }
 //4 事件绑定
 progressArea.setOnTouchListener(this);

3. 自定义视频控制面板

代码比较简单同时代码不长 都有注释 需要的可以参考下 大神勿喷

package com.zlc.video;

import android.app.Activity;
import android.content.Context;
import android.media.AudioManager;
import android.os.Handler;
import android.os.Message;
import android.provider.Settings;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;

import com.zlc.video.utils.DensityUtil;
import com.zlc.video.utils.ScreenUtil;
import java.text.SimpleDateFormat;
import java.util.Date;

public class VideoController extends RelativeLayout implements View.OnTouchListener,View.OnClickListener,SeekBar.OnSeekBarChangeListener{

 private Context mContext;
 private View mContainer;
 private VideoBusiness videoBusiness;
 /** 表示当前视频控制面板是否展示*/
 public boolean isShow = true;
 private Handler hideHandler = new Handler() {
  @Override
  public void handleMessage(Message msg) {
   if (isShow) {
    hideController();
   }
  }
 };
 /** 视频功能控制底边栏*/
 private LinearLayout mMediaController;

 /***************手势相关*********************/
 private int GESTURE_FLAG = 0;//1调节进度,2调节音量,3调节亮度
 private FrameLayout mProgressIndicator;
 private ProgressBar progressBar;
 /**进度相关*/
 private GestureDetector progressGestureDetector;
 private static final int GESTURE_MODIFY_PROGRESS = 1;
 /**音量相关*/
 private static final int GESTURE_MODIFY_VOLUME = 2;
 private AudioManager audiomanager;
 private int maxVolume, currentVolume;
 /**亮度相关*/
 private static final int GESTURE_MODIFY_BRIGHTNESS = 3;
 private WindowManager.LayoutParams brightnessLp;
 private int maxBrightness,currentBrightness;
 private LinearLayout progressArea;
 private int targetTime;
 //UI相关
 private RelativeLayout id_rl_video_controller;
 private FrameLayout id_fl_video_play;
 private FrameLayout id_fl_video_expand;
 private TextView id_video_time;
 private TextView id_video_totaltime;
 private SeekBar id_sb_progress;
 private ImageView id_btn_video_play;
 private ImageView id_iv_video_play;
 private TextView id_tv_video_info;

 public VideoController(Context context) {
  this(context, null);
 }

 public VideoController(Context context, AttributeSet attrs) {
  this(context, attrs, 0);
 }

 public VideoController(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);
  mContext = context;
  init();
  initListener();
 }

 private void init() {
  //初始化音量相关
  audiomanager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
  maxVolume = audiomanager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); // 获取系统最大音量
  currentVolume = audiomanager.getStreamVolume(AudioManager.STREAM_MUSIC); // 获取当前值
  //初始化亮度相关
  brightnessLp=((Activity)mContext).getWindow().getAttributes();
  currentBrightness = getCurrentBrightness();
  maxBrightness = 255; //设置最大亮度
  initView();
 }

 private void initView() {
  mContainer = View.inflate(mContext, R.layout.video_controller, null);
  id_rl_video_controller = findView(R.id.id_rl_video_controller);
  mMediaController = findView(R.id.id_ll_controller);
  mProgressIndicator = findView(R.id.id_fl_progress_indicator);
  progressBar = findView(R.id.id_pb_gesture_progress);
  progressArea = findView(R.id.id_ll_video_gesture_progress);
  id_fl_video_play = findView(R.id.id_fl_video_play);
  id_fl_video_expand = findView(R.id.id_fl_video_expand);
  id_video_time = findView(R.id.id_video_time);
  id_video_totaltime = findView(R.id.id_video_totaltime);
  id_sb_progress = findView(R.id.id_sb_progress);
  id_btn_video_play = findView(R.id.id_btn_video_play);
  id_iv_video_play = findView(R.id.id_iv_video_play);
  id_tv_video_info = findView(R.id.id_tv_video_info);
  addView(mContainer);
 }

 private <T extends View> T findView(int viewId) {
  return (T) mContainer.findViewById(viewId);
 }

 public void setVideoBusiness(VideoBusiness videoBusiness) {
  this.videoBusiness = videoBusiness;
 }

 private void initListener() {
  //进度手势相关
  progressGestureDetector = new GestureDetector(mContext,new ProgressGestureListenr());
  progressGestureDetector.setIsLongpressEnabled(true);
  progressArea.setLongClickable(true);
  progressArea.setOnTouchListener(this);
  mMediaController.setOnClickListener(this);
  id_rl_video_controller.setOnClickListener(this);
  id_fl_video_play.setOnClickListener(this);
  id_fl_video_expand.setOnClickListener(this);
  id_btn_video_play.setOnClickListener(this);
  id_sb_progress.setOnSeekBarChangeListener(this);
 }

 //状态切换
 public void toggle() {
  if (isShow) {
   hideController();
  } else {
   showController();
  }
 }

 //隐藏底部控制栏
 public void hideController() {
  isShow = false;
  mMediaController.setVisibility(View.GONE);
  endTimer();
 }

 //显示底部控制栏
 public void showController() {
  isShow = true;
  mMediaController.setVisibility(View.VISIBLE);
  startTimer();
 }

 private void startTimer() {
  if (hideHandler != null){
   hideHandler.removeMessages(0);
  }
  hideHandler.sendEmptyMessageDelayed(0, 5000);
 }

 private void endTimer() {
  hideHandler.removeMessages(0);
 }

 public void resetTimer() {
  endTimer();
  startTimer();
 }

 public void showLong() {
  isShow = true;
  mMediaController.setVisibility(View.VISIBLE);
 }

 //设置视频总时间
 public void setTotalTime(int time) {
  String totalTime = getTimeString(time);
  id_video_totaltime.setText(totalTime);
 }

 //设置视频当前进度
 public void setProgress(int progress){
  int maxProgress = videoBusiness.getTotalTime();
  int tempProgress = progress > maxProgress ? maxProgress : progress;
  id_sb_progress.setProgress(tempProgress);
 }

 //是指视频总进度
 public void setMaxProgress(int maxProgress){
  id_sb_progress.setMax(maxProgress);
 }

 //获取当前亮度
 private int getCurrentBrightness(){
  int currentBrightness = 255;
  if (brightnessLp.screenBrightness == WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE){
   // 获取系统亮度
   try {
    currentBrightness = Settings.System.getInt(((Activity)mContext).getContentResolver(), Settings.System.SCREEN_BRIGHTNESS);
   } catch (Settings.SettingNotFoundException e) {
    e.printStackTrace();
   }
  }else{
   // 获取当前窗口亮度
   currentBrightness = (int)(brightnessLp.screenBrightness * 255);
  }
  return currentBrightness;
 }

 @Override
 public void onClick(View view) {
  switch (view.getId()){
   case R.id.id_ll_controller: //底部控制器
    showController();
    break;
   case R.id.id_rl_video_controller: //全屏点击
    toggle();
    break;
   case R.id.id_fl_video_play: // 暂停/播放
   case R.id.id_btn_video_play: // 暂停/播放
    videoBusiness.playVideo(id_btn_video_play,id_iv_video_play);
    break;
   case R.id.id_fl_video_expand: //全屏
    resetTimer();
    videoBusiness.toggleScreenDir(view);
    break;
  }
 }

 @Override
 public boolean onTouch(View view, MotionEvent event) {

  getParent().requestDisallowInterceptTouchEvent(true);
  if (event.getAction() == MotionEvent.ACTION_UP) {
   mProgressIndicator.setVisibility(View.INVISIBLE);
   if (GESTURE_FLAG == GESTURE_MODIFY_PROGRESS) { //调节进度
    Log.e("进度时间","targetTime="+targetTime);
    videoBusiness.seekToPlay(targetTime);
    videoBusiness.isSeekBarEnable = true;
    hideController();
   }
   GESTURE_FLAG = 0;// 手指离开屏幕后,重置调节音量或进度的标志
  }
  return progressGestureDetector.onTouchEvent(event);
 }

 private int currentPosition; //当前播放进度
 private int totalPosition; //总播放进度
 class ProgressGestureListenr implements GestureDetector.OnGestureListener{
  private boolean firstScroll = false;// 每次触摸屏幕后,第一次scroll的标志
  private int slop;// 触发设置变动的最小距离
  @Override
  public boolean onDown(MotionEvent e) { //用户按下屏幕就会触发
   //初始数据
   slop = DensityUtil.dp2px(mContext,2);
   currentPosition = videoBusiness.getCurrentTime();
   totalPosition = videoBusiness.getTotalTime();
   firstScroll = true;
   return false;
  }

  @Override
  public void onShowPress(MotionEvent e) { //down事件发生而move或则up还没发生前触发该事件
  }

  @Override
  public boolean onSingleTapUp(MotionEvent e) { //一次点击up事件
   toggle();
   if(videoBusiness.isPlaying()){ //正在播放
    return false;
   }else{ //暂停或者开始播放
    videoBusiness.playVideo(id_btn_video_play,id_iv_video_play);
    isShow = false;
    return true;
   }
  }

  //在屏幕上拖动事件
  @Override
  public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
   if (firstScroll) {// 以触摸屏幕后第一次滑动为标准,避免在屏幕上操作切换混乱
    // 横向的距离变化大则调整进度,纵向的变化大则调整音量
    Log.e("xxxxxxx",e1.getX()+"");
    Log.e("yyyyyyy",e1.getY()+"");
    setScroll(e1, distanceX, distanceY);
   }
   // 如果每次触摸屏幕后第一次scroll是调节进度,那之后的scroll事件都处理音量进度,直到离开屏幕执行下一次操作
   switch (GESTURE_FLAG){
    case GESTURE_MODIFY_PROGRESS: //调节当前进度
     setCurrentProgress(distanceX, distanceY,slop);
     break;
    case GESTURE_MODIFY_VOLUME: //调节当前音量
     setCurrentVolume(distanceX, distanceY,slop);
     break;
    case GESTURE_MODIFY_BRIGHTNESS: //调节当前亮度
     setCurrentBrightess(distanceX, distanceY,slop);
     break;
   }
   firstScroll=false;
   return false;
  }

  @Override
  public void onLongPress(MotionEvent e) { //长按事件
  }

  @Override
  public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { //滑动手势事件
   return false;
  }
 }

 //滑动事件
 private void setScroll(MotionEvent e1, float distanceX, float distanceY) {
  int screenWidth = ScreenUtil.getScreenWidth(mContext);
  Log.e("屏宽",screenWidth+"");
  //横向的距离变化大则调整进度,纵向的变化大则调整音量
  mProgressIndicator.setVisibility(View.VISIBLE);
  if (Math.abs(distanceX) >= Math.abs(distanceY)) { //调整进度
   progressBar.setVisibility(View.INVISIBLE);
   id_tv_video_info.setVisibility(VISIBLE);
   GESTURE_FLAG = GESTURE_MODIFY_PROGRESS;
   videoBusiness.isSeekBarEnable = false;
   endTimer();
   showLong();
  }else { //调整音量
   progressBar.setVisibility(VISIBLE);
   id_tv_video_info.setVisibility(INVISIBLE);
   if (e1.getX() > screenWidth / 2){ //屏幕右边上下滑动调整音量
    //右半屏音量
    setVideoVolume();
   }else{        //屏幕左边上下滑动调整亮度
    //左半屏亮度
    setVideoBrightness();
   }
  }
 }

 //设置当前进度
 private void setCurrentProgress(float distanceX, float distanceY,float slop) {
  if (Math.abs(distanceX) > Math.abs(distanceY)) {// 横向移动大于纵向移动
   //Log.e("setCurrentProgress",distanceX+"");
   if(distanceX >= slop){ //从右往左滑 快退
    mProgressIndicator.setBackgroundResource(R.drawable.kuaitui);
    if (currentPosition > 1000) {
     currentPosition -= 1500;
    }
   }else if(distanceX <= -slop){ //从左往右滑 快进
    mProgressIndicator.setBackgroundResource(R.drawable.kuaijin);
    if (currentPosition < totalPosition) {
     currentPosition += 1500;
    }
   }
  }
  targetTime = currentPosition;
  Log.e("进度时间","currentPosition="+currentPosition);
  id_sb_progress.setProgress(currentPosition);
  id_video_time.setText(getTimeString(currentPosition));
  String videoPbInfo = getTimeString(currentPosition)+"/"+ getTimeString(totalPosition);
  id_tv_video_info.setText(videoPbInfo);
 }

 //设置当前亮度
 private void setCurrentBrightess(float distanceX, float distanceY, float slop) {
  currentBrightness = getCurrentBrightness();
  if (Math.abs(distanceY) > Math.abs(distanceX)) {// 纵向移动大于横向移动
   if (distanceY >= slop) {// 上滑 亮度调大,注意横屏时的坐标体系,尽管左上角是原点,但横向向上滑动时distanceY为正
    if (currentBrightness < maxBrightness) {// 为避免调节过快,distanceY应大于一个设定值
     currentBrightness += 8;
    }
   } else if (distanceY <= -slop) {// 亮度调小
    if (currentBrightness > 0) {
     currentBrightness -= 8;
    }
    if (currentBrightness<0){
     currentBrightness=0;
    }
   }
   mProgressIndicator.setBackgroundResource(R.drawable.liangdu);
   progressBar.setProgress(currentBrightness);
   changeAppBrightness(mContext,currentBrightness);
  }
 }

 //设置当前音量
 private void setCurrentVolume(float distanceX, float distanceY,float slop) {

  currentVolume = audiomanager.getStreamVolume(AudioManager.STREAM_MUSIC); // 获取当前值
  if (Math.abs(distanceY) > Math.abs(distanceX)) { // 纵向移动大于横向移动
   if (distanceY >= slop) { // 上滑 音量调大,注意横屏时的坐标体系,尽管左上角是原点,但横向向上滑动时distanceY为正
    if (currentVolume < maxVolume) {// 为避免调节过快,distanceY应大于一个设定值
     currentVolume++;
    }
    mProgressIndicator.setBackgroundResource(R.drawable.yinliang);
   } else if (distanceY <= -slop) {// 音量调小 下滑
    if (currentVolume > 0) {
     currentVolume--;
     if (currentVolume == 0) {// 静音,设定静音独有的图片
      mProgressIndicator.setBackgroundResource(R.drawable.jingying);
     }
    }
   }
   progressBar.setProgress(currentVolume);
   audiomanager.setStreamVolume(AudioManager.STREAM_MUSIC, currentVolume, 0);
  }
 }

 //设置视频亮度
 private void setVideoBrightness() {
  progressBar.setMax(maxBrightness);
  progressBar.setProgress(currentBrightness);
  mProgressIndicator.setBackgroundResource(R.drawable.liangdu);
  GESTURE_FLAG = GESTURE_MODIFY_BRIGHTNESS;
 }

 //设置视频音量
 private void setVideoVolume() {
  progressBar.setMax(maxVolume);
  progressBar.setProgress(currentVolume);
  mProgressIndicator.setBackgroundResource(R.drawable.yinliang);
  GESTURE_FLAG = GESTURE_MODIFY_VOLUME;
 }

 //改变系统亮度
 public void changeAppBrightness(Context context, int brightness) {
  Window window = ((Activity) context).getWindow();
  WindowManager.LayoutParams lp = window.getAttributes();
  if (brightness == -1) {
   lp.screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE;
  } else {
   lp.screenBrightness = (brightness <= 0 ? 1 : brightness) / 255f;
  }
  window.setAttributes(lp);
 }

 public String getTimeString(int second) {
  int temp = second / 1000;
  int hh = temp / 3600;
  SimpleDateFormat sdf;
  if (0 != hh) {
   sdf = new SimpleDateFormat("HH:mm:ss");
  } else {
   sdf = new SimpleDateFormat("mm:ss");
  }
  String format = sdf.format(new Date(second));
  return format;
 }

 //进度条改变
 @Override
 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
  String timeString = getTimeString(progress);
  id_video_time.setText(timeString);
 }

 //开始拖动
 @Override
 public void onStartTrackingTouch(SeekBar seekBar) {
  showLong();
  videoBusiness.removeUIMessage();
 }

 //结束拖动
 @Override
 public void onStopTrackingTouch(SeekBar seekBar) {
  showController();
  int progress = seekBar.getProgress();
  videoBusiness.seekToPlay(progress);
 }

}

4.下载地址

VideoView原生自定义视频播放器

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

时间: 2018-07-02

5步学会使用VideoView播放视频

我们可以试想ImageView能显示图片,而VideoView就是用来显示视频的. 使用VideoView播放视频的步骤如下 [1]在界面布局中定义VideoView <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="m

Android音频可视化开发案例说明

Android 调用自带的录制音频程序 Android中有自带的音频录制程序,我们可以通过指定一个Action MediaStore.Audio.Media.RECORD_SOUND_ACTION的Intent来 启动它就可以了.然后在onActivityResult()方法中,获取Intent的Data,就是录制的音频对应的URI. java代码: 复制代码 代码如下: package eoe.demo; import android.app.Activity; import android.

Android音频录制MediaRecorder之简易的录音软件实现代码

使用MediaRecorder的步骤:1.创建MediaRecorder对象2.调用MediRecorder对象的setAudioSource()方法设置声音的来源,一般传入MediaRecorder.MIC3.调用MediaRecorder对象的setOutputFormat()设置所录制的音频文件的格式4.调用MediaRecorder对象的setAudioRncoder().setAudioEncodingBitRate(int bitRate).setAudioSamlingRate(i

Android VideoCache视频缓存的方法详解

Android VideoCache视频缓存的方法详解 项目中遇到视频播放,需要加载网络url,不可能每次都进行网络加载,当然了,就需要用到我们的缓存机制 AndroidVideoCache AndroidVideoCache是一个视频/音频缓存库,利用本地代理实现了边下边播,使用起来非常简单. HttpProxyCacheServer是主要类,是一个代理服务器,可以配置缓存文件的数量.缓存文件的大小.缓存文件的目录和缓存文件命名算法,文件缓存均基于LRU算法,利用Builder来配置: //配

Android提高之MediaPlayer播放网络音频的实现方法

前面有文章曾经地介绍过MediaPlayer的基本用法,这里就更加深入地讲解MediaPlayer的在线播放功能.本文主要实现MediaPlayer在线播放音频的功能,由于在线视频播放比在线音频播放复杂,因此先介绍在线音频播放的实现,这样可以帮助大家逐步深入了解MediaPlayer的在线播放功能. 先来看看本文程序运行的结果如下图所示: main.xml的源码如下: <?xml version="1.0" encoding="utf-8"?> <

Android视频点播的实现代码(边播边缓存)

简述 一些知名的视频app客户端(优酷,爱奇艺)播放视频的时候都有一些缓存进度(二级进度缓存),还有一些短视频app,都有边播边缓的处理.还有就是当文件缓存完毕了再次播放的话就不再请求网络了直接播放本地文件了.既节省了流程又提高了加载速度. 今天我们就是来研究讨论实现这个边播边缓存的框架,因为它不和任何的业务逻辑耦合. 开源的项目 目前比较好的开源项目是:https://github.com/danikula/AndroidVideoCache 代码的架构写的也很不错,网络用的httpurlco

VideoView实现视频无缝连续播放

该视频播放器采用了较为简单的videoview,基本思想就是用setOnCompletionListener对视频播进行监听,当视频播放完毕之后,播放下一段视频,视频源放在SD卡内的Download文件夹内,具体代码如下: public class MainActivity extends Activity { VideoView videoView; static int pos=1; //静态整型变量用于标记播放到了第几段视频 MediaController mController; @Ov

Android视频/音频缓存框架AndroidVideoCache(Okhttp)详解

关于安卓边下边播功能,供大家参考,具体内容如下 对于视频/音频软件,音乐软件,视频软件,都有缓存这个功能,那如何实现边下边播功能: 如何实现这个边下边播功能? 文件是否支持同时读写?(Mediaplayer 播放文件,从网络上下载文件) 播放与下载进度如何协调? 已缓存的文件需及时清理 经过一番折腾,我 find 了 : [ AndroidVideoCache ],这个库是 danikula 大神写,看完源码后收益匪浅.实现流媒体边下边播原理利用socket 开启一个本机的代理服务器 结合自身需

Android使用音频信息绘制动态波纹

在一些音乐类应用中, 经常会展示随着节奏上下起伏的波纹信息, 这些波纹形象地传达了声音信息, 可以提升用户体验, 那么是如何实现的呢? 可以使用Visualizer类获取当前播放的声音信息, 并绘制在画布上, 使用波纹展示即可. 我来讲解一下使用方法. 主要 (1) Visualizer类提取波纹信息的方式. (2) 应用动态权限管理的方法. (3) 分离自定义视图的展示和逻辑. 1. 基础准备 Android 6.0引入动态权限管理, 在这个项目中, 会使用系统的音频信息, 因此把权限管理引入

Android音频系统AudioTrack使用方法详解

今天,简单讲讲AudioTrack的使用方法. 1.Android AudioTrack简介 在android中播放声音可以用MediaPlayer和AudioTrack两种方案的,但是两种方案是有很大区别的,MediaPlayer可以播放多种格式的声音文件,例如MP3,AAC,WAV,OGG,MIDI等.而AudioTrack只能播放PCM数据流. 事实上,两种本质上是没啥区别的,MediaPlayer在播放音频时,在framework层还是会创建AudioTrack,把解码后的PCM数流传递

Android 中Context的使用方法详解

Android 中Context的使用方法详解 概要: Context字面意思是上下文,位于framework package的android.content.Context中,其实该类为LONG型,类似Win32中的Handle句柄.很多方法需要通过 Context才能识别调用者的实例:比如说Toast的第一个参数就是Context,一般在Activity中我们直接用this代替,代表调用者的实例为Activity,而到了一个button的onClick(View view)等方法时,我们用t

Android 使用View Binding的方法详解

前言 Android Studio稳定版发布了3.6版本,带来了一些新变化:首先外观,启动页变了,logo改了,更显现代化:增加Multi Preview功能,能同时预览多个尺寸屏幕的显示效果:模拟器支持多屏:也终于支持全新的视图绑定组件View Binding:等. 之前我们与视图交互的方式有findViewById.kotlin中引入Android Kotlin Extensions后直接通过id进行访问.前者模板化严重,重复代码多:后者最为方便.现在有了新的选择–View Binding,

Android 中RxPermissions 的使用方法详解

Android 中RxPermissions 的使用方法详解 以请求拍照.读取位置权限为例 module的build.gradle: compile 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.4@aar' compile 'io.reactivex.rxjava2:rxjava:2.0.5' AndroidManifest.xml: <uses-permission android:name="android.permission.AC

Android中XUtils3框架使用方法详解(一)

xUtils简介 xUtils 包含了很多实用的android工具. xUtils 支持大文件上传,更全面的http请求协议支持(10种谓词),拥有更加灵活的ORM,更多的事件注解支持且不受混淆影响... xUitls 最低兼容android 2.2 (api level 8) 今天给大家带来XUtils3的基本介绍,本文章的案例都是基于XUtils3的API语法进行的演示.相信大家对这个框架也都了解过, 下面简单介绍下XUtils3的一些基本知识. XUtils3一共有4大功能:注解模块,网络

Android 监听网络状态方法详解

Android 监听网络状态方法详解 一.加入网络权限 获取网络信息需要在AndroidManifest.xml文件中加入相应的权限. <uses-permission Android:name="android.permission.ACCESS_NETWORK_STATE" /> 二.判断手机网络的几个方案 1)判断是否有网络连接 public boolean isMobileConnected(Context context) { if (context != nul

Android intent之间复杂参数传递方法详解

本文详细讲述了Android intent之间复杂参数传递方法.分享给大家供大家参考,具体如下: Intent是Activity与Activity之间,Activity与Service之间传递参数的介质,而这两种通常实现的是Java基本对象类型和String的传递. 在实际项目中,页面之间传值,除了以上几种,经常还有传递Object对象.List类型.List<Object>类型和全局变量等等的需求.本文就是介绍怎么传递这几种类型的参数. 一.传递List<String>和List

Android编程自定义菜单实现方法详解

本文实例讲述了Android编程自定义菜单实现方法.分享给大家供大家参考,具体如下: 在android开发的过程中系统自带的菜单往往满足不了开发中的一些需求,比如说一排最多只能放置三个菜单,坐多只能放置6个,再多的话就会折叠起来,如果我们想再一排显示4个或5个菜单那么就要自己想办法处理. 这里我用布局的隐藏并加上动画来模拟菜单的效果. 要点: 1.隐藏和显示菜单,我使用了一个线性布局把菜单封装起来. <?xml version="1.0" encoding="utf-8

Android控件ListView使用方法详解

Android控件ListView使用方法介绍,具体如下 一.ListView的简单用法 首先新建一个ListViewTest项目,并让Android Studio自动创建好活动.然后修改activity_main.xml中的代码,如下: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/re