diff options
12 files changed, 153 insertions, 87 deletions
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java index 1fcc3512d..1eec762e9 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java @@ -17,6 +17,7 @@ import android.widget.TextView; import com.bumptech.glide.Glide; +import de.danoeh.antennapod.view.PlayButton; import org.apache.commons.lang3.StringUtils; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; @@ -72,7 +73,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements SeekBar sbPosition; private ImageButton butRev; private TextView txtvRev; - private ImageButton butPlay; + private PlayButton butPlay; private ImageButton butFF; private TextView txtvFF; private ImageButton butSkip; @@ -123,8 +124,8 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements } @Override - public ImageButton getPlayButton() { - return butPlay; + protected void updatePlayButtonShowsPlay(boolean showPlay) { + butPlay.setIsShowPlay(showPlay); } @Override @@ -513,6 +514,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements txtvRev.setText(NumberFormat.getInstance().format(UserPreferences.getRewindSecs())); } butPlay = findViewById(R.id.butPlay); + butPlay.setIsVideoScreen(true); butFF = findViewById(R.id.butFF); txtvFF = findViewById(R.id.txtvFF); if (txtvFF != null) { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java index 184febdc9..cd7a6b913 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java @@ -50,6 +50,7 @@ import de.danoeh.antennapod.dialog.VariableSpeedDialog; import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler; import de.danoeh.antennapod.view.ChapterSeekBar; import de.danoeh.antennapod.ui.common.PlaybackSpeedIndicatorView; +import de.danoeh.antennapod.view.PlayButton; import io.reactivex.Maybe; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; @@ -82,7 +83,7 @@ public class AudioPlayerFragment extends Fragment implements private ChapterSeekBar sbPosition; private ImageButton butRev; private TextView txtvRev; - private ImageButton butPlay; + private PlayButton butPlay; private ImageButton butFF; private TextView txtvFF; private ImageButton butSkip; @@ -381,8 +382,8 @@ public class AudioPlayerFragment extends Fragment implements } @Override - public ImageButton getPlayButton() { - return butPlay; + protected void updatePlayButtonShowsPlay(boolean showPlay) { + butPlay.setIsShowPlay(showPlay); } @Override diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java index d77935910..37f372383 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java @@ -6,7 +6,6 @@ import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ImageButton; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; @@ -24,6 +23,7 @@ import de.danoeh.antennapod.core.service.playback.PlaybackService; import de.danoeh.antennapod.core.service.playback.PlayerStatus; import de.danoeh.antennapod.core.util.playback.Playable; import de.danoeh.antennapod.core.util.playback.PlaybackController; +import de.danoeh.antennapod.view.PlayButton; import io.reactivex.Maybe; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; @@ -40,7 +40,7 @@ public class ExternalPlayerFragment extends Fragment { private ImageView imgvCover; private TextView txtvTitle; - private ImageButton butPlay; + private PlayButton butPlay; private TextView feedName; private ProgressBar progressBar; private PlaybackController controller; @@ -103,8 +103,8 @@ public class ExternalPlayerFragment extends Fragment { } @Override - public ImageButton getPlayButton() { - return butPlay; + protected void updatePlayButtonShowsPlay(boolean showPlay) { + butPlay.setIsShowPlay(showPlay); } @Override diff --git a/app/src/main/java/de/danoeh/antennapod/view/PlayButton.java b/app/src/main/java/de/danoeh/antennapod/view/PlayButton.java new file mode 100644 index 000000000..691a15ca2 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/view/PlayButton.java @@ -0,0 +1,54 @@ +package de.danoeh.antennapod.view; + +import android.content.Context; +import android.util.AttributeSet; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.AppCompatImageButton; +import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat; +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.ui.common.ThemeUtils; + +public class PlayButton extends AppCompatImageButton { + private boolean isShowPlay = true; + private boolean isVideoScreen = false; + + public PlayButton(@NonNull Context context) { + super(context); + } + + public PlayButton(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public PlayButton(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public void setIsVideoScreen(boolean isVideoScreen) { + this.isVideoScreen = isVideoScreen; + } + + public void setIsShowPlay(boolean showPlay) { + if (this.isShowPlay != showPlay) { + this.isShowPlay = showPlay; + setContentDescription(getContext().getString(showPlay ? R.string.play_label : R.string.pause_label)); + if (isVideoScreen) { + setImageResource(showPlay ? R.drawable.ic_av_play_white_80dp : R.drawable.ic_av_pause_white_80dp); + } else if (!isShown()) { + setImageResource(ThemeUtils.getDrawableFromAttr(getContext(), + showPlay ? R.attr.av_play : R.attr.av_pause)); + } else if (showPlay) { + AnimatedVectorDrawableCompat drawable = AnimatedVectorDrawableCompat.create( + getContext(), R.drawable.ic_animate_pause_play); + setImageDrawable(drawable); + drawable.start(); + } else { + AnimatedVectorDrawableCompat drawable = AnimatedVectorDrawableCompat.create( + getContext(), R.drawable.ic_animate_play_pause); + setImageDrawable(drawable); + drawable.start(); + } + } + } +} diff --git a/app/src/main/res/drawable/ic_animate_pause_play.xml b/app/src/main/res/drawable/ic_animate_pause_play.xml new file mode 100644 index 000000000..cc68279cd --- /dev/null +++ b/app/src/main/res/drawable/ic_animate_pause_play.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<animated-vector + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + xmlns:aapt="http://schemas.android.com/aapt" + android:drawable="@drawable/ic_animate_play" + tools:ignore="NewApi"> + <target android:name="path"> + <aapt:attr name="android:animation"> + <objectAnimator + android:duration="@integer/fragment_transition_duration" + android:propertyName="pathData" + android:valueFrom="@string/svg_animatable_pause" + android:valueTo="@string/svg_animatable_play" + android:valueType="pathType"/> + </aapt:attr> + </target> + <target android:name="group"> + <aapt:attr name="android:animation"> + <objectAnimator + android:duration="@integer/fragment_transition_duration" + android:propertyName="rotation" + android:valueFrom="-90" + android:valueTo="0"/> + </aapt:attr> + </target> +</animated-vector> diff --git a/app/src/main/res/drawable/ic_animate_play.xml b/app/src/main/res/drawable/ic_animate_play.xml new file mode 100644 index 000000000..3c0a5ef1d --- /dev/null +++ b/app/src/main/res/drawable/ic_animate_play.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8"?> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportHeight="24.0" + android:viewportWidth="24.0"> + <group android:name="group" + android:pivotX="12" + android:pivotY="12"> + <path android:name="path" + android:fillColor="?attr/action_icon_color" + android:pathData="@string/svg_animatable_play"/> + </group> +</vector> diff --git a/app/src/main/res/drawable/ic_animate_play_pause.xml b/app/src/main/res/drawable/ic_animate_play_pause.xml new file mode 100644 index 000000000..8e4f65b5e --- /dev/null +++ b/app/src/main/res/drawable/ic_animate_play_pause.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<animated-vector + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + xmlns:aapt="http://schemas.android.com/aapt" + android:drawable="@drawable/ic_animate_play" + tools:ignore="NewApi"> + <target android:name="path"> + <aapt:attr name="android:animation"> + <objectAnimator + android:duration="@integer/fragment_transition_duration" + android:propertyName="pathData" + android:valueFrom="@string/svg_animatable_play" + android:valueTo="@string/svg_animatable_pause" + android:valueType="pathType"/> + </aapt:attr> + </target> + <target android:name="group"> + <aapt:attr name="android:animation"> + <objectAnimator + android:duration="@integer/fragment_transition_duration" + android:propertyName="rotation" + android:valueFrom="0" + android:valueTo="90"/> + </aapt:attr> + </target> +</animated-vector> diff --git a/app/src/main/res/layout/audioplayer_fragment.xml b/app/src/main/res/layout/audioplayer_fragment.xml index d87fe85f0..3685032e6 100644 --- a/app/src/main/res/layout/audioplayer_fragment.xml +++ b/app/src/main/res/layout/audioplayer_fragment.xml @@ -140,7 +140,7 @@ android:layout_height="wrap_content" android:layout_marginBottom="24dp"> - <ImageButton + <de.danoeh.antennapod.view.PlayButton android:id="@+id/butPlay" android:layout_width="@dimen/audioplayer_playercontrols_length_big" android:layout_height="@dimen/audioplayer_playercontrols_length_big" diff --git a/app/src/main/res/layout/external_player_fragment.xml b/app/src/main/res/layout/external_player_fragment.xml index f36baec26..4f200162a 100644 --- a/app/src/main/res/layout/external_player_fragment.xml +++ b/app/src/main/res/layout/external_player_fragment.xml @@ -57,7 +57,7 @@ </LinearLayout> - <ImageButton + <de.danoeh.antennapod.view.PlayButton android:id="@+id/butPlay" android:layout_width="52dp" android:layout_height="match_parent" diff --git a/app/src/main/res/layout/videoplayer_activity.xml b/app/src/main/res/layout/videoplayer_activity.xml index e0632ef41..fc902602c 100644 --- a/app/src/main/res/layout/videoplayer_activity.xml +++ b/app/src/main/res/layout/videoplayer_activity.xml @@ -41,7 +41,7 @@ android:contentDescription="@string/rewind_label" app:srcCompat="@drawable/ic_av_fast_rewind_white_80dp" /> - <ImageButton + <de.danoeh.antennapod.view.PlayButton android:id="@+id/butPlay" android:layout_width="wrap_content" android:layout_height="wrap_content" diff --git a/app/src/main/res/values/svg.xml b/app/src/main/res/values/svg.xml new file mode 100644 index 000000000..6fd4ff0c4 --- /dev/null +++ b/app/src/main/res/values/svg.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="svg_animatable_play" translatable="false">M 8 5 L 8 12 L 19 12 L 19 12 M 8 19 L 8 12 L 19 12 L 19 12</string> + <string name="svg_animatable_pause" translatable="false">M 5 6 L 5 10 L 19 10 L 19 6 M 5 18 L 5 14 L 19 14 L 19 18</string> +</resources> diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java index 9e3f0058e..ac801e6da 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java @@ -7,7 +7,6 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; -import android.content.res.TypedArray; import android.media.MediaPlayer; import android.os.Build; import android.os.IBinder; @@ -15,7 +14,6 @@ import android.text.TextUtils; import android.util.Log; import android.util.Pair; import android.view.SurfaceHolder; -import android.widget.ImageButton; import androidx.annotation.NonNull; import de.danoeh.antennapod.core.R; import de.danoeh.antennapod.core.event.MessageEvent; @@ -28,12 +26,6 @@ import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.playback.PlaybackService; import de.danoeh.antennapod.core.service.playback.PlaybackServiceMediaPlayer; import de.danoeh.antennapod.core.service.playback.PlayerStatus; -import de.danoeh.antennapod.ui.common.ThemeUtils; -import io.reactivex.Maybe; -import io.reactivex.MaybeOnSubscribe; -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.disposables.Disposable; -import io.reactivex.schedulers.Schedulers; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; @@ -60,8 +52,6 @@ public abstract class PlaybackController { private boolean initialized = false; private boolean eventsRegistered = false; - private Disposable mediaLoader; - public PlaybackController(@NonNull Activity activity) { this.activity = activity; } @@ -77,7 +67,7 @@ public abstract class PlaybackController { if (PlaybackService.isRunning) { initServiceRunning(); } else { - initServiceNotRunning(); + updatePlayButtonShowsPlay(true); } } @@ -312,21 +302,6 @@ public abstract class PlaybackController { * should be used to update the GUI or start/cancel background threads. */ private void handleStatus() { - final int playResource; - final int pauseResource; - final CharSequence playText = activity.getString(R.string.play_label); - final CharSequence pauseText = activity.getString(R.string.pause_label); - - if (PlaybackService.getCurrentMediaType() == MediaType.AUDIO || PlaybackService.isCasting()) { - TypedArray res = activity.obtainStyledAttributes(new int[]{ R.attr.av_play, R.attr.av_pause}); - playResource = res.getResourceId(0, R.drawable.ic_av_play_black_48dp); - pauseResource = res.getResourceId(1, R.drawable.ic_av_pause_black_48dp); - res.recycle(); - } else { - playResource = R.drawable.ic_av_play_white_80dp; - pauseResource = R.drawable.ic_av_pause_white_80dp; - } - Log.d(TAG, "status: " + status.toString()); switch (status) { case ERROR: @@ -336,37 +311,31 @@ public abstract class PlaybackController { case PAUSED: checkMediaInfoLoaded(); onPositionObserverUpdate(); - updatePlayButtonAppearance(playResource, playText); - if (!PlaybackService.isCasting() && - PlaybackService.getCurrentMediaType() == MediaType.VIDEO) { + updatePlayButtonShowsPlay(true); + if (!PlaybackService.isCasting() && PlaybackService.getCurrentMediaType() == MediaType.VIDEO) { setScreenOn(false); } break; case PLAYING: checkMediaInfoLoaded(); - if (!PlaybackService.isCasting() && - PlaybackService.getCurrentMediaType() == MediaType.VIDEO) { + if (!PlaybackService.isCasting() && PlaybackService.getCurrentMediaType() == MediaType.VIDEO) { onAwaitingVideoSurface(); setScreenOn(true); } - updatePlayButtonAppearance(pauseResource, pauseText); + updatePlayButtonShowsPlay(false); break; case PREPARING: checkMediaInfoLoaded(); if (playbackService != null) { - if (playbackService.isStartWhenPrepared()) { - updatePlayButtonAppearance(pauseResource, pauseText); - } else { - updatePlayButtonAppearance(playResource, playText); - } + updatePlayButtonShowsPlay(!playbackService.isStartWhenPrepared()); } break; case STOPPED: - updatePlayButtonAppearance(playResource, playText); + updatePlayButtonShowsPlay(true); break; case PREPARED: checkMediaInfoLoaded(); - updatePlayButtonAppearance(playResource, playText); + updatePlayButtonShowsPlay(true); onPositionObserverUpdate(); break; case SEEKING: @@ -374,7 +343,7 @@ public abstract class PlaybackController { break; case INITIALIZED: checkMediaInfoLoaded(); - updatePlayButtonAppearance(playResource, playText); + updatePlayButtonShowsPlay(true); break; } } @@ -386,16 +355,8 @@ public abstract class PlaybackController { mediaInfoLoaded = true; } - private void updatePlayButtonAppearance(int resource, CharSequence contentDescription) { - ImageButton butPlay = getPlayButton(); - if(butPlay != null) { - butPlay.setImageResource(resource); - butPlay.setContentDescription(contentDescription); - } - } + protected void updatePlayButtonShowsPlay(boolean showPlay) { - public ImageButton getPlayButton() { - return null; } public abstract void loadMediaInfo(); @@ -662,29 +623,4 @@ public abstract class PlaybackController { public boolean isStreaming() { return playbackService != null && playbackService.isStreaming(); } - - private void initServiceNotRunning() { - if (getPlayButton() == null) { - return; - } - Log.v(TAG, "initServiceNotRunning()"); - mediaLoader = Maybe.create((MaybeOnSubscribe<Playable>) emitter -> { - Playable media = getMedia(); - if (media != null) { - emitter.onSuccess(media); - } else { - emitter.onComplete(); - } - }) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(media -> { - if (media.getMediaType() == MediaType.AUDIO) { - getPlayButton().setImageResource( - ThemeUtils.getDrawableFromAttr(activity, de.danoeh.antennapod.core.R.attr.av_play)); - } else { - getPlayButton().setImageResource(R.drawable.ic_av_play_white_80dp); - } - }, error -> Log.e(TAG, Log.getStackTraceString(error))); - } } |