自定义视频播放器——VideoView和其他控件的组合

下面是自己写的一个视频播放器,只是用Android已有的控件组合了一下,个人觉得Android提供的MediaController不好看(或许可以修改,没试),自己定义了一个播放控制面板,可以播放、暂停、改变播放进度、全屏和非全屏。


1.播放器的布局文件simple_video_view.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#000000"
    >
    <!-- 视频控件 -->
    <VideoView
        android:id="@+id/video_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        />
    <!-- 播放控制面板 -->
    <LinearLayout 
        android:id="@+id/control_panel"
        android:layout_width="match_parent"
    	android:layout_height="wrap_content"
    	android:layout_alignBottom="@id/video_view"
    	android:orientation="horizontal"
    	android:background="#70000000"
    	android:visibility="gone"
        >
        <ImageView 
            android:id="@+id/play_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:src="@drawable/play_icon"
            android:padding="4dp"
            android:scaleType="centerInside"
            android:contentDescription="@string/app_name"
            />
        <RelativeLayout 
        	android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_gravity="center_vertical"
            >
			<SeekBar 
            	android:id="@+id/progress_bar"
           		android:layout_width="match_parent"
            	android:layout_height="wrap_content"
            	android:maxHeight="4dp"
            	android:layout_centerVertical="true"
            	android:paddingStart="8dp"
            	android:paddingEnd="8dp"
            	/>
           	<TextView 
           	    android:id="@+id/time"
           	    android:layout_width="wrap_content"
           	    android:layout_height="wrap_content"
           	    android:layout_alignEnd="@id/progress_bar"
           	    android:layout_below="@id/progress_bar"
           	    android:textSize="12sp"
           	    android:textColor="#ffffff"
           	    />
        </RelativeLayout>
		<ImageView 
            android:id="@+id/full_screen_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/full_screen_icon"
            android:layout_gravity="center_vertical"
            android:padding="4dp"
            android:scaleType="centerInside"
            android:contentDescription="@string/app_name"
            />
    </LinearLayout>
    <!-- 大播放按钮 -->
    <ImageView
		android:id="@+id/big_play_button"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:src="@drawable/big_play_icon"
		android:scaleType="centerInside"
		android:layout_centerInParent="true"
 		android:contentDescription="@string/app_name"
		/>
</RelativeLayout>


2.SimpleVideoView类

package com.example.test;

import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.widget.VideoView;

public class SimpleVideoView extends RelativeLayout implements OnClickListener{

	private Context context;
	private View mView;
	private VideoView mVideoView;//视频控件
	private ImageView mBigPlayBtn;//大的播放按钮
	private ImageView mPlayBtn;//播放按钮
	private ImageView mFullScreenBtn;//全屏按钮
	private SeekBar mPlayProgressBar;//播放进度条
	private TextView mPlayTime;//播放时间
	private LinearLayout mControlPanel;
	
	private Uri mVideoUri = null;
	
	private Animation outAnima;//控制面板出入动画
	private Animation inAnima;//控制面板出入动画
	
	private int mVideoDuration;//视频毫秒数
	private int mCurrentProgress;//毫秒数
	
	private Runnable mUpdateTask;
	private Thread mUpdateThread;
	
	private final int UPDATE_PROGRESS = 0;
	private final int EXIT_CONTROL_PANEL = 1;
	private boolean stopThread = true;//停止更新进度线程标志
	
	private Point screenSize = new Point();//屏幕大小
	private boolean mIsFullScreen = false;//是否全屏标志
	
	private int mWidth;//控件的宽度
	private int mHeigth;//控件的高度
	
    public SimpleVideoView(Context context){
    	super(context);
    	init(context, null, 0);
    }
    public SimpleVideoView(Context context, AttributeSet attrs){
    	super(context, attrs);
    	init(context, attrs, 0);
    }
    public SimpleVideoView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs, defStyleAttr);
    }
    
    private Handler handler = new Handler(){
    	@Override
    	public void handleMessage(Message msg){
    		switch(msg.what){
    		case UPDATE_PROGRESS:
    			mPlayProgressBar.setProgress(mCurrentProgress);
    			setPlayTime(mCurrentProgress);
    			break;
    		case EXIT_CONTROL_PANEL:
    			//执行退出动画
    			if(mControlPanel.getVisibility() != View.GONE){
	    			mControlPanel.startAnimation(outAnima);
					mControlPanel.setVisibility(View.GONE);	
    			}
    			break;
    		}
    	}
    };
    
    //初始化控件
	private void init(Context context, AttributeSet attrs, int defStyleAttr){
		this.context = context;
		mView = LayoutInflater.from(context).inflate(R.layout.simple_video_view, this);
		mBigPlayBtn = (ImageView) mView.findViewById(R.id.big_play_button);
		mPlayBtn = (ImageView) mView.findViewById(R.id.play_button);
		mFullScreenBtn = (ImageView) mView.findViewById(R.id.full_screen_button);
		mPlayProgressBar = (SeekBar) mView.findViewById(R.id.progress_bar);
		mPlayTime = (TextView) mView.findViewById(R.id.time);
		mControlPanel = (LinearLayout) mView.findViewById(R.id.control_panel);
		mVideoView = (VideoView) mView.findViewById(R.id.video_view);
		//获取屏幕大小
		((Activity) context).getWindowManager().getDefaultDisplay().getSize(screenSize);
		//加载动画
		outAnima = AnimationUtils.loadAnimation(context, R.anim.exit_from_bottom);
		inAnima = AnimationUtils.loadAnimation(context, R.anim.enter_from_bottom);
		//设置控制面板初始不可见
		mControlPanel.setVisibility(View.GONE);
		//设置大的播放按钮可见
		mBigPlayBtn.setVisibility(View.VISIBLE);
		//设置媒体控制器
//		mMediaController = new MediaController(context);
//		mMediaController.setVisibility(View.GONE);
//		mVideoView.setMediaController(mMediaController);
		mVideoView.setOnPreparedListener(new OnPreparedListener() {
			@Override
			public void onPrepared(MediaPlayer mp) {
				//视频加载完成后才能获取视频时长
				initVideo();
			}
		});
		//视频播放完成监听器
		mVideoView.setOnCompletionListener(new OnCompletionListener() {
			@Override
			public void onCompletion(MediaPlayer mp) {
				mPlayBtn.setImageResource(R.drawable.play_icon);
				mVideoView.seekTo(0);
				mPlayProgressBar.setProgress(0);
				setPlayTime(0);
				stopThread = true;
				sendHideControlPanelMessage();
			}
		});
		
		mView.setOnClickListener(this);
	}
	
	//初始化视频,设置视频时间和进度条最大值
	private void initVideo(){
		//初始化时间和进度条
		mVideoDuration = mVideoView.getDuration();//毫秒数
		int seconds = mVideoDuration/1000;
		mPlayTime.setText("00:00/"+
				((seconds/60>9)?(seconds/60):("0"+seconds/60))+":"+
				((seconds%60>9)?(seconds%60):("0"+seconds%60)));
		mPlayProgressBar.setMax(mVideoDuration);
		mPlayProgressBar.setProgress(0);
		//更新进度条和时间任务
		mUpdateTask = new Runnable(){
			@Override
			public void run(){
				while(!stopThread){
					mCurrentProgress = mVideoView.getCurrentPosition();
					handler.sendEmptyMessage(UPDATE_PROGRESS);
					try {
						Thread.sleep(500);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		};
		mBigPlayBtn.setOnClickListener(this);
		mPlayBtn.setOnClickListener(this);
		mFullScreenBtn.setOnClickListener(this);
		//进度条进度改变监听器
		mPlayProgressBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
			@Override
			public void onStopTrackingTouch(SeekBar seekBar) { 
				handler.sendEmptyMessageDelayed(EXIT_CONTROL_PANEL, 3000);
			}
			@Override
			public void onStartTrackingTouch(SeekBar seekBar) { 
				handler.removeMessages(EXIT_CONTROL_PANEL);
			}
			@Override
			public void onProgressChanged(SeekBar seekBar, int progress,
					boolean fromUser) {
				if(fromUser){
					mVideoView.seekTo(progress);//设置视频
					setPlayTime(progress);//设置时间
				}
			}
		});
		mWidth = this.getWidth();
		mHeigth = this.getHeight();
	}
	
	@Override
	public void onClick(View v) {
		if(v == mView){
			if(mBigPlayBtn.getVisibility() == View.VISIBLE){
				return;
			}
			if(mControlPanel.getVisibility() == View.VISIBLE){
				//执行退出动画
				mControlPanel.startAnimation(outAnima);
				mControlPanel.setVisibility(View.GONE);
			}else {
				//执行进入动画
				mControlPanel.startAnimation(inAnima);
				mControlPanel.setVisibility(View.VISIBLE);
				sendHideControlPanelMessage();
			}
		}
		else if(v.getId() == R.id.big_play_button){//大的播放按钮
			mBigPlayBtn.setVisibility(View.GONE);
			mVideoView.setBackground(null);
			if(!mVideoView.isPlaying()){
				mVideoView.start();
				mPlayBtn.setImageResource(R.drawable.pause_icon);
				//开始更新进度线程
				mUpdateThread = new Thread(mUpdateTask);
				stopThread = false;
				mUpdateThread.start();
			}
		}
		else if(v.getId() == R.id.play_button){//播放/暂停按钮
			if(mVideoView.isPlaying()){
				mVideoView.pause();
				mPlayBtn.setImageResource(R.drawable.play_icon);
			}else{
				if(mUpdateThread == null || !mUpdateThread.isAlive()){
					//开始更新进度线程
					mUpdateThread = new Thread(mUpdateTask);
					stopThread = false;
					mUpdateThread.start();
				}
				mVideoView.start();
				mPlayBtn.setImageResource(R.drawable.pause_icon);
			}
			sendHideControlPanelMessage();
		}
		else if(v.getId() == R.id.full_screen_button){//全屏
			if(context.getResources().getConfiguration().orientation 
					== Configuration.ORIENTATION_PORTRAIT){
				setFullScreen();
			}else{
				setNoFullScreen();
			}
			sendHideControlPanelMessage();
		}
	}

	//设置当前时间
	private void setPlayTime(int millisSecond){
		int currentSecond = millisSecond/1000;
		String currentTime = ((currentSecond/60>9)?(currentSecond/60+""):("0"+currentSecond/60))+":"+
				((currentSecond%60>9)?(currentSecond%60+""):("0"+currentSecond%60));
		StringBuilder text = new StringBuilder(mPlayTime.getText().toString());
		text.replace(0,  text.indexOf("/"), currentTime);
		mPlayTime.setText(text);
	}
	//设置控件的宽高
	private void setSize(){
		ViewGroup.LayoutParams lp = this.getLayoutParams();
		if(mIsFullScreen){
			lp.width = screenSize.y;
			lp.height = screenSize.x;
		}else{
			lp.width = mWidth;
			lp.height = mHeigth;
		}
		this.setLayoutParams(lp);
	}
	
	//两秒后隐藏控制面板
	private void sendHideControlPanelMessage(){
		handler.removeMessages(EXIT_CONTROL_PANEL);
		handler.sendEmptyMessageDelayed(EXIT_CONTROL_PANEL, 3000);
	}
	
	//设置视频路径
	public void setVideoUri(Uri uri){
		this.mVideoUri = uri;
		mVideoView.setVideoURI(mVideoUri);
	}
	//获取视频路径
	public Uri getVideoUri(){
		return mVideoUri;
	}
	
	//设置视频初始画面
	public void setInitPicture(Drawable d){
		mVideoView.setBackground(d);
	}
	//挂起视频
	public void suspend(){
		if(mVideoView != null){
			mVideoView.suspend();
		}
	}
	//设置视频进度
	public void setVideoProgress(int millisSecond,boolean isPlaying){
		mVideoView.setBackground(null);
		mBigPlayBtn.setVisibility(View.GONE);
		mPlayProgressBar.setProgress(millisSecond);
		setPlayTime(millisSecond);
		if(mUpdateThread == null || !mUpdateThread.isAlive()){
			mUpdateThread = new Thread(mUpdateTask);
			stopThread = false;
			mUpdateThread.start();
		}
		mVideoView.seekTo(millisSecond);
		if(isPlaying){
			mVideoView.start();
			mPlayBtn.setImageResource(R.drawable.pause_icon);
		}else{
			mVideoView.pause();
			mPlayBtn.setImageResource(R.drawable.play_icon);
		}
	}
	//获取视频进度
	public int getVideoProgress(){
		return mVideoView.getCurrentPosition();
	}
	//判断视频是否正在播放
	public boolean isPlaying(){
		return mVideoView.isPlaying();
	}
	//判断是否为全屏状态
	public boolean isFullScreen(){
		return mIsFullScreen;
	}
	//设置竖屏
	public void setNoFullScreen(){
		this.mIsFullScreen = false;
		Activity ac = (Activity)context;
		ac.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
		ac.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
		setSize();
	}
	//设置横屏
	public void setFullScreen(){
		this.mIsFullScreen = true;
		Activity ac = (Activity)context;
		ac.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
		ac.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
		setSize();
	}
	
}

3.隐藏和显示播放控制面板的动画

进入动画enter_from_bottom.xml

<?xml version="1.0" encoding="utf-8"?>
<translate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromYDelta="100%"
	android:toYDelta="0"
	android:duration="400"
</translate>

退出动画exit_from_bottom.xml

<?xml version="1.0" encoding="utf-8"?>
<translate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromYDelta="0"
	android:toYDelta="100%"
	android:duration="400"
</translate>

4.播放本地视频和网络视频需要的权限:

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


5.改变屏幕方向

        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" 
            android:configChanges="keyboardHidden|orientation|screenSize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

不注明keyboardHidden|orientation|screenSize屏幕方向改变时会停止播放


6.activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
     >
    <com.example.test.SimpleVideoView
        android:id="@+id/video"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />
</LinearLayout>


7.MainActivity类

package com.example.test;

import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity{
	private SimpleVideoView video;
	private String videoPath;
	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        video = (SimpleVideoView) findViewById(R.id.video);
        video.setInitPicture(getResources().getDrawable(R.drawable.ic_launcher,null));
        //网络视频地址
        videoPath = "http://112.253.22.157/17/z/z/y/u/zzyuasjwufnqerzvyxgkuigrkcatxr/hc.yinyuetai.com/D046015255134077DDB3ACA0D7E68D45.flv";
        //本地视频路径
        //videoPath= "/storage/emulated/0/Android/data/com.boohee.one/.SPORT_VIDEOS/1pfl0bzsp1mhs3ur1cahe82x1.mp4";
        videoPath = "/storage/emulated/0/tencent/QQfile_recv/这货是一条鳄鱼.mp4";
        video.setVideoUri(Uri.parse(videoPath));
        
    }
	
	@Override
	protected void onDestroy(){
		super.onDestroy();
		video.suspend();
	}
	
	@Override
	public void onBackPressed(){
		if(video.isFullScreen()){
			video.setNoFullScreen();
		}else{
			super.onBackPressed();
		}
	}
}


非全屏效果:


全屏效果:





评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值