Added textual tab indicator to player screen (#4731)
This commit is contained in:
parent
f3c76e7677
commit
7c93bc5140
|
@ -22,6 +22,8 @@ import androidx.viewpager2.adapter.FragmentStateAdapter;
|
|||
import androidx.viewpager2.widget.ViewPager2;
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import com.google.android.material.tabs.TabLayoutMediator;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.activity.CastEnabledActivity;
|
||||
import de.danoeh.antennapod.activity.MainActivity;
|
||||
|
@ -43,7 +45,6 @@ import de.danoeh.antennapod.dialog.SkipPreferenceDialog;
|
|||
import de.danoeh.antennapod.dialog.SleepTimerDialog;
|
||||
import de.danoeh.antennapod.dialog.VariableSpeedDialog;
|
||||
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
|
||||
import de.danoeh.antennapod.view.PagerIndicatorView;
|
||||
import de.danoeh.antennapod.view.PlaybackSpeedIndicatorView;
|
||||
import io.reactivex.Maybe;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
|
@ -74,7 +75,6 @@ public class AudioPlayerFragment extends Fragment implements
|
|||
PlaybackSpeedIndicatorView butPlaybackSpeed;
|
||||
TextView txtvPlaybackSpeed;
|
||||
private ViewPager2 pager;
|
||||
private PagerIndicatorView pageIndicator;
|
||||
private TextView txtvPosition;
|
||||
private TextView txtvLength;
|
||||
private SeekBar sbPosition;
|
||||
|
@ -90,6 +90,8 @@ public class AudioPlayerFragment extends Fragment implements
|
|||
private PlaybackController controller;
|
||||
private Disposable disposable;
|
||||
private boolean showTimeLeft;
|
||||
private boolean hasChapters = false;
|
||||
private TabLayoutMediator tabLayoutMediator;
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
|
@ -141,13 +143,37 @@ public class AudioPlayerFragment extends Fragment implements
|
|||
});
|
||||
}
|
||||
});
|
||||
pageIndicator = root.findViewById(R.id.page_indicator);
|
||||
pageIndicator.setViewPager(pager);
|
||||
pageIndicator.setOnClickListener(v ->
|
||||
pager.setCurrentItem((pager.getCurrentItem() + 1) % NUM_CONTENT_FRAGMENTS));
|
||||
|
||||
TabLayout tabLayout = root.findViewById(R.id.sliding_tabs);
|
||||
tabLayoutMediator = new TabLayoutMediator(tabLayout, pager, (tab, position) -> {
|
||||
tab.view.setAlpha(1.0f);
|
||||
switch (position) {
|
||||
case POS_COVER:
|
||||
tab.setText(R.string.cover_label);
|
||||
break;
|
||||
case POS_DESCR:
|
||||
tab.setText(R.string.description_label);
|
||||
break;
|
||||
case POS_CHAPTERS:
|
||||
tab.setText(R.string.chapters_label);
|
||||
if (!hasChapters) {
|
||||
tab.view.setAlpha(0.5f);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
tabLayoutMediator.attach();
|
||||
return root;
|
||||
}
|
||||
|
||||
public void setHasChapters(boolean hasChapters) {
|
||||
this.hasChapters = hasChapters;
|
||||
tabLayoutMediator.detach();
|
||||
tabLayoutMediator.attach();
|
||||
}
|
||||
|
||||
public View getExternalPlayerHolder() {
|
||||
return getView().findViewById(R.id.playerFragment);
|
||||
}
|
||||
|
@ -362,10 +388,6 @@ public class AudioPlayerFragment extends Fragment implements
|
|||
setupOptionsMenu(media);
|
||||
}
|
||||
|
||||
public void setHasChapters(boolean hasChapters) {
|
||||
pageIndicator.setDisabledPage(hasChapters ? -1 : 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
|
|
@ -1,124 +0,0 @@
|
|||
package de.danoeh.antennapod.view;
|
||||
|
||||
import android.animation.ArgbEvaluator;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.text.TextUtilsCompat;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.viewpager2.widget.ViewPager2;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public class PagerIndicatorView extends View {
|
||||
private final Paint paint = new Paint();
|
||||
private float position = 0;
|
||||
private int numPages = 0;
|
||||
private int disabledPage = -1;
|
||||
private int circleColor = 0;
|
||||
private int circleColorHighlight = -1;
|
||||
private boolean isLocaleRtl = false;
|
||||
|
||||
public PagerIndicatorView(Context context) {
|
||||
super(context);
|
||||
setup();
|
||||
}
|
||||
|
||||
public PagerIndicatorView(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setup();
|
||||
}
|
||||
|
||||
public PagerIndicatorView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
setup();
|
||||
}
|
||||
|
||||
private void setup() {
|
||||
isLocaleRtl = TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault())
|
||||
== ViewCompat.LAYOUT_DIRECTION_RTL;
|
||||
|
||||
paint.setAntiAlias(true);
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
|
||||
int[] colorAttrs = new int[]{android.R.attr.textColorSecondary};
|
||||
TypedArray a = getContext().obtainStyledAttributes(colorAttrs);
|
||||
circleColorHighlight = a.getColor(0, 0xffffffff);
|
||||
circleColor = (Integer) new ArgbEvaluator().evaluate(0.8f, 0x00ffffff, circleColorHighlight);
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Visual and logical position distinction only happens in RTL locales (e.g. Persian)
|
||||
* where pages positions are flipped thus it does nothing in LTR locales (e.g. English)
|
||||
*/
|
||||
private float logicalPositionToVisual(float position) {
|
||||
return isLocaleRtl ? numPages - 1 - position : position;
|
||||
}
|
||||
|
||||
public void setViewPager(ViewPager2 pager) {
|
||||
numPages = pager.getAdapter().getItemCount();
|
||||
pager.getAdapter().registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
|
||||
@Override
|
||||
public void onChanged() {
|
||||
numPages = pager.getAdapter().getItemCount();
|
||||
invalidate();
|
||||
}
|
||||
});
|
||||
pager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
PagerIndicatorView.this.position = logicalPositionToVisual(
|
||||
position + positionOffset);
|
||||
invalidate();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setDisabledPage(int disabledPage) {
|
||||
this.disabledPage = (int) logicalPositionToVisual(disabledPage);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
|
||||
for (int i = 0; i < numPages; i++) {
|
||||
if ((int) Math.floor(position) == i) {
|
||||
// This is the current dot
|
||||
drawCircle(canvas, i, (float) (1 - (position - Math.floor(position))));
|
||||
} else if ((int) Math.ceil(position) == i) {
|
||||
// This is the next dot
|
||||
drawCircle(canvas, i, (float) (position - Math.floor(position)));
|
||||
} else {
|
||||
drawCircle(canvas, i, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void drawCircle(Canvas canvas, int position, float frac) {
|
||||
float availableHeight = canvas.getHeight() - getPaddingTop() - getPaddingBottom();
|
||||
float circleRadiusSmall = availableHeight * 0.26f;
|
||||
float circleRadiusBig = availableHeight * 0.35f;
|
||||
float circleRadiusDelta = (circleRadiusBig - circleRadiusSmall);
|
||||
float start = 0.5f * (canvas.getWidth() - numPages * 1.5f * availableHeight);
|
||||
paint.setStrokeWidth(availableHeight * 0.3f);
|
||||
|
||||
if (position == disabledPage) {
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
} else {
|
||||
paint.setStyle(Paint.Style.FILL_AND_STROKE);
|
||||
}
|
||||
|
||||
paint.setColor((Integer) new ArgbEvaluator().evaluate(frac, circleColor, circleColorHighlight));
|
||||
canvas.drawCircle(start + (position * 1.5f + 0.75f) * availableHeight, 0.5f * availableHeight + getPaddingTop(),
|
||||
circleRadiusSmall + frac * circleRadiusDelta, paint);
|
||||
}
|
||||
}
|
|
@ -15,15 +15,15 @@
|
|||
app:navigationIcon="?homeAsUpIndicator"
|
||||
android:id="@+id/toolbar"/>
|
||||
|
||||
<de.danoeh.antennapod.view.PagerIndicatorView
|
||||
android:id="@+id/page_indicator"
|
||||
android:layout_height="16dp"
|
||||
android:layout_width="40dp"
|
||||
android:layout_marginTop="-12dp"
|
||||
android:padding="4dp"
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/sliding_tabs"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/toolbar"
|
||||
android:contentDescription="@string/switch_pages"
|
||||
android:layout_centerHorizontal="true"/>
|
||||
android:background="?android:attr/windowBackground"
|
||||
app:tabBackground="?attr/selectableItemBackground"
|
||||
app:tabMode="fixed"
|
||||
app:tabGravity="fill"/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/playerFragment"
|
||||
|
@ -39,7 +39,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_above="@id/playtime_layout"
|
||||
android:layout_below="@id/toolbar"
|
||||
android:layout_below="@id/sliding_tabs"
|
||||
android:foreground="?android:windowContentOverlay"
|
||||
android:layout_marginBottom="12dp"/>
|
||||
|
||||
|
|
Loading…
Reference in New Issue