Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * 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 io.vov.vitamio.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 io.vov.vitamio.utils.Log;
- import io.vov.vitamio.utils.StringUtils;
- /**
- * A view containing controls for a MediaPlayer. Typically contains the buttons
- * like "Play/Pause" and a progress slider. It takes care of synchronizing the
- * controls with the state of the MediaPlayer.
- * <p/>
- * The way to use this class is to a) instantiate it programatically or b)
- * create it in your xml layout.
- * <p/>
- * a) The MediaController will create a default set of controls and put them in
- * a window floating above your application. Specifically, the controls will
- * float above the view specified with setAnchorView(). By default, the window
- * will disappear if left idle for three seconds and reappear when the user
- * touches the anchor view. To customize the MediaController's style, layout and
- * controls you should extend MediaController and override the {#link
- * {@link #makeControllerView()} method.
- * <p/>
- * b) The MediaController is a FrameLayout, you can put it in your layout xml
- * and get it through {@link #findViewById(int)}.
- * <p/>
- * NOTES: In each way, if you want customize the MediaController, the SeekBar's
- * id must be mediacontroller_progress, the Play/Pause's must be
- * mediacontroller_pause, current time's must be mediacontroller_time_current,
- * total time's must be mediacontroller_time_total, file name's must be
- * mediacontroller_file_name. And your resources must have a pause_button
- * drawable and a play_button drawable.
- * <p/>
- * Functions like show() and hide() have no effect when MediaController is
- * created in an xml layout.
- */
- 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 = false;
- 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) {
- 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 = StringUtils.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(getResources().getIdentifier("mediacontroller", "layout", mContext.getPackageName()), this);
- }
- private void initControllerView(View v) {
- mPauseButton = (ImageButton) v.findViewById(getResources().getIdentifier("mediacontroller_play_pause", "id", mContext.getPackageName()));
- if (mPauseButton != null) {
- mPauseButton.requestFocus();
- mPauseButton.setOnClickListener(mPauseListener);
- }
- mProgress = (SeekBar) v.findViewById(getResources().getIdentifier("mediacontroller_seekbar", "id", mContext.getPackageName()));
- if (mProgress != null) {
- if (mProgress instanceof SeekBar) {
- SeekBar seeker = (SeekBar) mProgress;
- seeker.setOnSeekBarChangeListener(mSeekListener);
- }
- mProgress.setMax(1000);
- }
- mEndTime = (TextView) v.findViewById(getResources().getIdentifier("mediacontroller_time_total", "id", mContext.getPackageName()));
- mCurrentTime = (TextView) v.findViewById(getResources().getIdentifier("mediacontroller_time_current", "id", mContext.getPackageName()));
- mFileName = (TextView) v.findViewById(getResources().getIdentifier("mediacontroller_file_name", "id", mContext.getPackageName()));
- 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;
- }
- /**
- * <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();
- 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(StringUtils.generateTime(mDuration));
- if (mCurrentTime != null)
- mCurrentTime.setText(StringUtils.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) {
- 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(getResources().getIdentifier("mediacontroller_pause", "drawable", mContext.getPackageName()));
- else
- mPauseButton.setImageResource(getResources().getIdentifier("mediacontroller_play", "drawable", mContext.getPackageName()));
- }
- 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);
- 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();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement