package com.linroid.sky31radio.view;
/**
* Created by linroid on 1/14/15.
*/
import android.content.Context;
import android.util.AttributeSet;
import android.widget.FrameLayout;
import android.widget.ProgressBar;
import com.linroid.sky31radio.R;
import com.linroid.sky31radio.utils.RadioUtils;
/**
* This class handles the playpause button as well as the circular progress bar
* it self-updates the progress bar but the containing activity/fragment
* needs to add code to pause/resume this button to prevent unnecessary
* updates while the activity/fragment is not visible
*/
public class PlayPauseProgressButton extends FrameLayout {
private static final long UPDATE_FREQUENCY_MS = 500;
private ProgressBar mProgressBar;
private PlayPauseButton mPlayPauseButton;
private Runnable mUpdateProgress;
private boolean mPaused;
public PlayPauseProgressButton(Context context, AttributeSet attrs) {
super(context, attrs);
// set enabled to false as default so that calling enableAndShow will execute
setEnabled(false);
// set paused to false since we shouldn't be typically created while not visible
mPaused = false;
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mPlayPauseButton = (PlayPauseButton)findViewById(R.id.action_button_play);
mProgressBar = (ProgressBar)findViewById(R.id.circularProgressBar);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// Make the play pause button size dependent on the container size
int horizontalPadding = getMeasuredWidth() / 4;
int verticalPadding = getMeasuredHeight() / 4;
mPlayPauseButton.setPadding(
horizontalPadding, horizontalPadding,
verticalPadding, verticalPadding);
// rotate the progress bar 90 degrees counter clockwise so that the
// starting position is at the top
mProgressBar.setPivotX(mProgressBar.getMeasuredWidth() / 2);
mProgressBar.setPivotY(mProgressBar.getMeasuredHeight() / 2);
mProgressBar.setRotation(-90);
}
/**
* Enable and shows the container
*/
public void enableAndShow() {
// enable
setEnabled(true);
// make our view visible
setVisibility(VISIBLE);
}
/**
* Disables and sets the visibility to gone for the container
*/
public void disableAndHide() {
// disable
setEnabled(false);
// hide our view
setVisibility(GONE);
}
@Override
public void setEnabled(boolean enabled) {
// if the enabled state isn't changed, quit
if (enabled == isEnabled()) return;
super.setEnabled(enabled);
// signal our state has changed
onStateChanged();
}
/**
* Pauses the progress bar periodic update logic
*/
public void pause() {
if (!mPaused) {
mPaused = true;
// signal our state has changed
onStateChanged();
}
}
/**
* Resumes the progress bar periodic update logic
*/
public void resume() {
if (mPaused) {
mPaused = false;
// signal our state has changed
onStateChanged();
}
}
/**
* @return play pause button
*/
public PlayPauseButton getPlayPauseButton() {
return mPlayPauseButton;
}
/**
* Signaled if the state has changed (either the enabled or paused flag)
* When the state changes, we either kick off the updates or remove them based on those flags
*/
private void onStateChanged() {
// if we are enabled and not paused
if (isEnabled() && !mPaused) {
// update the state of the progress bar and play/pause button
updateState();
// kick off update states
postUpdate();
} else {
// otherwise remove our update
removeUpdate();
}
}
/**
* Updates the state of the progress bar and the play pause button
*/
private void updateState() {
final long duration = RadioUtils.duration();
if (duration > 0) {
final long pos = RadioUtils.position();
int progress = (int) (mProgressBar.getMax() * pos / duration);
mProgressBar.setProgress(progress);
} else {
// this is when there are no tracks loaded or some kind of error condition
mProgressBar.setProgress(0);
}
mPlayPauseButton.updateState();
}
/**
* Creates and posts the update runnable to the handler
*/
private void postUpdate() {
if (mUpdateProgress == null) {
mUpdateProgress = new Runnable() {
@Override
public void run() {
updateState();
postDelayed(mUpdateProgress, UPDATE_FREQUENCY_MS);
}
};
}
// remove any existing callbacks
removeCallbacks(mUpdateProgress);
// post ourselves as a delayed
postDelayed(mUpdateProgress, UPDATE_FREQUENCY_MS);
}
/**
* Removes the runnable from the handler
*/
private void removeUpdate() {
if (mUpdateProgress != null) {
removeCallbacks(mUpdateProgress);
}
}
}