Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chapter dividers for the progress bar #4915

Merged
merged 9 commits into from
Mar 1, 2021
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.core.event.FavoritesEvent;
import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
import de.danoeh.antennapod.core.feed.Chapter;
import de.danoeh.antennapod.core.event.UnreadItemsUpdateEvent;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
Expand All @@ -46,6 +47,7 @@
import de.danoeh.antennapod.dialog.SleepTimerDialog;
import de.danoeh.antennapod.dialog.VariableSpeedDialog;
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
import de.danoeh.antennapod.view.ChapterSeekBar;
import de.danoeh.antennapod.ui.common.PlaybackSpeedIndicatorView;
import io.reactivex.Maybe;
import io.reactivex.android.schedulers.AndroidSchedulers;
Expand All @@ -63,7 +65,7 @@
* Shows the audio player.
*/
public class AudioPlayerFragment extends Fragment implements
SeekBar.OnSeekBarChangeListener, Toolbar.OnMenuItemClickListener {
ChapterSeekBar.OnSeekBarChangeListener, Toolbar.OnMenuItemClickListener {
public static final String TAG = "AudioPlayerFragment";
private static final int POS_COVER = 0;
private static final int POS_DESCR = 1;
Expand All @@ -77,7 +79,7 @@ public class AudioPlayerFragment extends Fragment implements
private ViewPager2 pager;
private TextView txtvPosition;
private TextView txtvLength;
private SeekBar sbPosition;
private ChapterSeekBar sbPosition;
private ImageButton butRev;
private TextView txtvRev;
private ImageButton butPlay;
Expand Down Expand Up @@ -172,12 +174,33 @@ public void onPageSelected(int position) {
return root;
}

public void setHasChapters(boolean hasChapters) {
private void setHasChapters(boolean hasChapters) {
this.hasChapters = hasChapters;
tabLayoutMediator.detach();
tabLayoutMediator.attach();
}

private void setChapterDividers(Playable media) {

if (media == null) {
return;
}

float[] dividerPos = null;

if (hasChapters) {
List<Chapter> chapters = media.getChapters();
dividerPos = new float[chapters.size()];
float duration = media.getDuration();

for (int i = 0; i < chapters.size(); i++) {
dividerPos[i] = chapters.get(i).getStart() / duration;
}
}

sbPosition.setDividerPos(dividerPos);
}

public View getExternalPlayerHolder() {
return getView().findViewById(R.id.playerFragment);
}
Expand Down Expand Up @@ -298,16 +321,17 @@ private void loadMediaInfo() {
disposable = Maybe.create(emitter -> {
Playable media = controller.getMedia();
if (media != null) {
media.loadChapterMarks(getContext());
emitter.onSuccess(media);
} else {
emitter.onComplete();
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(media -> updateUi((Playable) media),
error -> Log.e(TAG, Log.getStackTraceString(error)),
() -> updateUi(null));
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(media -> updateUi((Playable) media),
error -> Log.e(TAG, Log.getStackTraceString(error)),
() -> updateUi(null));
}

private PlaybackController newPlaybackController() {
Expand Down Expand Up @@ -389,8 +413,15 @@ private void updateUi(Playable media) {
if (controller == null) {
return;
}

if (media != null && media.getChapters() != null) {
setHasChapters(media.getChapters().size() > 0);
} else {
setHasChapters(false);
}
updatePosition(new PlaybackPositionEvent(controller.getPosition(), controller.getDuration()));
updatePlaybackSpeedButton(media);
setChapterDividers(media);
setupOptionsMenu(media);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,6 @@ private void onMediaChanged(Playable media) {
return;
}
adapter.setMedia(media);
((AudioPlayerFragment) getParentFragment()).setHasChapters(adapter.getItemCount() > 0);
int positionOfCurrentChapter = getCurrentChapter(media);
updateChapterSelection(positionOfCurrentChapter);
}
Expand Down
129 changes: 129 additions & 0 deletions app/src/main/java/de/danoeh/antennapod/view/ChapterSeekBar.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package de.danoeh.antennapod.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import de.danoeh.antennapod.ui.common.ThemeUtils;

public class ChapterSeekBar extends androidx.appcompat.widget.AppCompatSeekBar {

private float top;
private float width;
private float bottom;
private float density;
private float progressPrimary;
private float progressSecondary;
private float[] dividerPos;
private final Paint paintBackground = new Paint();
private final Paint paintProgressPrimary = new Paint();
private final Paint paintProgressSecondary = new Paint();

public ChapterSeekBar(Context context) {
super(context);
init(context);
}

public ChapterSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}

public ChapterSeekBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}

private void init(Context context) {
setBackground(null); // Removes the thumb shadow
dividerPos = null;
density = context.getResources().getDisplayMetrics().density;
paintBackground.setColor(ThemeUtils.getColorFromAttr(getContext(),
de.danoeh.antennapod.core.R.attr.currently_playing_background));
paintBackground.setAlpha(128);
paintProgressPrimary.setColor(ThemeUtils.getColorFromAttr(getContext(),
de.danoeh.antennapod.core.R.attr.colorPrimary));
paintProgressSecondary.setColor(ThemeUtils.getColorFromAttr(getContext(),
de.danoeh.antennapod.core.R.attr.seek_background));
}

/**
* Sets the relative positions of the chapter dividers.
* @param dividerPos of the chapter dividers relative to the duration of the media.
*/
public void setDividerPos(final float[] dividerPos) {
if (dividerPos != null) {
this.dividerPos = new float[dividerPos.length + 2];
this.dividerPos[0] = 0;
System.arraycopy(dividerPos, 0, this.dividerPos, 1, dividerPos.length);
this.dividerPos[this.dividerPos.length - 1] = 1;
} else {
this.dividerPos = null;
}
}

@Override
protected synchronized void onDraw(Canvas canvas) {
top = getTop() + density * 7.5f;
bottom = getBottom() - density * 7.5f;
width = (float) (getRight() - getPaddingRight() - getLeft() - getPaddingLeft());
progressSecondary = getSecondaryProgress() / (float) getMax() * width;
progressPrimary = getProgress() / (float) getMax() * width;

if (dividerPos == null) {
drawProgress(canvas);
} else {
drawProgressChapters(canvas);
}
drawThumb(canvas);
}

private void drawProgress(Canvas canvas) {
final int saveCount = canvas.save();
canvas.translate(getPaddingLeft(), getPaddingTop());
canvas.drawRect(0, top, width, bottom, paintBackground);
canvas.drawRect(0, top, progressSecondary, bottom, paintProgressSecondary);
canvas.drawRect(0, top, progressPrimary, bottom, paintProgressPrimary);
canvas.restoreToCount(saveCount);
}

private void drawProgressChapters(Canvas canvas) {
final int saveCount = canvas.save();
int currChapter = 1;
float chapterMargin = density * 0.6f;
float topExpanded = getTop() + density * 7;
float bottomExpanded = getBottom() - density * 7;

canvas.translate(getPaddingLeft(), getPaddingTop());

for (int i = 1; i < dividerPos.length; i++) {
float right = dividerPos[i] * width - chapterMargin;
float left = dividerPos[i - 1] * width + chapterMargin;
float rightCurr = dividerPos[currChapter] * width - chapterMargin;
float leftCurr = dividerPos[currChapter - 1] * width + chapterMargin;

canvas.drawRect(left, top, right, bottom, paintBackground);

if (right < progressPrimary) {
currChapter = i + 1;
canvas.drawRect(left, top, right, bottom, paintProgressPrimary);
} else if (isPressed()) {
canvas.drawRect(leftCurr, topExpanded, rightCurr, bottomExpanded, paintBackground);
canvas.drawRect(leftCurr, topExpanded, progressPrimary, bottomExpanded, paintProgressPrimary);
} else {
if (progressSecondary > leftCurr) {
canvas.drawRect(leftCurr, top, progressSecondary, bottom, paintProgressSecondary);
}
canvas.drawRect(leftCurr, top, progressPrimary, bottom, paintProgressPrimary);
}
}
canvas.restoreToCount(saveCount);
}

private void drawThumb(Canvas canvas) {
final int saveCount = canvas.save();
canvas.translate(getPaddingLeft() - getThumbOffset(), getPaddingTop());
getThumb().draw(canvas);
canvas.restoreToCount(saveCount);
}
}
2 changes: 1 addition & 1 deletion app/src/main/res/layout/audioplayer_fragment.xml
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
android:layoutDirection="ltr"
android:orientation="vertical">

<SeekBar
<de.danoeh.antennapod.view.ChapterSeekBar
android:id="@+id/sbPosition"
android:layout_width="match_parent"
android:layout_height="wrap_content"
Expand Down