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

来源:互联网 发布:淘宝开放平台 编辑:程序博客网 时间:2024/06/05 14:20

下面是自己写的一个视频播放器,只是用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>    <!-- 大播放按钮 -->    <ImageViewandroid: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() {@Overridepublic void onPrepared(MediaPlayer mp) {//视频加载完成后才能获取视频时长initVideo();}});//视频播放完成监听器mVideoView.setOnCompletionListener(new OnCompletionListener() {@Overridepublic 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(){@Overridepublic 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() {@Overridepublic void onStopTrackingTouch(SeekBar seekBar) { handler.sendEmptyMessageDelayed(EXIT_CONTROL_PANEL, 3000);}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) { handler.removeMessages(EXIT_CONTROL_PANEL);}@Overridepublic void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) {if(fromUser){mVideoView.seekTo(progress);//设置视频setPlayTime(progress);//设置时间}}});mWidth = this.getWidth();mHeigth = this.getHeight();}@Overridepublic 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));            }@Overrideprotected void onDestroy(){super.onDestroy();video.suspend();}@Overridepublic void onBackPressed(){if(video.isFullScreen()){video.setNoFullScreen();}else{super.onBackPressed();}}}


非全屏效果:


全屏效果:





0 0