From 17b9579dfea12b9b6289982e3fd4251ecf12b86d Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Wed, 20 May 2020 12:20:24 +0200 Subject: New playback speed dialog --- .../antennapod/dialog/PlaybackControlsDialog.java | 85 +-------- .../antennapod/dialog/VariableSpeedDialog.java | 196 ++++++++++++++------- 2 files changed, 144 insertions(+), 137 deletions(-) (limited to 'app/src/main/java/de/danoeh/antennapod/dialog') diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/PlaybackControlsDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/PlaybackControlsDialog.java index d1ffdc148..e45533826 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/PlaybackControlsDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/PlaybackControlsDialog.java @@ -11,27 +11,21 @@ import android.widget.Button; import android.widget.CheckBox; import android.widget.SeekBar; import android.widget.TextView; -import de.danoeh.antennapod.core.preferences.PlaybackPreferences; import de.danoeh.antennapod.R; -import de.danoeh.antennapod.core.feed.util.PlaybackSpeedUtils; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.util.Converter; -import de.danoeh.antennapod.core.util.playback.Playable; import de.danoeh.antennapod.core.util.playback.PlaybackController; +import de.danoeh.antennapod.view.PlaybackSpeedSeekBar; import java.util.List; import java.util.Locale; public class PlaybackControlsDialog extends DialogFragment { - private static final String ARGUMENT_IS_PLAYING_VIDEO = "isPlayingVideo"; - private PlaybackController controller; private AlertDialog dialog; - private boolean isPlayingVideo; - public static PlaybackControlsDialog newInstance(boolean isPlayingVideo) { + public static PlaybackControlsDialog newInstance() { Bundle arguments = new Bundle(); - arguments.putBoolean(ARGUMENT_IS_PLAYING_VIDEO, isPlayingVideo); PlaybackControlsDialog dialog = new PlaybackControlsDialog(); dialog.setArguments(arguments); return dialog; @@ -65,8 +59,6 @@ public class PlaybackControlsDialog extends DialogFragment { @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { - isPlayingVideo = getArguments() != null && getArguments().getBoolean(ARGUMENT_IS_PLAYING_VIDEO); - dialog = new AlertDialog.Builder(getContext()) .setTitle(R.string.audio_controls) .setView(R.layout.audio_controls) @@ -79,68 +71,18 @@ public class PlaybackControlsDialog extends DialogFragment { } private void setupUi() { - final SeekBar barPlaybackSpeed = dialog.findViewById(R.id.playback_speed); - final TextView butDecSpeed = dialog.findViewById(R.id.butDecSpeed); - butDecSpeed.setOnClickListener(v -> { - if (controller != null && controller.canSetPlaybackSpeed()) { - barPlaybackSpeed.setProgress(barPlaybackSpeed.getProgress() - 2); - } else { - VariableSpeedDialog.showGetPluginDialog(getContext()); - } - }); - final TextView butIncSpeed = dialog.findViewById(R.id.butIncSpeed); - butIncSpeed.setOnClickListener(v -> { - if (controller != null && controller.canSetPlaybackSpeed()) { - barPlaybackSpeed.setProgress(barPlaybackSpeed.getProgress() + 2); - } else { - VariableSpeedDialog.showGetPluginDialog(getContext()); - } - }); - final TextView txtvPlaybackSpeed = dialog.findViewById(R.id.txtvPlaybackSpeed); - float currentSpeed = getCurrentSpeed(); - txtvPlaybackSpeed.setText(String.format(Locale.getDefault(), "%.2fx", currentSpeed)); - barPlaybackSpeed.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - if (controller != null && controller.canSetPlaybackSpeed()) { - float playbackSpeed = (progress + 10) / 20.0f; - controller.setPlaybackSpeed(playbackSpeed); - - PlaybackPreferences.setCurrentlyPlayingTemporaryPlaybackSpeed(playbackSpeed); - if (isPlayingVideo) { - UserPreferences.setVideoPlaybackSpeed(playbackSpeed); - } else { - UserPreferences.setPlaybackSpeed(playbackSpeed); - } - - String speedStr = String.format(Locale.getDefault(), "%.2fx", playbackSpeed); - txtvPlaybackSpeed.setText(speedStr); - } else if (fromUser) { - float speed = getCurrentSpeed(); - barPlaybackSpeed.post(() -> barPlaybackSpeed.setProgress(Math.round((20 * speed) - 10))); - } - } + PlaybackSpeedSeekBar speedSeekBar = dialog.findViewById(R.id.speed_seek_bar); + speedSeekBar.setController(controller); + speedSeekBar.setProgressChangedListener(speed + -> txtvPlaybackSpeed.setText(String.format(Locale.getDefault(), "%.2fx", speed))); - @Override - public void onStartTrackingTouch(SeekBar seekBar) { - if (controller != null && !controller.canSetPlaybackSpeed()) { - VariableSpeedDialog.showGetPluginDialog(getContext()); - } - } - - @Override - public void onStopTrackingTouch(SeekBar seekBar) { - } - }); - barPlaybackSpeed.setProgress(Math.round((20 * currentSpeed) - 10)); - - final SeekBar barLeftVolume = (SeekBar) dialog.findViewById(R.id.volume_left); + final SeekBar barLeftVolume = dialog.findViewById(R.id.volume_left); barLeftVolume.setProgress(UserPreferences.getLeftVolumePercentage()); - final SeekBar barRightVolume = (SeekBar) dialog.findViewById(R.id.volume_right); + final SeekBar barRightVolume = dialog.findViewById(R.id.volume_right); barRightVolume.setProgress(UserPreferences.getRightVolumePercentage()); - final CheckBox stereoToMono = (CheckBox) dialog.findViewById(R.id.stereo_to_mono); + final CheckBox stereoToMono = dialog.findViewById(R.id.stereo_to_mono); stereoToMono.setChecked(UserPreferences.stereoToMono()); if (controller != null && !controller.canDownmix()) { stereoToMono.setEnabled(false); @@ -220,13 +162,4 @@ public class PlaybackControlsDialog extends DialogFragment { new Handler().postDelayed(this::setupAudioTracks, 500); }); } - - private float getCurrentSpeed() { - Playable media = null; - if (controller != null) { - media = controller.getMedia(); - } - - return PlaybackSpeedUtils.getCurrentPlaybackSpeed(media); - } } diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java index 3a6ba183f..ef8ed335d 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java @@ -1,97 +1,171 @@ package de.danoeh.antennapod.dialog; +import android.app.Dialog; import android.content.Context; -import android.os.Build; +import android.os.Bundle; +import android.view.View; +import android.view.ViewGroup; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; +import androidx.fragment.app.DialogFragment; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import com.google.android.material.chip.Chip; +import com.google.android.material.snackbar.Snackbar; import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.preferences.UserPreferences; +import de.danoeh.antennapod.core.util.playback.PlaybackController; +import de.danoeh.antennapod.view.ItemOffsetDecoration; +import de.danoeh.antennapod.view.PlaybackSpeedSeekBar; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Locale; -public class VariableSpeedDialog { +public class VariableSpeedDialog extends DialogFragment { + private SpeedSelectionAdapter adapter; + private final DecimalFormat speedFormat; + private PlaybackController controller; + private final List selectedSpeeds; + private PlaybackSpeedSeekBar speedSeekBar; + private Chip addCurrentSpeedChip; - private VariableSpeedDialog() { - } - - public static void showDialog(final Context context) { - if (UserPreferences.useSonic() - || UserPreferences.useExoplayer() - || Build.VERSION.SDK_INT >= 23) { - showSpeedSelectorDialog(context); - } else { - showGetPluginDialog(context, true); - } + public VariableSpeedDialog() { + DecimalFormatSymbols format = new DecimalFormatSymbols(Locale.US); + format.setDecimalSeparator('.'); + speedFormat = new DecimalFormat("0.00", format); + selectedSpeeds = new ArrayList<>(UserPreferences.getPlaybackSpeedArray()); } public static void showGetPluginDialog(final Context context) { - showGetPluginDialog(context, false); - } - - private static void showGetPluginDialog(final Context context, boolean showSpeedSelector) { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.no_playback_plugin_title); builder.setMessage(R.string.no_playback_plugin_or_sonic_msg); builder.setPositiveButton(R.string.enable_sonic, (dialog, which) -> { UserPreferences.enableSonic(); - if (showSpeedSelector) { - showSpeedSelectorDialog(context); - } }); builder.setNeutralButton(R.string.close_label, null); builder.show(); } - private static void showSpeedSelectorDialog(final Context context) { - DecimalFormatSymbols format = new DecimalFormatSymbols(Locale.US); - format.setDecimalSeparator('.'); - DecimalFormat speedFormat = new DecimalFormat("0.00", format); - - final String[] speedValues = context.getResources().getStringArray( - R.array.playback_speed_values); - // According to Java spec these get initialized to false on creation - final boolean[] speedChecked = new boolean[speedValues.length]; - - // Build the "isChecked" array so that multiChoice dialog is populated correctly - List selectedSpeedList = new ArrayList<>(); - float[] selectedSpeeds = UserPreferences.getPlaybackSpeedArray(); - for (float speed : selectedSpeeds) { - selectedSpeedList.add(speedFormat.format(speed)); + @Override + public void onStart() { + super.onStart(); + controller = new PlaybackController(getActivity()) { + @Override + public void setupGUI() { + updateSpeed(); + } + + @Override + public void onPlaybackSpeedChange() { + updateSpeed(); + } + }; + controller.init(); + speedSeekBar.setController(controller); + } + + private void updateSpeed() { + speedSeekBar.updateSpeed(); + addCurrentSpeedChip.setText(speedFormat.format(controller.getCurrentPlaybackSpeedMultiplier())); + } + + @Override + public void onStop() { + super.onStop(); + controller.release(); + controller = null; + } + + @NonNull + @Override + public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); + builder.setPositiveButton(R.string.close_label, null); + + View root = View.inflate(getContext(), R.layout.speed_select_dialog, null); + speedSeekBar = root.findViewById(R.id.speed_seek_bar); + RecyclerView selectedSpeedsGrid = root.findViewById(R.id.selected_speeds_grid); + selectedSpeedsGrid.setLayoutManager(new GridLayoutManager(getContext(), 3)); + selectedSpeedsGrid.addItemDecoration(new ItemOffsetDecoration(getContext(), 4)); + adapter = new SpeedSelectionAdapter(); + adapter.setHasStableIds(true); + selectedSpeedsGrid.setAdapter(adapter); + + addCurrentSpeedChip = root.findViewById(R.id.add_current_speed_chip); + addCurrentSpeedChip.setCloseIconVisible(true); + addCurrentSpeedChip.setCloseIconResource(R.drawable.ic_add_black); + addCurrentSpeedChip.setOnCloseIconClickListener(v -> addCurrentSpeed()); + addCurrentSpeedChip.setOnClickListener(v -> addCurrentSpeed()); + + builder.setView(root); + return builder.create(); + } + + private void addCurrentSpeed() { + float newSpeed = controller.getCurrentPlaybackSpeedMultiplier(); + if (selectedSpeeds.contains(newSpeed)) { + Snackbar.make(addCurrentSpeedChip, + getString(R.string.preset_already_exists, newSpeed), Snackbar.LENGTH_LONG).show(); + } else { + selectedSpeeds.add(newSpeed); + Collections.sort(selectedSpeeds); + UserPreferences.setPlaybackSpeedArray(selectedSpeeds); + adapter.notifyDataSetChanged(); } + } - for (int i = 0; i < speedValues.length; i++) { - speedChecked[i] = selectedSpeedList.contains(speedValues[i]); + public class SpeedSelectionAdapter extends RecyclerView.Adapter { + + @Override + @NonNull + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + Chip chip = new Chip(getContext()); + chip.setCloseIconVisible(true); + chip.setCloseIconResource(R.drawable.ic_delete_black); + return new ViewHolder(chip); } - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(R.string.set_playback_speed_label); - builder.setMultiChoiceItems(R.array.playback_speed_values, - speedChecked, (dialog, which, isChecked) -> speedChecked[which] = isChecked); - builder.setNegativeButton(android.R.string.cancel, null); - builder.setPositiveButton(android.R.string.ok, - (dialog, which) -> { - int choiceCount = 0; - for (boolean checked : speedChecked) { - if (checked) { - choiceCount++; - } - } - String[] newSpeedValues = new String[choiceCount]; - int newSpeedIndex = 0; - for (int i = 0; i < speedChecked.length; i++) { - if (speedChecked[i]) { - newSpeedValues[newSpeedIndex++] = speedValues[i]; - } + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, int position) { + float speed = selectedSpeeds.get(position); + + holder.chip.setText(speedFormat.format(speed)); + holder.chip.setOnCloseIconClickListener(v -> { + selectedSpeeds.remove(speed); + UserPreferences.setPlaybackSpeedArray(selectedSpeeds); + notifyDataSetChanged(); + }); + holder.chip.setOnClickListener(v -> { + if (controller != null) { + controller.setPlaybackSpeed(speed); + notifyDataSetChanged(); } + }); + } - UserPreferences.setPlaybackSpeedArray(newSpeedValues); + @Override + public int getItemCount() { + return selectedSpeeds.size(); + } - }); - builder.create().show(); - } + @Override + public long getItemId(int position) { + return selectedSpeeds.get(position).hashCode(); + } + + public class ViewHolder extends RecyclerView.ViewHolder { + Chip chip; + ViewHolder(Chip itemView) { + super(itemView); + chip = itemView; + } + } + } } -- cgit v1.2.3