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 @@ -31,6 +31,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.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.util.PlaybackSpeedUtils;
Expand All @@ -47,6 +48,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.view.PlaybackSpeedIndicatorView;
import io.reactivex.Maybe;
import io.reactivex.android.schedulers.AndroidSchedulers;
Expand All @@ -64,7 +66,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 @@ -79,7 +81,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 @@ -178,6 +180,31 @@ public void setHasChapters(boolean hasChapters) {
this.hasChapters = hasChapters;
tabLayoutMediator.detach();
tabLayoutMediator.attach();
if (controller != null) {
setChapterDividers(controller.getMedia());
}
}

public void setChapterDividers(Playable media) {

if (media == null) {
return;
}

List<Chapter> chapters;
float[] dividerPos = null;

if ((chapters = media.getChapters()) != null && chapters.size() > 0) {
ByteHamster marked this conversation as resolved.
Show resolved Hide resolved
dividerPos = new float[chapters.size() - 1];
float duration = media.getDuration();

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

sbPosition.setDividerPos(dividerPos);
sbPosition.invalidate();
jonasburian marked this conversation as resolved.
Show resolved Hide resolved
}

public View getExternalPlayerHolder() {
Expand Down
85 changes: 85 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,85 @@
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.core.util.ThemeUtils;

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

private float[] dividerPos;
private final Paint dividerPaint = new Paint();

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

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

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

private void init() {
setBackground(null); // Removes the thumb shadow
dividerPos = null;
dividerPaint.setColor(ThemeUtils.getColorFromAttr(getContext(), android.R.attr.windowBackground));
}

/**
* Calculates the positions of the chapter dividers in the progress bar.
* @param dividerPos of the chapter dividers relative to the duration of the media.
*/
public void setDividerPos(final float[] dividerPos) {
if (dividerPos != null && dividerPos.length > 0) {
jonasburian marked this conversation as resolved.
Show resolved Hide resolved
float width = (float) (getRight() - getPaddingRight() - getLeft() - getPaddingLeft());
this.dividerPos = new float[dividerPos.length];

for (int i = 0; i < dividerPos.length; i++) {
this.dividerPos[i] = dividerPos[i] * width;
}

} else {
this.dividerPos = null;
}
}

@Override
protected synchronized void onDraw(Canvas canvas) {
drawProgress(canvas);
if (dividerPos != null) {
drawDividers(canvas);
}
drawThumb(canvas);
}

private void drawProgress(Canvas canvas) {
final int saveCount = canvas.save();
canvas.translate(getPaddingLeft(), getPaddingTop());
getProgressDrawable().draw(canvas);
canvas.restoreToCount(saveCount);
}

private void drawDividers(Canvas canvas) {
final int saveCount = canvas.save();
canvas.translate(getPaddingLeft(), getPaddingTop());
for (float pos : dividerPos) {
canvas.drawRect(pos - 5, getTop(), pos + 5, getBottom(), dividerPaint);
jonasburian marked this conversation as resolved.
Show resolved Hide resolved
}
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
3 changes: 3 additions & 0 deletions core/src/main/res/values/attrs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,7 @@
<enum name="minimum" value="2"/>
</attr>
</declare-styleable>

<declare-styleable name="ChapterSeekBar" />
jonasburian marked this conversation as resolved.
Show resolved Hide resolved

</resources>