Android自己定制MediaController

   今天终于把这个给调通了。怪自己太笨。留着

 我把三个主要的类公布:先是MediaController

/*
 * Copyright (C) 2006 The Android Open Source Project
 * Copyright (C) 2013 YIXIA.COM
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.widget;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Rect;
import android.media.AudioManager;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.PopupWindow;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

import java.lang.reflect.Method;

import com.android.widget.OutlineTextView;
import com.example.revideoview.R;

//import io.vov.vitamio.utils.Log;

/**
 * 针对普通播放的MediaController
 * 
 * @author Catherine
 * 
 */
public class MediaController extends FrameLayout {
    private static final int sDefaultTimeout = 3000;
    private static final int FADE_OUT = 1;
    private static final int SHOW_PROGRESS = 2;
    private MediaPlayerControl mPlayer;
    private Context mContext;
    private PopupWindow mWindow;
    private int mAnimStyle;
    private View mAnchor;
    private View mRoot;
    private SeekBar mProgress;
    private TextView mEndTime, mCurrentTime;
    private TextView mFileName;
    private OutlineTextView mInfoView;
    private String mTitle;
    private long mDuration;
    private boolean mShowing;
    private boolean mDragging;
    private boolean mInstantSeeking = true;
    private boolean mFromXml = false;
    private ImageButton mPauseButton;
    private AudioManager mAM;
    private OnShownListener mShownListener;
    private OnHiddenListener mHiddenListener;
    @SuppressLint("HandlerLeak")
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            long pos;
            switch (msg.what) {
            case FADE_OUT:
                hide();
                break;
            case SHOW_PROGRESS:
                pos = setProgress();
                if (!mDragging && mShowing) {
                    msg = obtainMessage(SHOW_PROGRESS);
                    sendMessageDelayed(msg, 1000 - (pos % 1000));
                    updatePausePlay();
                }
                break;
            }
        }
    };
    private View.OnClickListener mPauseListener = new View.OnClickListener() {
        public void onClick(View v) {
            System.out.println("dot the pause");
            doPauseResume();
            show(sDefaultTimeout);
        }
    };
    private OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() {
        public void onStartTrackingTouch(SeekBar bar) {
            mDragging = true;
            show(3600000);
            mHandler.removeMessages(SHOW_PROGRESS);
            if (mInstantSeeking)
                mAM.setStreamMute(AudioManager.STREAM_MUSIC, true);
            if (mInfoView != null) {
                mInfoView.setText("");
                mInfoView.setVisibility(View.VISIBLE);
            }
        }

        public void onProgressChanged(SeekBar bar, int progress,
                boolean fromuser) {
            if (!fromuser)
                return;

            long newposition = (mDuration * progress) / 1000;
            String time = StringTools.generateTime(newposition);
            if (mInstantSeeking)
                mPlayer.seekTo(newposition);
            if (mInfoView != null)
                mInfoView.setText(time);
            if (mCurrentTime != null)
                mCurrentTime.setText(time);
        }

        public void onStopTrackingTouch(SeekBar bar) {
            if (!mInstantSeeking)
                mPlayer.seekTo((mDuration * bar.getProgress()) / 1000);
            if (mInfoView != null) {
                mInfoView.setText("");
                mInfoView.setVisibility(View.GONE);
            }
            show(sDefaultTimeout);
            mHandler.removeMessages(SHOW_PROGRESS);
            mAM.setStreamMute(AudioManager.STREAM_MUSIC, false);
            mDragging = false;
            mHandler.sendEmptyMessageDelayed(SHOW_PROGRESS, 1000);
        }
    };

    public MediaController(Context context, AttributeSet attrs) {
        super(context, attrs);
        mRoot = this;
        mFromXml = true;
        initController(context);
    }

    public MediaController(Context context) {
        super(context);
        if (!mFromXml && initController(context))
            initFloatingWindow();
    }

    private boolean initController(Context context) {
        mContext = context;
        mAM = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
        return true;
    }

    @Override
    public void onFinishInflate() {
        if (mRoot != null)
            initControllerView(mRoot);
    }

    private void initFloatingWindow() {
        mWindow = new PopupWindow(mContext);
        mWindow.setFocusable(false);
        mWindow.setBackgroundDrawable(null);
        mWindow.setOutsideTouchable(true);
        mAnimStyle = android.R.style.Animation;
    }

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    public void setWindowLayoutType() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            try {
                mAnchor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
                Method setWindowLayoutType = PopupWindow.class.getMethod(
                        "setWindowLayoutType", new Class[] { int.class });
                setWindowLayoutType
                        .invoke(mWindow,
                                WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG);
            } catch (Exception e) {
                // Log.e("setWindowLayoutType", e);
            }
        }
    }

    /**
     * Set the view that acts as the anchor for the control view. This can for
     * example be a VideoView, or your Activity's main view.
     * 
     * @param view
     *            The view to which to anchor the controller when it is visible.
     */
    public void setAnchorView(View view) {
        mAnchor = view;
        if (!mFromXml) {
            removeAllViews();
            mRoot = makeControllerView();
            mWindow.setContentView(mRoot);
            mWindow.setWidth(LayoutParams.MATCH_PARENT);
            mWindow.setHeight(LayoutParams.WRAP_CONTENT);
        }
        initControllerView(mRoot);
    }

    /**
     * Create the view that holds the widgets that control playback. Derived
     * classes can override this to create their own.
     * 
     * @return The controller view.
     */
    protected View makeControllerView() {
        return ((LayoutInflater) mContext
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(
                R.layout.mediacontroller, this);
    }

    private void initControllerView(View v) {
        mPauseButton = (ImageButton) v
                .findViewById(R.id.mediacontroller_play_pause);
        if (mPauseButton != null) {
            mPauseButton.requestFocus();
            mPauseButton.setOnClickListener(mPauseListener);
        }

        mProgress = (SeekBar) v.findViewById(R.id.mediacontroller_seekbar);
        if (mProgress != null) {
            if (mProgress instanceof SeekBar) {
                SeekBar seeker = (SeekBar) mProgress;
                seeker.setOnSeekBarChangeListener(mSeekListener);
                seeker.setThumbOffset(1);
            }
            mProgress.setMax(1000);
        }

        mEndTime = (TextView) v.findViewById(R.id.mediacontroller_time_total);
        mCurrentTime = (TextView) v
                .findViewById(R.id.mediacontroller_time_current);
        mFileName = (TextView) v.findViewById(R.id.mediacontroller_file_name);
        if (mFileName != null)
            mFileName.setText(mTitle);
    }

    public void setMediaPlayer(MediaPlayerControl player) {
        mPlayer = player;
        updatePausePlay();
    }

    /**
     * Control the action when the seekbar dragged by user
     * 
     * @param seekWhenDragging
     *            True the media will seek periodically
     */
    public void setInstantSeeking(boolean seekWhenDragging) {
        mInstantSeeking = seekWhenDragging;
    }

    public void show() {
        show(sDefaultTimeout);
    }

    /**
     * Set the content of the file_name TextView
     * 
     * @param name
     */
    public void setFileName(String name) {
        mTitle = name;
        if (mFileName != null)
            mFileName.setText(mTitle);
    }

    /**
     * Set the View to hold some information when interact with the
     * MediaController
     * 
     * @param v
     */
    public void setInfoView(OutlineTextView v) {
        mInfoView = v;
    }

    private void disableUnsupportedButtons() {
        try {
            if (mPauseButton != null && !mPlayer.canPause())
                mPauseButton.setEnabled(true);
        } catch (IncompatibleClassChangeError ex) {
        }
    }

    /**
     * <p>
     * Change the animation style resource for this controller.
     * </p>
     * <p/>
     * <p>
     * If the controller is showing, calling this method will take effect only
     * the next time the controller is shown.
     * </p>
     * 
     * @param animationStyle
     *            animation style to use when the controller appears and
     *            disappears. Set to -1 for the default animation, 0 for no
     *            animation, or a resource identifier for an explicit animation.
     */
    public void setAnimationStyle(int animationStyle) {
        mAnimStyle = animationStyle;
    }

    /**
     * Show the controller on screen. It will go away automatically after
     * 'timeout' milliseconds of inactivity.
     * 
     * @param timeout
     *            The timeout in milliseconds. Use 0 to show the controller
     *            until hide() is called.
     */
    public void show(int timeout) {
        if (!mShowing && mAnchor != null && mAnchor.getWindowToken() != null) {
            if (mPauseButton != null)
                mPauseButton.requestFocus();
            disableUnsupportedButtons();

            if (mFromXml) {
                setVisibility(View.VISIBLE);
            } else {
                int[] location = new int[2];

                mAnchor.getLocationOnScreen(location);
                Rect anchorRect = new Rect(location[0], location[1],
                        location[0] + mAnchor.getWidth(), location[1]
                                + mAnchor.getHeight());

                mWindow.setAnimationStyle(mAnimStyle);
                setWindowLayoutType();
                mWindow.showAtLocation(mAnchor, Gravity.NO_GRAVITY,
                        anchorRect.left, anchorRect.bottom);
            }
            mShowing = true;
            if (mShownListener != null)
                mShownListener.onShown();
        }
        updatePausePlay();
        mHandler.sendEmptyMessage(SHOW_PROGRESS);

        if (timeout != 0) {
            mHandler.removeMessages(FADE_OUT);
            mHandler.sendMessageDelayed(mHandler.obtainMessage(FADE_OUT),
                    timeout);
        }
    }

    public boolean isShowing() {
        return mShowing;
    }

    public void hide() {
        if (mAnchor == null)
            return;

        if (mShowing) {
            try {
                mHandler.removeMessages(SHOW_PROGRESS);
                if (mFromXml)
                    setVisibility(View.GONE);
                else
                    mWindow.dismiss();
            } catch (IllegalArgumentException ex) {
                // Log.d("MediaController already removed");
            }
            mShowing = false;
            if (mHiddenListener != null)
                mHiddenListener.onHidden();
        }
    }

    public void setOnShownListener(OnShownListener l) {
        mShownListener = l;
    }

    public void setOnHiddenListener(OnHiddenListener l) {
        mHiddenListener = l;
    }

    private long setProgress() {
        if (mPlayer == null || mDragging)
            return 0;

        long position = mPlayer.getCurrentPosition();
        long duration = mPlayer.getDuration();
        if (mProgress != null) {
            if (duration > 0) {
                long pos = 1000L * position / duration;
                mProgress.setProgress((int) pos);
            }
            int percent = mPlayer.getBufferPercentage();
            mProgress.setSecondaryProgress(percent * 10);
        }

        mDuration = duration;

        if (mEndTime != null)
            mEndTime.setText(StringTools.generateTime(mDuration));
        if (mCurrentTime != null)
            mCurrentTime.setText(StringTools.generateTime(position));

        return position;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        show(sDefaultTimeout);
        return true;
    }

    @Override
    public boolean onTrackballEvent(MotionEvent ev) {
        show(sDefaultTimeout);
        return false;
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        System.out.println("this is dispatchKeyEvent");
        int keyCode = event.getKeyCode();
        if (event.getRepeatCount() == 0
                && (keyCode == KeyEvent.KEYCODE_HEADSETHOOK
                        || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || keyCode == KeyEvent.KEYCODE_SPACE)) {
            doPauseResume();
            show(sDefaultTimeout);
            if (mPauseButton != null)
                mPauseButton.requestFocus();
            return true;
        } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP) {
            if (mPlayer.isPlaying()) {
                mPlayer.pause();
                updatePausePlay();
            }
            return true;
        } else if (keyCode == KeyEvent.KEYCODE_BACK
                || keyCode == KeyEvent.KEYCODE_MENU) {
            hide();
            return true;
        } else {
            show(sDefaultTimeout);
        }
        return super.dispatchKeyEvent(event);
    }

    private void updatePausePlay() {
        if (mRoot == null || mPauseButton == null)
            return;

        if (mPlayer.isPlaying())
            mPauseButton
                    .setImageResource(R.drawable.mediacontroller_pause_button);
        else
            mPauseButton
                    .setImageResource(R.drawable.mediacontroller_play_button);
    }

    private void doPauseResume() {
        if (mPlayer.isPlaying())
            mPlayer.pause();
        else
            mPlayer.start();
        updatePausePlay();
    }

    @Override
    public void setEnabled(boolean enabled) {
        if (mPauseButton != null)
            mPauseButton.setEnabled(enabled);
        if (mProgress != null)
            mProgress.setEnabled(enabled);
        disableUnsupportedButtons();
        super.setEnabled(enabled);
    }

    public interface OnShownListener {
        public void onShown();
    }

    public interface OnHiddenListener {
        public void onHidden();
    }

    public interface MediaPlayerControl {
        void start();

        void pause();

        long getDuration();

        long getCurrentPosition();

        void seekTo(long pos);

        boolean isPlaying();

        int getBufferPercentage();

        boolean canPause();

        boolean canSeekBackward();

        boolean canSeekForward();
    }

}
package com.android.widget;

import java.io.IOException;

import com.android.widget.CustomProgressDialog;
import com.android.widget.MediaController.MediaPlayerControl;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.ViewGroup.LayoutParams;
import android.widget.FrameLayout;

/**
 * 针对普通播放的VideoView
 * 
 * @author Catherine
 * 
 */
public class VideoView extends SurfaceView implements MediaPlayerControl,
        View.OnClickListener {

    private Context mContext;

    private String mUri = "";

    private int mDuration;

    // All the stuff we need for playing and showing a video
    private SurfaceHolder mSurfaceHolder = null;
    private MediaPlayer mMediaPlayer = null;
    private boolean mIsPrepared;
    public static int mVideoWidth;
    public static int mVideoHeight;
    private int mSurfaceWidth;
    private int mSurfaceHeight;
    private MediaController mMediaController;
    public OnCompletionListener mOnCompletionListener;
    private MediaPlayer.OnPreparedListener mOnPreparedListener;
    private int mCurrentBufferPercentage;
    private OnErrorListener mOnErrorListener;
    private boolean mStartWhenPrepared;
    private int mSeekWhenPrepared;

    private MySizeChangeLinstener mMyChangeLinstener;

    public int getVideoWidth() {
        return mVideoWidth;
    }

    public int getVideoHeight() {
        return mVideoHeight;
    }

    public void setVideoScale(int width, int height) {
        LayoutParams lp = getLayoutParams();
        lp.height = height;
        lp.width = width;
        setLayoutParams(lp);
    }

    public interface MySizeChangeLinstener {
        public void doMyThings();
    }

    public void setMySizeChangeLinstener(MySizeChangeLinstener l) {
        mMyChangeLinstener = l;
    }

    public VideoView(Context context) {
        super(context);
        mContext = context;
        initVideoView();
    }

    public VideoView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
        mContext = context;
        initVideoView();
    }

    public VideoView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mContext = context;
        initVideoView();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // Log.i("@@@@", "onMeasure");
        int width = getDefaultSize(mVideoWidth, widthMeasureSpec);
        int height = getDefaultSize(mVideoHeight, heightMeasureSpec);
        setMeasuredDimension(width, height);
    }

    public void setVideofullScale(int width, int height) {
        FrameLayout.LayoutParams lp = (android.widget.FrameLayout.LayoutParams) getLayoutParams();
        lp.height = height;
        lp.width = width;
        lp.setMargins(0, 0, 0, 0);
        setLayoutParams(lp);
        getHolder().setFixedSize(width, height);
    }

    public void setVideoDefaultScale(int width, int height) {
        FrameLayout.LayoutParams lp = (android.widget.FrameLayout.LayoutParams) getLayoutParams();
        lp.height = height;
        lp.width = width;
        lp.setMargins(258, 85, 0, 0);
        setLayoutParams(lp);
        getHolder().setFixedSize(width, height);
    }

    public int resolveAdjustedSize(int desiredSize, int measureSpec) {
        int result = desiredSize;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        switch (specMode) {
        case MeasureSpec.UNSPECIFIED:

            result = desiredSize;
            break;

        case MeasureSpec.AT_MOST:

            result = Math.min(desiredSize, specSize);
            break;

        case MeasureSpec.EXACTLY:
            // No choice. Do what we are told.
            result = specSize;
            break;
        }
        return result;
    }

    private CustomProgressDialog dialog;

    private WindowManager wm;

    private void initVideoView() {
        
        mVideoWidth = 0;
        mVideoHeight = 0;
        getHolder().addCallback(mSHCallback);
        getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        setFocusable(true);
        setFocusableInTouchMode(true);
        requestFocus();

        dialog = new CustomProgressDialog(mContext);
    }

    public void setVideoPath(String path) {
        setVideoURI(path);
    }

    public void setVideoURI(String uri) {
        mUri = uri;
        mStartWhenPrepared = false;
        mSeekWhenPrepared = 0;
        openVideo();
        requestLayout();
        invalidate();
    }

    public void stopPlayback() {
        if (mMediaPlayer != null) {
            mMediaPlayer.stop();
            mMediaPlayer.release();
            mMediaPlayer = null;
        }
    }

    private void openVideo() {
        if (mUri == null || mSurfaceHolder == null) {

            return;
        }

        if (mMediaPlayer != null) {
            mMediaPlayer.reset();
            mMediaPlayer.release();
            mMediaPlayer = null;
        }
        try {
            mMediaPlayer = new MediaPlayer();
            mMediaPlayer.setOnPreparedListener(mPreparedListener);
            mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener);
            mMediaPlayer.setOnInfoListener(mInfoListener);
            mIsPrepared = false;
            mDuration = -1;
            mMediaPlayer.setOnCompletionListener(mCompletionListener);
            mMediaPlayer.setOnErrorListener(mErrorListener);
            mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
            mCurrentBufferPercentage = 0;
            mMediaPlayer.setDataSource(mUri);

            mMediaPlayer.setDisplay(mSurfaceHolder);
            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mMediaPlayer.setScreenOnWhilePlaying(true);
            mMediaPlayer.prepareAsync();
            attachMediaController();
        } catch (IOException ex) {
            return;
        } catch (IllegalArgumentException ex) {
            return;
        }
    }

    MediaPlayer.OnInfoListener mInfoListener = new MediaPlayer.OnInfoListener() {

        @Override
        public boolean onInfo(MediaPlayer mp, int what, int extra) {
            WindowManager.LayoutParams params = new WindowManager.LayoutParams();
            params.gravity = Gravity.CENTER;
            params.width = LayoutParams.WRAP_CONTENT;
            params.height = LayoutParams.WRAP_CONTENT;
            switch (what) {
            case MediaPlayer.MEDIA_INFO_BUFFERING_START:
                if (dialog != null && !dialog.isShowing()) {
                    dialog.show();
                }
                break;
            case MediaPlayer.MEDIA_INFO_BUFFERING_END:
                if (dialog != null && dialog.isShowing()) {
                    dialog.cancel();
                }
                break;
            case MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START:
                if (dialog != null && dialog.isShowing()) {
                    dialog.cancel();
                }
                break;
            }
            return true;
        }

    };

    public void setMediaController(MediaController controller) {
        if (mMediaController != null) {
            mMediaController.hide();
        }
        mMediaController = controller;
        attachMediaController();
    }

    private void attachMediaController() {
        if (mMediaPlayer != null && mMediaController != null) {
            mMediaController.setMediaPlayer(this);
            View anchorView = this.getParent() instanceof View ? (View) this
                    .getParent() : this;
            mMediaController.setAnchorView(anchorView);
            mMediaController.setEnabled(mIsPrepared);
        }
    }

    MediaPlayer.OnVideoSizeChangedListener mSizeChangedListener = new MediaPlayer.OnVideoSizeChangedListener() {
        public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
            mVideoWidth = mp.getVideoWidth();
            mVideoHeight = mp.getVideoHeight();

            if (mMyChangeLinstener != null) {
                mMyChangeLinstener.doMyThings();
            }

            if (mVideoWidth != 0 && mVideoHeight != 0) {
                getHolder().setFixedSize(mVideoWidth, mVideoHeight);
            }
        }
    };

    MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() {
        public void onPrepared(MediaPlayer mp) {
            // briefly show the mediacontroller
            mIsPrepared = true;
            if (mOnPreparedListener != null) {
                mOnPreparedListener.onPrepared(mMediaPlayer);
            }
            if (mMediaController != null) {
                mMediaController.setEnabled(true);
            }
            mVideoWidth = mp.getVideoWidth();
            mVideoHeight = mp.getVideoHeight();
            if (mVideoWidth != 0 && mVideoHeight != 0) {
                // Log.i("@@@@", "video size: " + mVideoWidth +"/"+
                // mVideoHeight);
                getHolder().setFixedSize(mVideoWidth, mVideoHeight);
                if (mSurfaceWidth == mVideoWidth
                        && mSurfaceHeight == mVideoHeight) {
                    // We didn't actually change the size (it was already at the
                    // size
                    // we need), so we won't get a "surface changed" callback,
                    // so
                    // start the video here instead of in the callback.
                    if (mSeekWhenPrepared != 0) {
                        mMediaPlayer.seekTo(mSeekWhenPrepared);
                        mSeekWhenPrepared = 0;
                    }
                    if (mStartWhenPrepared) {
                        mMediaPlayer.start();
                        mStartWhenPrepared = false;
                        if (mMediaController != null) {
                            mMediaController.show();
                        }
                    } else if (!isPlaying()
                            && (mSeekWhenPrepared != 0 || getCurrentPosition() > 0)) {
                        if (mMediaController != null) {
                            // Show the media controls when we're paused into a
                            // video and make 'em stick.
                            mMediaController.show(0);
                        }
                    }
                }
            } else {
                // We don't know the video size yet, but should start anyway.
                // The video size might be reported to us later.
                if (mSeekWhenPrepared != 0) {
                    mMediaPlayer.seekTo(mSeekWhenPrepared);
                    mSeekWhenPrepared = 0;
                }
                if (mStartWhenPrepared) {
                    mMediaPlayer.start();
                    mStartWhenPrepared = false;
                }
            }
        }
    };

    private MediaPlayer.OnCompletionListener mCompletionListener = new MediaPlayer.OnCompletionListener() {
        public void onCompletion(MediaPlayer mp) {
            if (mMediaController != null) {
                mMediaController.hide();
            }
            if (mOnCompletionListener != null) {
                mOnCompletionListener.onCompletion(mMediaPlayer);
            }
        }
    };

    private MediaPlayer.OnErrorListener mErrorListener = new MediaPlayer.OnErrorListener() {
        public boolean onError(MediaPlayer mp, int framework_err, int impl_err) {
            if (mMediaController != null) {
                mMediaController.hide();
            }

            /* If an error handler has been supplied, use it and finish. */
            if (mOnErrorListener != null) {
                if (mOnErrorListener.onError(mMediaPlayer, framework_err,
                        impl_err)) {
                    return true;
                }
            }
            if (getWindowToken() != null) {
                Resources r = mContext.getResources();
                int messageId;
            }
            return true;
        }
    };

    private MediaPlayer.OnBufferingUpdateListener mBufferingUpdateListener = new MediaPlayer.OnBufferingUpdateListener() {
        public void onBufferingUpdate(MediaPlayer mp, int percent) {
            mCurrentBufferPercentage = percent;
        }
    };

    /**
     * Register a callback to be invoked when the media file is loaded and ready
     * to go.
     * 
     * @param l
     *            The callback that will be run
     */
    public void setOnPreparedListener(MediaPlayer.OnPreparedListener l) {
        mOnPreparedListener = l;
    }

    /**
     * Register a callback to be invoked when the end of a media file has been
     * reached during playback.
     * 
     * @param l
     *            The callback that will be run
     */
    public void setOnCompletionListener(OnCompletionListener l) {
        mOnCompletionListener = l;
    }

    /**
     * Register a callback to be invoked when an error occurs during playback or
     * setup. If no listener is specified, or if the listener returned false,
     * VideoView will inform the user of any errors.
     * 
     * @param l
     *            The callback that will be run
     */
    public void setOnErrorListener(OnErrorListener l) {
        mOnErrorListener = l;
    }

    SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback() {
        public void surfaceChanged(SurfaceHolder holder, int format, int w,
                int h) {
            mSurfaceWidth = w;
            mSurfaceHeight = h;
            if (mMediaPlayer != null && mIsPrepared && mVideoWidth == w
                    && mVideoHeight == h) {
                if (mSeekWhenPrepared != 0) {
                    mMediaPlayer.seekTo(mSeekWhenPrepared);
                    mSeekWhenPrepared = 0;
                }
                mMediaPlayer.start();
                if (mMediaController != null) {
                    mMediaController.show();
                }
            }
        }

        public void surfaceCreated(SurfaceHolder holder) {
            mSurfaceHolder = holder;
            openVideo();
        }

        public void surfaceDestroyed(SurfaceHolder holder) {
            // after we return from this we can't use the surface any more
            mSurfaceHolder = null;
            if (mMediaController != null)
                mMediaController.hide();
            if (mMediaPlayer != null) {
                mMediaPlayer.reset();
                mMediaPlayer.release();
                mMediaPlayer = null;
            }
        }
    };

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (mIsPrepared && mMediaPlayer != null && mMediaController != null) {
            toggleMediaControlsVisiblity();
        }
        return false;
    }

    @Override
    public boolean onTrackballEvent(MotionEvent ev) {
        if (mIsPrepared && mMediaPlayer != null && mMediaController != null) {
            toggleMediaControlsVisiblity();
        }
        return false;
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        System.out.println("this is videoview keyevent");

        if (mIsPrepared && keyCode != KeyEvent.KEYCODE_BACK
                && keyCode != KeyEvent.KEYCODE_VOLUME_UP
                && keyCode != KeyEvent.KEYCODE_VOLUME_DOWN
                && keyCode != KeyEvent.KEYCODE_MENU
                && keyCode != KeyEvent.KEYCODE_CALL
                && keyCode != KeyEvent.KEYCODE_ENDCALL && mMediaPlayer != null
                && mMediaController != null) {
            if (keyCode == KeyEvent.KEYCODE_HEADSETHOOK
                    || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE
                    || keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
                if (mMediaPlayer.isPlaying()) {
                    pause();
                    mMediaController.show();
                } else {
                    start();
                    mMediaController.hide();
                }
                return true;
            } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP
                    && mMediaPlayer.isPlaying()) {
                pause();
                mMediaController.show();
            } else {
                toggleMediaControlsVisiblity();
            }
        }

        return false;
    }

    private void toggleMediaControlsVisiblity() {
        // if (mMediaController.isShowing()) {
        // mMediaController.hide();
        // } else {
        mMediaController.show();
        if (mMediaController.isShowing() && mMediaPlayer.isPlaying()) {
            pause();
        } else {
            start();
        }
        // }
    }

    public void start() {
        if (mMediaPlayer != null && mIsPrepared) {
            mMediaPlayer.start();
            mStartWhenPrepared = false;
        } else {
            mStartWhenPrepared = true;
        }
    }

    public void pause() {
        if (mMediaPlayer != null && mIsPrepared) {
            if (mMediaPlayer.isPlaying()) {
                mMediaPlayer.pause();
            }
        }
        mStartWhenPrepared = false;
    }

    public long getDuration() {
        if (mMediaPlayer != null && mIsPrepared) {
            if (mDuration > 0) {
                return mDuration;
            }
            mDuration = mMediaPlayer.getDuration();
            return mDuration;
        }
        mDuration = -1;
        return mDuration;
    }

    public long getCurrentPosition() {
        if (mMediaPlayer != null && mIsPrepared) {
            return mMediaPlayer.getCurrentPosition();
        }
        return 0;
    }

    public void seekTo(int msec) {
        if (mMediaPlayer != null && mIsPrepared) {
            mMediaPlayer.seekTo(msec);
        } else {
            mSeekWhenPrepared = msec;
        }
    }

    public boolean isPlaying() {
        if (mMediaPlayer != null && mIsPrepared) {
            return mMediaPlayer.isPlaying();
        }
        return false;
    }

    public int getBufferPercentage() {
        if (mMediaPlayer != null) {
            return mCurrentBufferPercentage;
        }
        return 0;
    }

    public final static int A_DEFALT = 0; // 原始比例
    public final static int A_4X3 = 1;
    public final static int A_16X9 = 2;
    public final static int A_RAW = 4; // 原始大小

    /**
     * 全屏状态才可以使用选择比例
     * 
     * @param flg
     */
    public void selectScales(int flg) {
        if (getWindowToken() != null) {
            Rect rect = new Rect();
            getWindowVisibleDisplayFrame(rect);

            double height = rect.bottom - rect.top;
            double width = rect.right - rect.left;

            if (height <= 0.0 || width <= 0.0 || mVideoHeight <= 0.0
                    || mVideoWidth <= 0.0) {
                return;
            }
            ViewGroup.LayoutParams param = getLayoutParams();

            switch (flg) {
            case A_DEFALT:
                if (width / height >= mVideoWidth / mVideoHeight) { //
                    // 屏幕 宽了以屏幕高为基础
                    param.height = (int) height;
                    param.width = (int) (mVideoWidth * height / mVideoHeight);
                } else { // 屏幕 高了 以宽为基础
                    param.width = (int) width;
                    param.height = (int) (mVideoHeight * width / mVideoWidth);
                }
                setLayoutParams(param);
                break;

            case A_4X3:
                if (width / height >= 4.0 / 3.0) {
                    // 屏幕 宽了 以屏幕高为基础
                    param.height = (int) height;
                    param.width = (int) (4 * height / 3);
                } else { // 屏幕 高了 以宽为基础
                    param.width = (int) width;
                    param.height = (int) (3 * width / 4);
                }
                setLayoutParams(param);
                break;
            case A_16X9:
                if (width / height >= 16.0 / 9.0) {
                    // 屏幕 宽了 以屏幕高为基础
                    param.height = (int) height;
                    param.width = (int) (16 * height / 9);
                } else { // 屏幕 高了 以宽为基础
                    param.width = (int) width;
                    param.height = (int) (9 * width / 16);
                }
                setLayoutParams(param);
                break;
            }

        }

    }

    @Override
    public boolean canPause() {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean canSeekBackward() {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean canSeekForward() {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public void seekTo(long pos) {
        if (mMediaPlayer != null && mIsPrepared) {
            mMediaPlayer.seekTo((int) pos);
        } else {
            mSeekWhenPrepared = (int) pos;
        }
    }

    @Override
    public void onClick(View v) {
        System.out.println("this is pause");

    }

}

 然后:

自定义的VideoView:

 ,最后才是主要类“基本上完全了,想要更深,自己DIY即可:

package com.example.revideoview;

import java.io.File;

import com.android.widget.CustomProgressDialog;
import com.android.widget.VodCtrTop;
import com.android.widget.MediaController;
import com.android.widget.StringTools;
import com.android.widget.VideoView;

import android.app.Activity;
import android.content.Context;
import android.graphics.PixelFormat;
import android.graphics.drawable.BitmapDrawable;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.MessageQueue.IdleHandler;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.TextView;
import android.widget.RelativeLayout.LayoutParams;

/**
 * 
 * @author Catherine
 * */

public class MainActivity extends Activity {
    VideoView videoView;

    MediaController mMediaController;

    public static MainActivity instance;
    String title;
    String numText;

    int resourceId;
    String path;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        instance = this;
        path = Environment.getExternalStorageDirectory()
                + "/c234b_08_hd_h264_1280_720.mp4";
        System.out.println("the path is===>" + path);
        File file = new File(path);
        if (file.exists()) {

            // tvTitle = (TextView) findViewById(R.id.title);

            videoView = (VideoView) findViewById(R.id.myVideoView);
            videoView.setOnCompletionListener(new OnCompletionListener() {

                @Override
                public void onCompletion(MediaPlayer arg0) {
                    finish();
                }
            });
            resourceId = R.drawable.ic_launcher;
            setDataSource(path);

            initControlView();
            initOperatHintPop();

            setMediaPlayer();

            Looper.myQueue().addIdleHandler(new IdleHandler() {

                @Override
                public boolean queueIdle() {
                    if (ctrTop != null && videoView.isPlaying()) {
                        showCtrTop();
                    }
                    return false;
                }
            });
        } else {
            System.out.println("文件不存在");
        }

    }

    int btn_judge = 0;

    private void showCtrTop() {
        ctrTop.showAtLocation(videoView, Gravity.TOP, 0, 0);
        ctrTop.setSourceTag(resourceId);

        if (StringTools.isNullOrEmpty(numText)) {
            ctrTop.setVideoName(title);
        } else {
            ctrTop.setVideoName(title + "(" + numText + ")");
        }
    }

    VodCtrTop ctrTop;
    // VodCtrBot ctrBot;

    private PopupWindow hintPop;
    private ImageView hintPopImg;

    private void initControlView() {

        // ctrBot = new VodCtrBot(this, videoView, new Handler() {

        // });

        ctrTop = new VodCtrTop(this, new Handler() {
            @Override
            public void handleMessage(Message msg) {

                super.handleMessage(msg);
            }

        });

    }

    private void initOperatHintPop() {
        hintPop = new PopupWindow();
        hintPopImg = new ImageView(this);
        hintPop.setWindowLayoutMode(
                android.view.ViewGroup.LayoutParams.MATCH_PARENT,
                android.view.ViewGroup.LayoutParams.WRAP_CONTENT);
        hintPop.setBackgroundDrawable(new BitmapDrawable());
        WindowManager.LayoutParams localLayoutParams = new WindowManager.LayoutParams(
                android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
                android.view.ViewGroup.LayoutParams.WRAP_CONTENT);
        this.hintPopImg.setLayoutParams(localLayoutParams);
        this.hintPop.setContentView(this.hintPopImg);
    }

    private void setMediaPlayer() {
        // 全屏之后设置进度条

        mMediaController = new MediaController(this);
        videoView.setMediaController(mMediaController);
        mMediaController.show();
    }

    @Override
    protected void onResume() {
        // setDataSource(url, title);
        super.onResume();

        // getCookies();
    }

    public WindowManager windowManager;
    private Handler handler;
    private OverlayThread overlayThread;

    private LinearLayout overlay_ll;
    public TextView overlay;


    private Handler mHandler = new Handler() {

        public void handleMessage(Message msg) {
            if (msg.what == 0) {

            }
        };
    };

    public void initOverlay() {
        handler = new Handler();
        overlayThread = new OverlayThread();
        final LayoutInflater inflater = LayoutInflater.from(instance);
        overlay_ll = (LinearLayout) inflater.inflate(R.layout.overlay, null);
        overlay = (TextView) overlay_ll.findViewById(R.id.tv_center);

        final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_APPLICATION,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                        | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
                PixelFormat.TRANSLUCENT);
        windowManager = (WindowManager) instance
                .getSystemService(Context.WINDOW_SERVICE);
        windowManager.addView(overlay_ll, lp);
        // windowManager.addView(overlay_bottom, lp);
    }

    /**
     * 设置overlay不可见
     * 
     * 
     */
    class OverlayThread implements Runnable {

        @Override
        public void run() {
            overlay_ll.setVisibility(View.GONE);
        }
    }


    public void setDataSource(String url) {

        playVideo(url);

    }

    /**
     * 获取屏幕的宽和高
     */
    private void getScreenSize() {
        DisplayMetrics dm = new DisplayMetrics();
        this.getWindowManager().getDefaultDisplay().getMetrics(dm);
        // VitaVideoView.mVideoWidth = dm.widthPixels;
        // VitaVideoView.mVideoHeight = dm.heightPixels;
    }

    public void playVideo(String url) {

        Message msg = new Message();
        msg.what = 0;
        // 发送一个隐藏的消息
        mHandler.sendMessageDelayed(msg, 5 * 1000);

        videoView.setVideoPath(url);

        // 展示一个进度
        final CustomProgressDialog dialog = new CustomProgressDialog(instance);
        if (!dialog.isShowing()) {
            dialog.show();
        }

        videoView.setOnPreparedListener(new OnPreparedListener() {

            @Override
            public void onPrepared(MediaPlayer mp) {

                // 取消进度
                if (null != dialog) {
                    dialog.cancel();
                }
                // setMediaPlayer();
                videoView.start();
            }
        });

        videoView.requestFocus();
    }

    int playNum = 0;
    int titleNum = 0;

    //

    protected void exitApp() {
        UserDialogRunnable userRun = new UserDialogRunnable();
        new Handler().postDelayed(userRun, 300L);
    }

    class UserDialogRunnable implements Runnable {

        @Override
        public void run() {
            finish();
            overridePendingTransition(R.anim.hyperspace_in,
                    R.anim.hyperspace_out);
            // android.os.Process.killProcess(android.os.Process.myPid());
        }

    }

    public boolean onKeyDown(int keyCode, KeyEvent event) {
        System.out.println("this is mainactivity onKeyDown");
        switch (keyCode) {
        case KeyEvent.KEYCODE_DPAD_CENTER:
            System.out.println("this is mainactivity keyevent");
            // mMediaController.show();
            if (videoView.isPlaying()) {
                // 暂停
                videoView.pause();
                // 展示暂停
                hintPopImg.setImageResource(R.drawable.osd_pause);
                hintPop.showAtLocation(videoView, 17, 0, 0);
            } else {
                hintPop.dismiss();
                videoView.start();
            }

            break;
        case KeyEvent.KEYCODE_DPAD_LEFT:
            // mMediaController.show();
            showCtrTop();
            // ctrBot.show();
            // if (event.getRepeatCount() == 0 && event.getEventTime() > 2 *
            // 1000) {
            // videoBack();
            // }
            return false;
        case KeyEvent.KEYCODE_DPAD_RIGHT:
            mMediaController.show();
            showCtrTop();
            return false;
        case KeyEvent.KEYCODE_BACK:
            finish();
            // return true;
        case KeyEvent.KEYCODE_MENU:

            return true;
        }

        return false;
    };

    public boolean onTouchEvent(android.view.MotionEvent event) {
        return false;
    };

    Handler menuHandler = new Handler();

    int addOrbackNum = 30 * 1000;

    // private void videoBack() {
    // long pos = videoView.getCurrentPosition();
    // pos -= addOrbackNum;
    // videoView.seekTo(pos);
    // }
    //
    // private void videoAdd() {
    // long pos = videoView.getCurrentPosition();
    // pos += addOrbackNum;
    // videoView.seekTo(pos);
    // }

    public void changeScales(int whatMode) {
        videoView.selectScales(whatMode);

    }

    OnErrorListener errorListener = new OnErrorListener() {

        @Override
        public boolean onError(MediaPlayer mp, int what, int extra) {

            return true;
        }
    };

    protected void onDestroy() {
        if (ctrTop != null) {
            ctrTop.dismiss();
        }
        if (hintPop != null) {
            hintPop.dismiss();
        }
        super.onDestroy();
    };
}

具体源码,可以看我的文件里面的“自定义Videoview.jar”

里面也有继承TextView,以及Toast以及Processbar。。。。可参考

当然,这个给出一个灵感链接:http://blog.sina.com.cn/s/blog_640b806d0100q2wo.html#commonComment

原文地址:https://www.cnblogs.com/Catherine-Brain/p/4089748.html