Download File
Download Project
Settings
Line Wrap
Themes
default
ambiance
bespin
dracula
eclipse
material
mbo
mdn-like
neat
solarized dark
ttcn
zenburn
MediaSeekBar.java
/* * Copyright 2017 The Android Open Source Project * * 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.example.android.mediasession.ui; import android.animation.ValueAnimator; import android.content.Context; import android.support.v4.media.MediaMetadataCompat; import android.support.v4.media.session.MediaControllerCompat; import android.support.v4.media.session.MediaSessionCompat; import android.support.v4.media.session.PlaybackStateCompat; import android.support.v7.widget.AppCompatSeekBar; import android.util.AttributeSet; import android.view.animation.LinearInterpolator; import android.widget.SeekBar; /** * SeekBar that can be used with a {@link MediaSessionCompat} to track and seek in playing * media. */ public class MediaSeekBar extends AppCompatSeekBar { private MediaControllerCompat mMediaController; private ControllerCallback mControllerCallback; private boolean mIsTracking = false; private OnSeekBarChangeListener mOnSeekBarChangeListener = new OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } @Override public void onStartTrackingTouch(SeekBar seekBar) { mIsTracking = true; } @Override public void onStopTrackingTouch(SeekBar seekBar) { mMediaController.getTransportControls().seekTo(getProgress()); mIsTracking = false; } }; private ValueAnimator mProgressAnimator; public MediaSeekBar(Context context) { super(context); super.setOnSeekBarChangeListener(mOnSeekBarChangeListener); } public MediaSeekBar(Context context, AttributeSet attrs) { super(context, attrs); super.setOnSeekBarChangeListener(mOnSeekBarChangeListener); } public MediaSeekBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); super.setOnSeekBarChangeListener(mOnSeekBarChangeListener); } @Override public void setOnSeekBarChangeListener(OnSeekBarChangeListener l) { // Prohibit adding seek listeners to this subclass. } public void setMediaController(final MediaControllerCompat mediaController) { if (mediaController != null) { mControllerCallback = new ControllerCallback(); mediaController.registerCallback(mControllerCallback); } else if (mMediaController != null) { mMediaController.unregisterCallback(mControllerCallback); mControllerCallback = null; } mMediaController = mediaController; } public void disconnectController() { if (mMediaController != null) { mMediaController.unregisterCallback(mControllerCallback); mControllerCallback = null; mMediaController = null; } } private class ControllerCallback extends MediaControllerCompat.Callback implements ValueAnimator.AnimatorUpdateListener { @Override public void onSessionDestroyed() { super.onSessionDestroyed(); } @Override public void onPlaybackStateChanged(PlaybackStateCompat state) { super.onPlaybackStateChanged(state); // If there's an ongoing animation, stop it now. if (mProgressAnimator != null) { mProgressAnimator.cancel(); mProgressAnimator = null; } final int progress = state != null ? (int) state.getPosition() : 0; setProgress(progress); // If the media is playing then the seekbar should follow it, and the easiest // way to do that is to create a ValueAnimator to update it so the bar reaches // the end of the media the same time as playback gets there (or close enough). if (state != null && state.getState() == PlaybackStateCompat.STATE_PLAYING) { final int timeToEnd = (int) ((getMax() - progress) / state.getPlaybackSpeed()); mProgressAnimator = ValueAnimator.ofInt(progress, getMax()) .setDuration(timeToEnd); mProgressAnimator.setInterpolator(new LinearInterpolator()); mProgressAnimator.addUpdateListener(this); mProgressAnimator.start(); } } @Override public void onMetadataChanged(MediaMetadataCompat metadata) { super.onMetadataChanged(metadata); final int max = metadata != null ? (int) metadata.getLong(MediaMetadataCompat.METADATA_KEY_DURATION) : 0; setProgress(0); setMax(max); } @Override public void onAnimationUpdate(final ValueAnimator valueAnimator) { // If the user is changing the slider, cancel the animation. if (mIsTracking) { valueAnimator.cancel(); return; } final int animatedIntValue = (int) valueAnimator.getAnimatedValue(); setProgress(animatedIntValue); } } }