mirror of
https://codeberg.org/tom79/Fedilab.git
synced 2025-03-12 01:39:53 +02:00
track selector
This commit is contained in:
parent
f082611b02
commit
0a9c5162ca
6 changed files with 426 additions and 7 deletions
|
@ -149,7 +149,6 @@ import app.fedilab.android.peertube.client.data.PlaylistData;
|
||||||
import app.fedilab.android.peertube.client.data.PluginData;
|
import app.fedilab.android.peertube.client.data.PluginData;
|
||||||
import app.fedilab.android.peertube.client.data.VideoData;
|
import app.fedilab.android.peertube.client.data.VideoData;
|
||||||
import app.fedilab.android.peertube.client.entities.Error;
|
import app.fedilab.android.peertube.client.entities.Error;
|
||||||
import app.fedilab.android.peertube.client.entities.File;
|
|
||||||
import app.fedilab.android.peertube.client.entities.MenuItemView;
|
import app.fedilab.android.peertube.client.entities.MenuItemView;
|
||||||
import app.fedilab.android.peertube.client.entities.PlaylistExist;
|
import app.fedilab.android.peertube.client.entities.PlaylistExist;
|
||||||
import app.fedilab.android.peertube.client.entities.Report;
|
import app.fedilab.android.peertube.client.entities.Report;
|
||||||
|
@ -159,6 +158,7 @@ import app.fedilab.android.peertube.drawer.MenuAdapter;
|
||||||
import app.fedilab.android.peertube.drawer.MenuItemAdapter;
|
import app.fedilab.android.peertube.drawer.MenuItemAdapter;
|
||||||
import app.fedilab.android.peertube.helper.Helper;
|
import app.fedilab.android.peertube.helper.Helper;
|
||||||
import app.fedilab.android.peertube.helper.HelperInstance;
|
import app.fedilab.android.peertube.helper.HelperInstance;
|
||||||
|
import app.fedilab.android.peertube.helper.TrackSelectionDialog;
|
||||||
import app.fedilab.android.peertube.viewmodel.CaptionsVM;
|
import app.fedilab.android.peertube.viewmodel.CaptionsVM;
|
||||||
import app.fedilab.android.peertube.viewmodel.CommentVM;
|
import app.fedilab.android.peertube.viewmodel.CommentVM;
|
||||||
import app.fedilab.android.peertube.viewmodel.PlaylistsVM;
|
import app.fedilab.android.peertube.viewmodel.PlaylistsVM;
|
||||||
|
@ -203,7 +203,7 @@ public class PeertubeActivity extends BasePeertubeActivity implements CommentLis
|
||||||
private String currentCaption;
|
private String currentCaption;
|
||||||
private boolean isRemote;
|
private boolean isRemote;
|
||||||
private boolean willPlayFromIntent;
|
private boolean willPlayFromIntent;
|
||||||
|
private boolean isShowingTrackSelectionDialog;
|
||||||
private Status status;
|
private Status status;
|
||||||
|
|
||||||
public static void hideKeyboard(Activity activity) {
|
public static void hideKeyboard(Activity activity) {
|
||||||
|
@ -1765,7 +1765,7 @@ public class PeertubeActivity extends BasePeertubeActivity implements CommentLis
|
||||||
List<MenuItemView> items = new ArrayList<>();
|
List<MenuItemView> items = new ArrayList<>();
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case RESOLUTION:
|
case RESOLUTION:
|
||||||
binding.subMenuTitle.setText(R.string.pickup_resolution);
|
/*binding.subMenuTitle.setText(R.string.pickup_resolution);
|
||||||
int position = 0;
|
int position = 0;
|
||||||
for (File file : peertube.getAllFile(PeertubeActivity.this)) {
|
for (File file : peertube.getAllFile(PeertubeActivity.this)) {
|
||||||
|
|
||||||
|
@ -1790,6 +1790,15 @@ public class PeertubeActivity extends BasePeertubeActivity implements CommentLis
|
||||||
position++;
|
position++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}*/
|
||||||
|
if (!isShowingTrackSelectionDialog
|
||||||
|
&& TrackSelectionDialog.willHaveContent(player)) {
|
||||||
|
isShowingTrackSelectionDialog = true;
|
||||||
|
TrackSelectionDialog trackSelectionDialog =
|
||||||
|
TrackSelectionDialog.createForPlayer(
|
||||||
|
player,
|
||||||
|
/* onDismissListener= */ dismissedDialog -> isShowingTrackSelectionDialog = false);
|
||||||
|
trackSelectionDialog.show(getSupportFragmentManager(), /* tag= */ null);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SPEED:
|
case SPEED:
|
||||||
|
|
|
@ -146,7 +146,7 @@ public class VideoData implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<File> getAllFile(Context context) {
|
public List<File> getAllFile(Context context) {
|
||||||
if (files != null && files.size() > 0) {
|
if (files != null && files.size() > 0) { //Old support
|
||||||
return files;
|
return files;
|
||||||
} else if (streamingPlaylists != null) {
|
} else if (streamingPlaylists != null) {
|
||||||
List<File> files = new ArrayList<>();
|
List<File> files = new ArrayList<>();
|
||||||
|
@ -156,9 +156,6 @@ public class VideoData implements Serializable {
|
||||||
file.setFileUrl(streamingPlaylists.getPlaylistUrl());
|
file.setFileUrl(streamingPlaylists.getPlaylistUrl());
|
||||||
file.setFileDownloadUrl(streamingPlaylists.getPlaylistUrl());
|
file.setFileDownloadUrl(streamingPlaylists.getPlaylistUrl());
|
||||||
files.add(file);
|
files.add(file);
|
||||||
if (streamingPlaylists.getFiles().size() > 0) {
|
|
||||||
files.addAll(streamingPlaylists.getFiles());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,352 @@
|
||||||
|
package app.fedilab.android.peertube.helper;
|
||||||
|
|
||||||
|
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.Button;
|
||||||
|
|
||||||
|
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.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.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;
|
||||||
|
|
||||||
|
import app.fedilab.android.R;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dialog to select tracks.
|
||||||
|
*/
|
||||||
|
public final class TrackSelectionDialog extends DialogFragment {
|
||||||
|
|
||||||
|
public static final ImmutableList<Integer> SUPPORTED_TRACK_TYPES =
|
||||||
|
ImmutableList.of(C.TRACK_TYPE_VIDEO, C.TRACK_TYPE_AUDIO, C.TRACK_TYPE_TEXT);
|
||||||
|
private final SparseArray<TrackSelectionViewFragment> tabFragments;
|
||||||
|
private final ArrayList<Integer> tabTrackTypes;
|
||||||
|
private int titleId;
|
||||||
|
private DialogInterface.OnClickListener onClickListener;
|
||||||
|
private DialogInterface.OnDismissListener onDismissListener;
|
||||||
|
|
||||||
|
public TrackSelectionDialog() {
|
||||||
|
tabFragments = new SparseArray<>();
|
||||||
|
tabTrackTypes = new ArrayList<>();
|
||||||
|
// Retain instance across activity re-creation to prevent losing access to init data.
|
||||||
|
setRetainInstance(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether a track selection dialog will have content to display if initialized with the
|
||||||
|
* specified {@link Player}.
|
||||||
|
*/
|
||||||
|
public static boolean willHaveContent(Player player) {
|
||||||
|
return willHaveContent(player.getCurrentTracks());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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(
|
||||||
|
R.string.track_selection_title,
|
||||||
|
player.getCurrentTracks(),
|
||||||
|
player.getTrackSelectionParameters(),
|
||||||
|
/* allowAdaptiveSelections= */ true,
|
||||||
|
/* allowMultipleOverrides= */ false,
|
||||||
|
player::setTrackSelectionParameters,
|
||||||
|
onDismissListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a dialog for given {@link Tracks} and {@link TrackSelectionParameters}.
|
||||||
|
*
|
||||||
|
* @param titleId The resource id of the dialog title.
|
||||||
|
* @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(
|
||||||
|
int titleId,
|
||||||
|
Tracks tracks,
|
||||||
|
TrackSelectionParameters trackSelectionParameters,
|
||||||
|
boolean allowAdaptiveSelections,
|
||||||
|
boolean allowMultipleOverrides,
|
||||||
|
TrackSelectionListener trackSelectionListener,
|
||||||
|
DialogInterface.OnDismissListener onDismissListener) {
|
||||||
|
TrackSelectionDialog trackSelectionDialog = new TrackSelectionDialog();
|
||||||
|
trackSelectionDialog.init(
|
||||||
|
tracks,
|
||||||
|
trackSelectionParameters,
|
||||||
|
titleId,
|
||||||
|
allowAdaptiveSelections,
|
||||||
|
allowMultipleOverrides,
|
||||||
|
/* onClickListener= */ (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<TrackGroup, TrackSelectionOverride> 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,
|
||||||
|
int titleId,
|
||||||
|
boolean allowAdaptiveSelections,
|
||||||
|
boolean allowMultipleOverrides,
|
||||||
|
DialogInterface.OnClickListener onClickListener,
|
||||||
|
DialogInterface.OnDismissListener onDismissListener) {
|
||||||
|
this.titleId = titleId;
|
||||||
|
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<Tracks.Group> 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<TrackGroup, TrackSelectionOverride> getOverrides(int trackType) {
|
||||||
|
TrackSelectionViewFragment trackView = tabFragments.get(trackType);
|
||||||
|
return trackView == null ? Collections.emptyMap() : trackView.overrides;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
|
// We need to own the view to let tab layout work correctly on all API levels. We can't use
|
||||||
|
// AlertDialog because it owns the view itself, so we use AppCompatDialog instead, themed using
|
||||||
|
// the AlertDialog theme overlay with force-enabled title.
|
||||||
|
AppCompatDialog dialog =
|
||||||
|
new AppCompatDialog(getActivity());
|
||||||
|
dialog.setTitle(titleId);
|
||||||
|
return dialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDismiss(DialogInterface dialog) {
|
||||||
|
super.onDismiss(dialog);
|
||||||
|
onDismissListener.onDismiss(dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(
|
||||||
|
LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
|
View dialogView = inflater.inflate(R.layout.track_selection_dialog, container, false);
|
||||||
|
TabLayout tabLayout = dialogView.findViewById(R.id.track_selection_dialog_tab_layout);
|
||||||
|
ViewPager viewPager = dialogView.findViewById(R.id.track_selection_dialog_view_pager);
|
||||||
|
Button cancelButton = dialogView.findViewById(R.id.track_selection_dialog_cancel_button);
|
||||||
|
Button okButton = dialogView.findViewById(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when tracks are selected.
|
||||||
|
*/
|
||||||
|
public interface TrackSelectionListener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when tracks are selected.
|
||||||
|
*
|
||||||
|
* @param trackSelectionParameters A {@link TrackSelectionParameters} representing the selected
|
||||||
|
* tracks. Any manual selections are defined by {@link
|
||||||
|
* TrackSelectionParameters#disabledTrackTypes} and {@link
|
||||||
|
* TrackSelectionParameters#overrides}.
|
||||||
|
*/
|
||||||
|
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 {
|
||||||
|
|
||||||
|
/* package */ boolean isDisabled;
|
||||||
|
/* package */ Map<TrackGroup, TrackSelectionOverride> overrides;
|
||||||
|
private List<Tracks.Group> trackGroups;
|
||||||
|
private boolean allowAdaptiveSelections;
|
||||||
|
private boolean allowMultipleOverrides;
|
||||||
|
|
||||||
|
public TrackSelectionViewFragment() {
|
||||||
|
// Retain instance across activity re-creation to prevent losing access to init data.
|
||||||
|
setRetainInstance(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init(
|
||||||
|
List<Tracks.Group> trackGroups,
|
||||||
|
boolean isDisabled,
|
||||||
|
Map<TrackGroup, TrackSelectionOverride> 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,
|
||||||
|
/* trackFormatComparator= */ null,
|
||||||
|
/* listener= */ this);
|
||||||
|
return rootView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTrackSelectionChanged(
|
||||||
|
boolean isDisabled, Map<TrackGroup, TrackSelectionOverride> overrides) {
|
||||||
|
this.isDisabled = isDisabled;
|
||||||
|
this.overrides = overrides;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class FragmentAdapter extends FragmentPagerAdapter {
|
||||||
|
|
||||||
|
public FragmentAdapter(FragmentManager fragmentManager) {
|
||||||
|
super(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2018 The Android Open Source Project
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<androidx.viewpager.widget.ViewPager
|
||||||
|
android:id="@+id/track_selection_dialog_view_pager"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1">
|
||||||
|
|
||||||
|
<com.google.android.material.tabs.TabLayout
|
||||||
|
android:id="@+id/track_selection_dialog_tab_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:tabGravity="fill"
|
||||||
|
app:tabMode="fixed" />
|
||||||
|
|
||||||
|
</androidx.viewpager.widget.ViewPager>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="end"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/track_selection_dialog_cancel_button"
|
||||||
|
style="?android:attr/borderlessButtonStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@android:string/cancel" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/track_selection_dialog_ok_button"
|
||||||
|
style="?android:attr/borderlessButtonStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@android:string/ok" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
|
@ -1962,4 +1962,8 @@
|
||||||
<string name="add_description">Add a description</string>
|
<string name="add_description">Add a description</string>
|
||||||
<string name="retrieve_remote_account">Retrieve remote account!</string>
|
<string name="retrieve_remote_account">Retrieve remote account!</string>
|
||||||
<string name="exit">Exit</string>
|
<string name="exit">Exit</string>
|
||||||
|
|
||||||
|
|
||||||
|
<string name="track_selection_title">Select tracks</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
|
@ -266,4 +266,6 @@
|
||||||
<item name="android:insetTop">0dp</item>
|
<item name="android:insetTop">0dp</item>
|
||||||
<item name="android:insetBottom">0dp</item>
|
<item name="android:insetBottom">0dp</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in a new issue