diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/DetailActivity.java b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/DetailActivity.java
index a3336d532..8597b4bbd 100644
--- a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/DetailActivity.java
+++ b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/DetailActivity.java
@@ -38,6 +38,7 @@ import com.fongmi.android.tv.net.OKHttp;
import com.fongmi.android.tv.player.ExoUtil;
import com.fongmi.android.tv.player.Players;
import com.fongmi.android.tv.ui.custom.CustomKeyDown;
+import com.fongmi.android.tv.ui.custom.TrackSelectionDialog;
import com.fongmi.android.tv.ui.presenter.EpisodePresenter;
import com.fongmi.android.tv.ui.presenter.FlagPresenter;
import com.fongmi.android.tv.ui.presenter.GroupPresenter;
@@ -147,6 +148,7 @@ public class DetailActivity extends BaseActivity implements CustomKeyDown.Listen
mControl.scale.setOnClickListener(view -> onScale());
mControl.reset.setOnClickListener(view -> onReset());
mControl.speed.setOnClickListener(view -> onSpeed());
+ mControl.tracks.setOnClickListener(view -> onTracks());
mControl.ending.setOnClickListener(view -> onEnding());
mControl.opening.setOnClickListener(view -> onOpening());
mControl.interval.setOnClickListener(view -> onInterval());
@@ -212,8 +214,8 @@ public class DetailActivity extends BaseActivity implements CustomKeyDown.Listen
private void resetFocus(boolean useParse) {
mControl.exoProgress.setNextFocusUpId(useParse ? R.id.parse : R.id.next);
- for (int i = 0; i < mControl.playLayout.getChildCount(); i++) {
- mControl.playLayout.getChildAt(i).setNextFocusDownId(useParse ? R.id.parse : com.google.android.exoplayer2.ui.R.id.exo_progress);
+ for (int i = 0; i < mControl.actionLayout.getChildCount(); i++) {
+ mControl.actionLayout.getChildAt(i).setNextFocusDownId(useParse ? R.id.parse : com.google.android.exoplayer2.ui.R.id.exo_progress);
}
}
@@ -224,9 +226,10 @@ public class DetailActivity extends BaseActivity implements CustomKeyDown.Listen
private void getPlayer(boolean replay) {
Vod.Flag.Episode item = (Vod.Flag.Episode) mEpisodeAdapter.get(getEpisodePosition());
if (mFullscreen && Players.get().getRetry() == 0) Notify.show(ResUtil.getString(R.string.play_ready, item.getName()));
+ mBinding.widget.title.setText(getString(R.string.detail_title, mBinding.name.getText(), item.getName()));
mViewModel.playerContent(getKey(), getVodFlag().getFlag(), item.getUrl());
- mBinding.progress.getRoot().setVisibility(View.VISIBLE);
- mBinding.error.getRoot().setVisibility(View.GONE);
+ mBinding.widget.progress.getRoot().setVisibility(View.VISIBLE);
+ mBinding.widget.error.setVisibility(View.GONE);
updateHistory(item, replay);
}
@@ -272,6 +275,7 @@ public class DetailActivity extends BaseActivity implements CustomKeyDown.Listen
for (int i = 0; i < mFlagAdapter.size(); i++) ((Vod.Flag) mFlagAdapter.get(i)).toggle(mCurrent == i, item);
mEpisodeAdapter.notifyArrayItemRangeChanged(0, mEpisodeAdapter.size());
mHandler.post(() -> mBinding.episode.setSelectedPosition(getEpisodePosition()));
+ mBinding.widget.title.setText(getString(R.string.detail_title, mBinding.name.getText(), item.getName()));
if (mEpisodeAdapter.size() == 0) return;
getPlayer(false);
}
@@ -284,8 +288,8 @@ public class DetailActivity extends BaseActivity implements CustomKeyDown.Listen
private void setParseActivated(Parse item) {
ApiConfig.get().setParse(item);
- mBinding.error.getRoot().setVisibility(View.GONE);
- mBinding.progress.getRoot().setVisibility(View.VISIBLE);
+ mBinding.widget.error.setVisibility(View.GONE);
+ mBinding.widget.progress.getRoot().setVisibility(View.VISIBLE);
Result result = mViewModel.getPlayer().getValue();
if (result != null) Players.get().start(result, true);
mParseAdapter.notifyArrayItemRangeChanged(0, mParseAdapter.size());
@@ -423,6 +427,12 @@ public class DetailActivity extends BaseActivity implements CustomKeyDown.Listen
mHistory.update();
}
+ private void onTracks() {
+ mHandler.postDelayed(() -> getPlayerView().hideController(), 150);
+ TrackSelectionDialog.createForPlayer(Players.get().exo(), dialog -> {
+ }).show(getSupportFragmentManager(), "tracks");
+ }
+
private void getPart(String source) {
OKHttp.newCall("http://api.pullword.com/get.php?source=" + URLEncoder.encode(source) + "¶m1=0¶m2=0&json=1").enqueue(new Callback() {
@Override
@@ -483,8 +493,9 @@ public class DetailActivity extends BaseActivity implements CustomKeyDown.Listen
private final Runnable mHideCenter = new Runnable() {
@Override
public void run() {
- mBinding.center.action.setImageResource(R.drawable.ic_play);
- mBinding.center.getRoot().setVisibility(View.GONE);
+ mBinding.widget.action.setImageResource(R.drawable.ic_play);
+ mBinding.widget.center.setVisibility(View.GONE);
+ mBinding.widget.title.setVisibility(View.GONE);
}
};
@@ -512,11 +523,12 @@ public class DetailActivity extends BaseActivity implements CustomKeyDown.Listen
case Player.STATE_IDLE:
break;
case Player.STATE_BUFFERING:
- mBinding.progress.getRoot().setVisibility(View.VISIBLE);
+ mBinding.widget.progress.getRoot().setVisibility(View.VISIBLE);
break;
case Player.STATE_READY:
Players.get().setRetry(0);
- mBinding.progress.getRoot().setVisibility(View.GONE);
+ TrackSelectionDialog.setVisible(mControl.tracks);
+ mBinding.widget.progress.getRoot().setVisibility(View.GONE);
break;
case Player.STATE_ENDED:
if (Players.get().canNext()) checkNext();
@@ -548,9 +560,9 @@ public class DetailActivity extends BaseActivity implements CustomKeyDown.Listen
}
private void onError(String msg) {
- mBinding.progress.getRoot().setVisibility(View.GONE);
- mBinding.error.getRoot().setVisibility(View.VISIBLE);
- mBinding.error.text.setText(msg);
+ mBinding.widget.progress.getRoot().setVisibility(View.GONE);
+ mBinding.widget.error.setVisibility(View.VISIBLE);
+ mBinding.widget.text.setText(msg);
Players.get().stop();
stopTimer();
}
@@ -563,10 +575,10 @@ public class DetailActivity extends BaseActivity implements CustomKeyDown.Listen
@Override
public void onSeeking(int time) {
- mBinding.center.exoDuration.setText(mControl.exoDuration.getText());
- mBinding.center.exoPosition.setText(Players.get().getTime(time));
- mBinding.center.action.setImageResource(time > 0 ? R.drawable.ic_forward : R.drawable.ic_rewind);
- mBinding.center.getRoot().setVisibility(View.VISIBLE);
+ mBinding.widget.exoDuration.setText(mControl.exoDuration.getText());
+ mBinding.widget.exoPosition.setText(Players.get().getTime(time));
+ mBinding.widget.action.setImageResource(time > 0 ? R.drawable.ic_forward : R.drawable.ic_rewind);
+ mBinding.widget.center.setVisibility(View.VISIBLE);
}
@Override
@@ -587,12 +599,14 @@ public class DetailActivity extends BaseActivity implements CustomKeyDown.Listen
public void onKeyCenter() {
if (Players.get().isPlaying()) {
Players.get().pause();
- mBinding.center.getRoot().setVisibility(View.VISIBLE);
- mBinding.center.exoPosition.setText(Players.get().getTime(0));
- mBinding.center.exoDuration.setText(mControl.exoDuration.getText());
+ mBinding.widget.title.setVisibility(View.VISIBLE);
+ mBinding.widget.center.setVisibility(View.VISIBLE);
+ mBinding.widget.exoPosition.setText(Players.get().getTime(0));
+ mBinding.widget.exoDuration.setText(mControl.exoDuration.getText());
} else {
Players.get().play();
- mBinding.center.getRoot().setVisibility(View.GONE);
+ mBinding.widget.title.setVisibility(View.GONE);
+ mBinding.widget.center.setVisibility(View.GONE);
}
}
diff --git a/app/src/leanback/res/layout/activity_detail.xml b/app/src/leanback/res/layout/activity_detail.xml
index d0b0fe869..69436dc46 100644
--- a/app/src/leanback/res/layout/activity_detail.xml
+++ b/app/src/leanback/res/layout/activity_detail.xml
@@ -43,25 +43,10 @@
app:use_controller="false" />
-
-
-
-
+ android:id="@+id/widget"
+ layout="@layout/view_controller_widget"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
diff --git a/app/src/leanback/res/layout/adapter_parse.xml b/app/src/leanback/res/layout/adapter_parse.xml
index cf858a378..03af7be12 100644
--- a/app/src/leanback/res/layout/adapter_parse.xml
+++ b/app/src/leanback/res/layout/adapter_parse.xml
@@ -8,7 +8,7 @@
android:focusable="true"
android:focusableInTouchMode="true"
android:gravity="center"
- android:nextFocusUp="@id/playLayout"
+ android:nextFocusUp="@id/action"
android:nextFocusDown="@id/exo_progress"
android:singleLine="true"
android:textColor="@color/white"
diff --git a/app/src/leanback/res/layout/dialog_config.xml b/app/src/leanback/res/layout/dialog_config.xml
index 04af8fb04..e577d1037 100644
--- a/app/src/leanback/res/layout/dialog_config.xml
+++ b/app/src/leanback/res/layout/dialog_config.xml
@@ -35,6 +35,7 @@
android:imeOptions="actionDone"
android:importantForAutofill="no"
android:inputType="text"
+ android:nextFocusDown="@id/positive"
android:singleLine="true"
android:textSize="18sp" />
@@ -47,7 +48,7 @@
android:orientation="horizontal">
diff --git a/app/src/leanback/res/layout/view_controller_bottom.xml b/app/src/leanback/res/layout/view_controller_bottom.xml
index fbb7b4f80..81f9db5f5 100644
--- a/app/src/leanback/res/layout/view_controller_bottom.xml
+++ b/app/src/leanback/res/layout/view_controller_bottom.xml
@@ -15,148 +15,170 @@
android:paddingEnd="16dp"
android:paddingBottom="8dp">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:fillViewport="true"
+ android:scrollbars="none">
-
-
-
-
-
-
-
-
-
+ android:animateLayoutChanges="true"
+ android:gravity="center_vertical"
+ android:orientation="horizontal">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/leanback/res/layout/view_controller_widget.xml b/app/src/leanback/res/layout/view_controller_widget.xml
new file mode 100644
index 000000000..42c68cdba
--- /dev/null
+++ b/app/src/leanback/res/layout/view_controller_widget.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/fongmi/android/tv/model/SiteViewModel.java b/app/src/main/java/com/fongmi/android/tv/model/SiteViewModel.java
index 6ed6851c3..318942536 100644
--- a/app/src/main/java/com/fongmi/android/tv/model/SiteViewModel.java
+++ b/app/src/main/java/com/fongmi/android/tv/model/SiteViewModel.java
@@ -164,7 +164,7 @@ public class SiteViewModel extends ViewModel {
if (site.getType() == 1) params.put("ac", "detail");
params.put("wd", keyword);
String body = OKHttp.newCall(site.getApi(), params).execute().body().string();
- SpiderDebug.log(site.getName() +"," +body);
+ SpiderDebug.log(site.getName() + "," + body);
if (site.getType() == 0) post(site, Result.fromXml(body));
else post(site, Result.fromJson(body));
}
diff --git a/app/src/main/java/com/fongmi/android/tv/player/ExoUtil.java b/app/src/main/java/com/fongmi/android/tv/player/ExoUtil.java
index c8010a35c..9ae06e855 100644
--- a/app/src/main/java/com/fongmi/android/tv/player/ExoUtil.java
+++ b/app/src/main/java/com/fongmi/android/tv/player/ExoUtil.java
@@ -13,6 +13,7 @@ import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.ext.rtmp.RtmpDataSource;
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory;
import com.google.android.exoplayer2.source.MediaSource;
+import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.ui.CaptionStyleCompat;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultDataSource;
@@ -28,7 +29,7 @@ public class ExoUtil {
static ExoPlayer create() {
DefaultRenderersFactory renderersFactory = new DefaultRenderersFactory(App.get());
renderersFactory.setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER);
- return new ExoPlayer.Builder(App.get()).setRenderersFactory(renderersFactory).build();
+ return new ExoPlayer.Builder(App.get()).setRenderersFactory(renderersFactory).setTrackSelector(new DefaultTrackSelector(App.get())).build();
}
public static CaptionStyleCompat getCaptionStyle() {
@@ -54,7 +55,7 @@ public class ExoUtil {
}
private static MediaItem.SubtitleConfiguration getConfig(Result result) {
- return result.getSub().isEmpty() ? null : new MediaItem.SubtitleConfiguration.Builder(Uri.parse(result.getSub())).setMimeType(MimeTypes.APPLICATION_SUBRIP).setSelectionFlags(C.SELECTION_FLAG_DEFAULT).build();
+ return result.getSub().isEmpty() ? null : new MediaItem.SubtitleConfiguration.Builder(Uri.parse(result.getSub())).setLabel("Spider").setMimeType(MimeTypes.APPLICATION_SUBRIP).setSelectionFlags(C.SELECTION_FLAG_DEFAULT).build();
}
private static DataSource.Factory getFactory(Map headers, String url) {
diff --git a/app/src/main/java/com/fongmi/android/tv/ui/custom/TrackSelectionDialog.java b/app/src/main/java/com/fongmi/android/tv/ui/custom/TrackSelectionDialog.java
new file mode 100644
index 000000000..9fb0be7e6
--- /dev/null
+++ b/app/src/main/java/com/fongmi/android/tv/ui/custom/TrackSelectionDialog.java
@@ -0,0 +1,272 @@
+package com.fongmi.android.tv.ui.custom;
+
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.util.SparseArray;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatDialog;
+import androidx.fragment.app.DialogFragment;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentPagerAdapter;
+import androidx.viewpager.widget.ViewPager;
+
+import com.fongmi.android.tv.player.Players;
+import com.google.android.exoplayer2.C;
+import com.google.android.exoplayer2.Player;
+import com.google.android.exoplayer2.Tracks;
+import com.google.android.exoplayer2.source.TrackGroup;
+import com.google.android.exoplayer2.trackselection.TrackSelectionOverride;
+import com.google.android.exoplayer2.trackselection.TrackSelectionParameters;
+import com.google.android.exoplayer2.ui.R;
+import com.google.android.exoplayer2.ui.TrackSelectionView;
+import com.google.android.material.tabs.TabLayout;
+import com.google.common.collect.ImmutableList;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public final class TrackSelectionDialog extends DialogFragment {
+
+ public static final ImmutableList SUPPORTED_TRACK_TYPES = ImmutableList.of(C.TRACK_TYPE_VIDEO, C.TRACK_TYPE_AUDIO, C.TRACK_TYPE_TEXT);
+ private final SparseArray tabFragments;
+ private final ArrayList tabTrackTypes;
+ private DialogInterface.OnClickListener onClickListener;
+ private DialogInterface.OnDismissListener onDismissListener;
+
+ public TrackSelectionDialog() {
+ tabFragments = new SparseArray<>();
+ tabTrackTypes = new ArrayList<>();
+ setRetainInstance(true);
+ }
+
+ /**
+ * Returns whether a track selection dialog will have content to display if initialized with the
+ * specified {@link Player}.
+ */
+ public static void setVisible(View view) {
+ view.setVisibility(willHaveContent(Players.get().exo().getCurrentTracks()) ? View.VISIBLE : View.GONE);
+ }
+
+ /**
+ * Returns whether a track selection dialog will have content to display if initialized with the
+ * specified {@link Tracks}.
+ */
+ public static boolean willHaveContent(Tracks tracks) {
+ for (Tracks.Group trackGroup : tracks.getGroups()) {
+ if (SUPPORTED_TRACK_TYPES.contains(trackGroup.getType())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Creates a dialog for a given {@link Player}, whose parameters will be automatically updated
+ * when tracks are selected.
+ *
+ * @param player The {@link Player}.
+ * @param onDismissListener A {@link DialogInterface.OnDismissListener} to call when the dialog is
+ * dismissed.
+ */
+ public static TrackSelectionDialog createForPlayer(Player player, DialogInterface.OnDismissListener onDismissListener) {
+ return createForTracksAndParameters(player.getCurrentTracks(), player.getTrackSelectionParameters(), true, false, player::setTrackSelectionParameters, onDismissListener);
+ }
+
+ /**
+ * Creates a dialog for given {@link Tracks} and {@link TrackSelectionParameters}.
+ *
+ * @param tracks The {@link Tracks} describing the tracks to display.
+ * @param trackSelectionParameters The initial {@link TrackSelectionParameters}.
+ * @param allowAdaptiveSelections Whether adaptive selections (consisting of more than one track)
+ * can be made.
+ * @param allowMultipleOverrides Whether tracks from multiple track groups can be selected.
+ * @param trackSelectionListener Called when tracks are selected.
+ * @param onDismissListener {@link DialogInterface.OnDismissListener} called when the dialog is
+ * dismissed.
+ */
+ public static TrackSelectionDialog createForTracksAndParameters(Tracks tracks, TrackSelectionParameters trackSelectionParameters, boolean allowAdaptiveSelections, boolean allowMultipleOverrides, TrackSelectionListener trackSelectionListener, DialogInterface.OnDismissListener onDismissListener) {
+ TrackSelectionDialog trackSelectionDialog = new TrackSelectionDialog();
+ trackSelectionDialog.init(tracks, trackSelectionParameters, allowAdaptiveSelections, allowMultipleOverrides, (dialog, which) -> {
+ TrackSelectionParameters.Builder builder = trackSelectionParameters.buildUpon();
+ for (int i = 0; i < SUPPORTED_TRACK_TYPES.size(); i++) {
+ int trackType = SUPPORTED_TRACK_TYPES.get(i);
+ builder.setTrackTypeDisabled(trackType, trackSelectionDialog.getIsDisabled(trackType));
+ builder.clearOverridesOfType(trackType);
+ Map overrides = trackSelectionDialog.getOverrides(trackType);
+ for (TrackSelectionOverride override : overrides.values()) builder.addOverride(override);
+ }
+ trackSelectionListener.onTracksSelected(builder.build());
+ }, onDismissListener);
+ return trackSelectionDialog;
+ }
+
+ private static String getTrackTypeString(Resources resources, @C.TrackType int trackType) {
+ switch (trackType) {
+ case C.TRACK_TYPE_VIDEO:
+ return resources.getString(R.string.exo_track_selection_title_video);
+ case C.TRACK_TYPE_AUDIO:
+ return resources.getString(R.string.exo_track_selection_title_audio);
+ case C.TRACK_TYPE_TEXT:
+ return resources.getString(R.string.exo_track_selection_title_text);
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ private void init(Tracks tracks, TrackSelectionParameters trackSelectionParameters, boolean allowAdaptiveSelections, boolean allowMultipleOverrides, DialogInterface.OnClickListener onClickListener, DialogInterface.OnDismissListener onDismissListener) {
+ this.onClickListener = onClickListener;
+ this.onDismissListener = onDismissListener;
+ for (int i = 0; i < SUPPORTED_TRACK_TYPES.size(); i++) {
+ @C.TrackType int trackType = SUPPORTED_TRACK_TYPES.get(i);
+ ArrayList trackGroups = new ArrayList<>();
+ for (Tracks.Group trackGroup : tracks.getGroups()) {
+ if (trackGroup.getType() == trackType) {
+ trackGroups.add(trackGroup);
+ }
+ }
+ if (!trackGroups.isEmpty()) {
+ TrackSelectionViewFragment tabFragment = new TrackSelectionViewFragment();
+ tabFragment.init(trackGroups, trackSelectionParameters.disabledTrackTypes.contains(trackType), trackSelectionParameters.overrides, allowAdaptiveSelections, allowMultipleOverrides);
+ tabFragments.put(trackType, tabFragment);
+ tabTrackTypes.add(trackType);
+ }
+ }
+ }
+
+ /**
+ * Returns whether the disabled option is selected for the specified track type.
+ *
+ * @param trackType The track type.
+ * @return Whether the disabled option is selected for the track type.
+ */
+ public boolean getIsDisabled(int trackType) {
+ TrackSelectionViewFragment trackView = tabFragments.get(trackType);
+ return trackView != null && trackView.isDisabled;
+ }
+
+ /**
+ * Returns the selected track overrides for the specified track type.
+ *
+ * @param trackType The track type.
+ * @return The track overrides for the track type.
+ */
+ public Map getOverrides(int trackType) {
+ TrackSelectionViewFragment trackView = tabFragments.get(trackType);
+ return trackView == null ? Collections.emptyMap() : trackView.overrides;
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ Dialog dialog = new AppCompatDialog(getActivity());
+ dialog.getWindow().setDimAmount(0);
+ return dialog;
+ }
+
+ @Override
+ public void onDismiss(@NonNull DialogInterface dialog) {
+ super.onDismiss(dialog);
+ onDismissListener.onDismiss(dialog);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ View dialogView = inflater.inflate(com.fongmi.android.tv.R.layout.dialog_tracks, container, false);
+ TabLayout tabLayout = dialogView.findViewById(com.fongmi.android.tv.R.id.track_selection_dialog_tab_layout);
+ ViewPager viewPager = dialogView.findViewById(com.fongmi.android.tv.R.id.track_selection_dialog_view_pager);
+ TextView cancelButton = dialogView.findViewById(com.fongmi.android.tv.R.id.track_selection_dialog_cancel_button);
+ TextView okButton = dialogView.findViewById(com.fongmi.android.tv.R.id.track_selection_dialog_ok_button);
+ viewPager.setAdapter(new FragmentAdapter(getChildFragmentManager()));
+ tabLayout.setupWithViewPager(viewPager);
+ tabLayout.setVisibility(tabFragments.size() > 1 ? View.VISIBLE : View.GONE);
+ cancelButton.setOnClickListener(view -> dismiss());
+ okButton.setOnClickListener(view -> {
+ onClickListener.onClick(getDialog(), DialogInterface.BUTTON_POSITIVE);
+ dismiss();
+ });
+ return dialogView;
+ }
+
+ public interface TrackSelectionListener {
+
+ void onTracksSelected(TrackSelectionParameters trackSelectionParameters);
+ }
+
+ /**
+ * Fragment to show a track selection in tab of the track selection dialog.
+ */
+ public static final class TrackSelectionViewFragment extends Fragment implements TrackSelectionView.TrackSelectionListener {
+
+ private List trackGroups;
+ private boolean allowAdaptiveSelections;
+ private boolean allowMultipleOverrides;
+ Map overrides;
+ boolean isDisabled;
+
+ public TrackSelectionViewFragment() {
+ setRetainInstance(true);
+ }
+
+ public void init(List trackGroups, boolean isDisabled, Map overrides, boolean allowAdaptiveSelections, boolean allowMultipleOverrides) {
+ this.trackGroups = trackGroups;
+ this.isDisabled = isDisabled;
+ this.allowAdaptiveSelections = allowAdaptiveSelections;
+ this.allowMultipleOverrides = allowMultipleOverrides;
+ // TrackSelectionView does this filtering internally, but we need to do it here as well to
+ // handle the case where the TrackSelectionView is never created.
+ this.overrides = new HashMap<>(TrackSelectionView.filterOverrides(overrides, trackGroups, allowMultipleOverrides));
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ View rootView = inflater.inflate(R.layout.exo_track_selection_dialog, container, /* attachToRoot= */ false);
+ TrackSelectionView trackSelectionView = rootView.findViewById(R.id.exo_track_selection_view);
+ trackSelectionView.setShowDisableOption(true);
+ trackSelectionView.setAllowMultipleOverrides(allowMultipleOverrides);
+ trackSelectionView.setAllowAdaptiveSelections(allowAdaptiveSelections);
+ trackSelectionView.init(trackGroups, isDisabled, overrides, null, this);
+ return rootView;
+ }
+
+ @Override
+ public void onTrackSelectionChanged(boolean isDisabled, @NonNull Map overrides) {
+ this.isDisabled = isDisabled;
+ this.overrides = overrides;
+ }
+ }
+
+ private final class FragmentAdapter extends FragmentPagerAdapter {
+
+ public FragmentAdapter(FragmentManager fragmentManager) {
+ super(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
+ }
+
+ @NonNull
+ @Override
+ public Fragment getItem(int position) {
+ return tabFragments.get(tabTrackTypes.get(position));
+ }
+
+ @Override
+ public int getCount() {
+ return tabTrackTypes.size();
+ }
+
+ @Override
+ public CharSequence getPageTitle(int position) {
+ return getTrackTypeString(getResources(), tabTrackTypes.get(position));
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/shape_title.xml b/app/src/main/res/drawable/shape_title.xml
new file mode 100644
index 000000000..54bd9fd1b
--- /dev/null
+++ b/app/src/main/res/drawable/shape_title.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/dialog_tracks.xml b/app/src/main/res/layout/dialog_tracks.xml
new file mode 100644
index 000000000..4c14b4cd3
--- /dev/null
+++ b/app/src/main/res/layout/dialog_tracks.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/view_error.xml b/app/src/main/res/layout/view_error.xml
deleted file mode 100644
index 565d4505a..000000000
--- a/app/src/main/res/layout/view_error.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml
index 5ba84b486..dea46ef31 100644
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ b/app/src/main/res/values-zh-rCN/strings.xml
@@ -11,6 +11,7 @@
上次看到%s
+ %s:%s
站源:%s
年份:%s
地区:%s
@@ -26,6 +27,7 @@
准备播放:%s
重播
重置
+ 轨道
片头片尾
倒序
→
diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml
index 2122cb255..cd5886e97 100644
--- a/app/src/main/res/values-zh-rTW/strings.xml
+++ b/app/src/main/res/values-zh-rTW/strings.xml
@@ -11,6 +11,7 @@
上次看到%s
+ %s:%s
站源:%s
年份:%s
地區:%s
@@ -26,6 +27,7 @@
準備播放:%s
重播
重置
+ 軌道
片頭片尾
倒序
→
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 1e9698aa9..5303ea962 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -11,6 +11,7 @@
Last seen %s
+ %s : %s
Site: %s
Year: %s
Area: %s
@@ -26,6 +27,7 @@
Ready to play: %s
Replay
Reset
+ Tracks
OP&ED
Reverse
→