VideoView plus custom Controller to play video

I believe that those who do Android development have generally done playing web videos. Everyone generally uses VideoView to play web videos. There is also a Controller to control the pause or fast forward of the video. But the style of Controller cannot be changed to be particularly ugly. Can't meet the high-end UI experience.

Complete a custom playback controller, and a simple horizontal and vertical screen switching function. Probably record the process:

1. Customize MyVideoView, in order to solve the problem that may not cover the entire screen and cause blank edges.

public class MyVideoView extends VideoView {
    public MyVideoView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = getDefaultSize(0,widthMeasureSpec);
        int height = getDefaultSize(0,heightMeasureSpec);
        setMeasuredDimension(width,height);
    }
}

2. Put VideoView and Controller into an xml file in a layout.

<?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="match_parent">

    <RelativeLayout
        android:id="@+id/rl_content"
        android:layout_width="match_parent"
        android:layout_height="200dp">
        <!-- 播放视频的VideoView -->
        <com.teach.myapplication.MyVideoView
            android:id="@+id/videoView"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
        <!-- 控制器 -->
        <RelativeLayout
            android:id="@+id/rl"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true">
            <!-- 自定义样式后的SeekBar进度条 -->
            <SeekBar
                android:id="@+id/sb"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_above="@+id/ll"
                android:maxHeight="4dp"
                android:minHeight="4dp"
                android:paddingLeft="16dp"
                android:paddingRight="16dp"
                android:progressDrawable="@drawable/seekbar_shape"
                android:thumb="@mipmap/icon_seekbar_button"
                android:thumbOffset="20dp" />

            <LinearLayout
                android:paddingBottom="3dp"
                android:id="@+id/ll"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:layout_marginLeft="16dp"
                android:orientation="horizontal">
                <!-- 当前播放位置 -->
                <TextView
                    android:id="@+id/tv_process_date"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="00:00"
                    android:textColor="#0E83F8"
                    android:textSize="13sp" />

                <TextView
                    android:id="@+id/tv"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="/"
                    android:textColor="#FFFFFF"
                    android:textSize="13sp" />
                <!-- 视频总时长 -->
                <TextView
                    android:id="@+id/tv_all_date"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="00:00"
                    android:textColor="#FFFFFF"
                    android:textSize="13sp" />
            </LinearLayout>
            <!-- 全屏按钮 -->
            <ImageView
                android:paddingBottom="3dp"
                android:id="@+id/iv_full_screen"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_alignParentBottom="true"
                android:layout_marginRight="16dp"
                android:src="@mipmap/icon_quanping" />
            <!-- 播放暂停按钮 -->
            <ImageView
                android:id="@+id/iv_play_or_pause"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_above="@+id/sb"
                android:layout_centerHorizontal="true"
                android:src="@mipmap/icon_dianbo_play" />
        </RelativeLayout>

    </RelativeLayout>
</RelativeLayout>

3. Custom MediaView

/**
 * 自定义的视频播放器
 */
public class MediaView extends FrameLayout implements SeekBar.OnSeekBarChangeListener, View.OnClickListener, MediaPlayer.OnPreparedListener, View.OnTouchListener {
    /**
     * 视频播放VideoView
     */
    private MyVideoView videoView;
    /**
     * 进度SeekBar
     */
    private SeekBar sb;
    /**
     * 播放总时长 和当前播放时长
     */
    private TextView tv_process_date, tv_all_date;
    /**
     * 全屏播放按钮
     */
    private ImageView iv_full_screen;
    /**
     * 播放或者暂停按钮
     */
    private ImageView iv_play_or_pause;
    /**
     * 播放控制器
     */
    private RelativeLayout rl, rl_content;
    /**
     * 是否正在播放视频
     */
    private boolean playing;
    /**
     * 当前播放至的进度
     */
    private int progress;
    /**
     * 时间定时器
     */
    private Timer timer;
    private TimerTask task;
    private Handler handler;
    /**
     * 是否展示控制器
     */
    private boolean showIng;
    private Context context;
    private boolean isFullScreen;
    private int mHeight;

    public MediaView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        View view = LayoutInflater.from(context).inflate(R.layout.my_mediacontroller_layout, this, true);
        videoView = view.findViewById(R.id.videoView);
        sb = view.findViewById(R.id.sb);
        sb.setOnSeekBarChangeListener(this);
        tv_process_date = view.findViewById(R.id.tv_process_date);
        tv_all_date = view.findViewById(R.id.tv_all_date);
        iv_full_screen = view.findViewById(R.id.iv_full_screen);
        iv_full_screen.setOnClickListener(this);
        iv_play_or_pause = view.findViewById(R.id.iv_play_or_pause);
        iv_play_or_pause.setOnClickListener(this);
        rl = view.findViewById(R.id.rl);
        rl_content = view.findViewById(R.id.rl_content);
        videoView.setOnTouchListener(this);
        handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                if (msg.what == 1) {
                    //do something
                    sb.setProgress(videoView.getCurrentPosition());
                    tv_process_date.setText(DateFormatUtils.getDateFormat(videoView.getCurrentPosition()));
                } else if (msg.what == 2) {
                    rl.setVisibility(View.GONE);
                    showIng = false;
                }
                super.handleMessage(msg);
            }
        };
    }

    /**
     * 播放器准备
     *
     * @param url
     */
    public void start(String url) {
        videoView.setVideoPath(url);
        videoView.setOnPreparedListener(this);
    }

    /**
     * 播放
     */
    public void play() {
        videoView.seekTo(videoView.getCurrentPosition());
        playing = true;
        videoView.start();
        Log.e("lee", "播放的时候" + DateFormatUtils.getDateFormat(videoView.getCurrentPosition()));
        Log.e("lee", "播放的时候" + videoView.getCurrentPosition());
        timer = new Timer();
        task = new TimerTask() {
            @Override
            public void run() {
                Message message = new Message();
                message.what = 1;
                handler.sendMessage(message);
            }
        };
        timer.schedule(task, 0, 1000);
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                Message message = new Message();
                message.what = 2;
                handler.sendMessage(message);
            }
        }, 5000);
        iv_play_or_pause.setImageResource(R.mipmap.icon_dianbo_pause);
    }

    /**
     * 暂停
     */
    public void pause() {
        videoView.pause();
        Log.e("lee", "暂停的时候" + DateFormatUtils.getDateFormat(videoView.getCurrentPosition()));
        Log.e("lee", "暂停的时候" + videoView.getCurrentPosition());
        timer.cancel();
    }

    /**
     * seekbar监听器
     */
    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        tv_process_date.setText(DateFormatUtils.getDateFormat(progress));
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
        videoView.pause();
    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
        videoView.seekTo(seekBar.getProgress());
        videoView.start();
        playing = true;
        iv_play_or_pause.setImageResource(R.mipmap.icon_dianbo_pause);
    }

    /**
     * 点击事件
     *
     * @param v
     */
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.iv_play_or_pause://播放暂停按钮
                if (playing) {//正在播放 (点击暂停)
                    iv_play_or_pause.setImageResource(R.mipmap.icon_dianbo_play);
                    pause();
                    playing = false;
                } else {//正在暂停 (点击播放)
                    iv_play_or_pause.setImageResource(R.mipmap.icon_dianbo_pause);
                    play();
                    playing = true;
                }
                break;
            case R.id.iv_full_screen:
                if (!isFullScreen) {//竖屏状态(切换成横屏)
                    //首先获得原来的高度
                    mHeight = rl_content.getHeight();
                    //重新制定高度
                    RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) rl_content.getLayoutParams();
                    params.height = ViewGroup.LayoutParams.MATCH_PARENT;
                    params.width = ViewGroup.LayoutParams.MATCH_PARENT;
                    ((MainActivity) context).getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);//显示顶部状态栏
                    ((MainActivity) context).getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
                    ((MainActivity) context).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                    rl_content.setLayoutParams(params);
                    isFullScreen = true;
                } else {//横屏状态(切换成竖屏)
                    RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) rl_content.getLayoutParams();
                    params.height = mHeight;
                    params.width = ViewGroup.LayoutParams.MATCH_PARENT;
                    ((MainActivity) context).getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);//全屏不 显示顶部状态栏
                    ((MainActivity) context).getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
                    ((MainActivity) context).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                    rl_content.setLayoutParams(params);
                    isFullScreen = false;
                }
                break;
            default:

                break;
        }
    }

    /**
     * 视频加载成功
     *
     * @param mp
     */
    @Override
    public void onPrepared(MediaPlayer mp) {
        sb.setMax(videoView.getDuration());
        tv_process_date.setText(DateFormatUtils.getDateFormat(videoView.getCurrentPosition()));
        tv_all_date.setText(DateFormatUtils.getDateFormat(videoView.getDuration()));
        //播放
        play();

        /**
         * 视频播放完成监听
         */
        mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mp) {
                videoView.seekTo(0);
                sb.setProgress(0);
                playing = false;
                rl.setVisibility(View.VISIBLE);
                showIng = true;
                iv_play_or_pause.setImageResource(R.mipmap.icon_dianbo_play);
            }
        });
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                Log.e("lee", "ACTION_DOWN");
                rl.setVisibility(View.VISIBLE);
                showIng = true;
                if (showIng) {
                    handler.removeMessages(2);
                }
                break;
            case MotionEvent.ACTION_MOVE:
                Log.e("lee", "ACTION_MOVE");
                if (showIng) {
                    handler.removeMessages(2);
                }
                break;
            case MotionEvent.ACTION_UP:
                Log.e("lee", "ACTION_DOWN");
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        Message message = new Message();
                        message.what = 2;
                        handler.sendMessage(message);
                    }
                }, 5000);
                break;
            default:
                break;
        }
        return true;
    }
}

4. External call

Code in Activity

 mediaView = findViewById(R.id.view);
 mediaView.start("http://vfx.mtime.cn/Video/2019/06/26/mp4/190626111517361726.mp4");

xml code

    <com.teach.myapplication.MediaView
        android:id="@+id/view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

Note that Activity should be added in the manifest file

android:screenOrientation="portrait"
android:configChanges="orientation|screenSize|keyboardHidden"

5. The style of seekbar seekbar_shape.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@android:id/background">
        <shape>
            <corners android:radius="2dp" />
            <solid android:color="#33FFFFFF" />
        </shape>
    </item>

    <item android:id="@android:id/secondaryProgress">
        <clip>
            <shape>
                <corners android:radius="2dp" />
                <solid android:color="#77FFFFFF" />
            </shape>
        </clip>
    </item>

    <item android:id="@android:id/progress">
        <clip>
            <shape>
                <corners android:radius="2dp" />
                <solid android:color="#0E83F8" />
            </shape>
        </clip>
    </item>
</layer-list>

The above has completed the simple custom playback controller and can simply switch the playback function between horizontal and vertical screens, and the pause and playback icons will not be uploaded, just replace with your own name.

Guess you like

Origin blog.csdn.net/qq77485042/article/details/105840471