add mute icon to the image viewer

appears then the webm track has audio and toggles it. keeps its muted
state as long as the image viewer is open.
also use the new api to disable pausing other playbacks when playing
a video.
refactor-toolbar
Floens 8 years ago
parent 4356eafc2f
commit fef2187ee0
  1. 26
      Clover/app/src/main/java/org/floens/chan/core/presenter/ImageViewerPresenter.java
  2. 6
      Clover/app/src/main/java/org/floens/chan/ui/adapter/ImageViewerAdapter.java
  3. 29
      Clover/app/src/main/java/org/floens/chan/ui/controller/ImageViewerController.java
  4. 67
      Clover/app/src/main/java/org/floens/chan/ui/view/MultiImageView.java
  5. BIN
      Clover/app/src/main/res/drawable-hdpi/ic_volume_off_white_24dp.png
  6. BIN
      Clover/app/src/main/res/drawable-hdpi/ic_volume_up_white_24dp.png
  7. BIN
      Clover/app/src/main/res/drawable-mdpi/ic_volume_off_white_24dp.png
  8. BIN
      Clover/app/src/main/res/drawable-mdpi/ic_volume_up_white_24dp.png
  9. BIN
      Clover/app/src/main/res/drawable-xhdpi/ic_volume_off_white_24dp.png
  10. BIN
      Clover/app/src/main/res/drawable-xhdpi/ic_volume_up_white_24dp.png
  11. BIN
      Clover/app/src/main/res/drawable-xxhdpi/ic_volume_off_white_24dp.png
  12. BIN
      Clover/app/src/main/res/drawable-xxhdpi/ic_volume_up_white_24dp.png
  13. BIN
      Clover/app/src/main/res/drawable-xxxhdpi/ic_volume_off_white_24dp.png
  14. BIN
      Clover/app/src/main/res/drawable-xxxhdpi/ic_volume_up_white_24dp.png

@ -54,6 +54,8 @@ public class ImageViewerPresenter implements MultiImageView.Callback, ViewPager.
private boolean viewPagerVisible = false;
private boolean changeViewsOnInTransitionEnd = false;
private boolean muted = true;
public ImageViewerPresenter(Callback callback) {
this.callback = callback;
inject(this);
@ -106,6 +108,12 @@ public class ImageViewerPresenter implements MultiImageView.Callback, ViewPager.
callback.showProgress(false);
}
public void onVolumeClicked() {
muted = !muted;
callback.showVolumeMenuItem(true, muted);
callback.setVolume(getCurrentPostImage(), muted);
}
public List<PostImage> getAllPostImages() {
return images;
}
@ -188,6 +196,9 @@ public class ImageViewerPresenter implements MultiImageView.Callback, ViewPager.
callback.showProgress(progress.get(selectedPosition) >= 0f);
callback.onLoadProgress(progress.get(selectedPosition));
// If it has audio, we'll know after it is loaded.
callback.showVolumeMenuItem(false, true);
}
// Called from either a page swipe caused a lowres image to the center or an
@ -307,6 +318,17 @@ public class ImageViewerPresenter implements MultiImageView.Callback, ViewPager.
callback.onVideoError(multiImageView);
}
@Override
public void onVideoLoaded(MultiImageView multiImageView, boolean hasAudio) {
PostImage currentPostImage = getCurrentPostImage();
if (multiImageView.getPostImage() == currentPostImage) {
if (hasAudio) {
callback.showVolumeMenuItem(true, muted);
callback.setVolume(currentPostImage, muted);
}
}
}
private boolean imageAutoLoad(PostImage postImage) {
// Auto load the image when it is cached
return fileCache.exists(postImage.imageUrl.toString()) || shouldLoadForNetworkType(ChanSettings.imageAutoLoadNetwork.get());
@ -361,6 +383,8 @@ public class ImageViewerPresenter implements MultiImageView.Callback, ViewPager.
void setImageMode(PostImage postImage, MultiImageView.Mode mode);
void setVolume(PostImage postImage, boolean muted);
void setTitle(PostImage postImage, int index, int count, boolean spoiler);
void scrollToImage(PostImage postImage);
@ -372,5 +396,7 @@ public class ImageViewerPresenter implements MultiImageView.Callback, ViewPager.
void onLoadProgress(float progress);
void onVideoError(MultiImageView multiImageView);
void showVolumeMenuItem(boolean show, boolean muted);
}
}

@ -91,6 +91,12 @@ public class ImageViewerAdapter extends ViewPagerAdapter {
}
}
public void setVolume(PostImage postImage, boolean muted) {
// It must be loaded, or the user is not able to click the menu item.
MultiImageView view = find(postImage);
view.setVolume(muted);
}
public MultiImageView.Mode getMode(PostImage postImage) {
MultiImageView view = find(postImage);
if (view == null) {

@ -39,6 +39,7 @@ import android.view.Window;
import android.view.WindowManager;
import android.view.animation.DecelerateInterpolator;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.Toast;
import com.android.volley.VolleyError;
@ -85,6 +86,7 @@ public class ImageViewerController extends Controller implements ImageViewerPres
private static final float TRANSITION_FINAL_ALPHA = 0.85f;
private static final int GO_POST_ID = 1;
private static final int VOLUME_ID = 3;
private static final int SAVE_ID = 2;
private static final int OPEN_BROWSER_ID = 103;
private static final int SHARE_ID = 104;
@ -108,6 +110,7 @@ public class ImageViewerController extends Controller implements ImageViewerPres
private LoadingBar loadingBar;
private ToolbarMenuItem overflowMenuItem;
private ToolbarMenuItem volumeMenuItem;
public ImageViewerController(Context context, Toolbar toolbar) {
super(context);
@ -129,6 +132,9 @@ public class ImageViewerController extends Controller implements ImageViewerPres
if (goPostCallback != null) {
navigation.menu.addItem(new ToolbarMenuItem(context, this, GO_POST_ID, R.drawable.ic_subdirectory_arrow_left_white_24dp));
}
volumeMenuItem = navigation.menu.addItem(new ToolbarMenuItem(context,
this, VOLUME_ID, R.drawable.ic_volume_off_white_24dp));
navigation.menu.addItem(new ToolbarMenuItem(context, this, SAVE_ID, R.drawable.ic_file_download_white_24dp));
List<FloatingMenuItem> items = new ArrayList<>();
@ -144,17 +150,16 @@ public class ImageViewerController extends Controller implements ImageViewerPres
pager.addOnPageChangeListener(presenter);
loadingBar = view.findViewById(R.id.loading_bar);
showVolumeMenuItem(false, true);
// Sanity check
if (parentController.view.getWindowToken() == null) {
throw new IllegalArgumentException("parentController.view not attached");
}
AndroidUtils.waitForLayout(parentController.view.getViewTreeObserver(), view, new AndroidUtils.OnMeasuredCallback() {
@Override
public boolean onMeasured(View view) {
AndroidUtils.waitForLayout(parentController.view.getViewTreeObserver(), view, view -> {
presenter.onViewMeasured();
return true;
}
});
}
@ -189,6 +194,9 @@ public class ImageViewerController extends Controller implements ImageViewerPres
case SAVE_ID:
saveShare(false, presenter.getCurrentPostImage());
break;
case VOLUME_ID:
presenter.onVolumeClicked();
break;
}
}
@ -285,6 +293,11 @@ public class ImageViewerController extends Controller implements ImageViewerPres
((ImageViewerAdapter) pager.getAdapter()).setMode(postImage, mode);
}
@Override
public void setVolume(PostImage postImage, boolean muted) {
((ImageViewerAdapter) pager.getAdapter()).setVolume(postImage, muted);
}
public MultiImageView.Mode getImageMode(PostImage postImage) {
return ((ImageViewerAdapter) pager.getAdapter()).getMode(postImage);
}
@ -335,6 +348,14 @@ public class ImageViewerController extends Controller implements ImageViewerPres
}
}
@Override
public void showVolumeMenuItem(boolean show, boolean muted) {
ImageView view = volumeMenuItem.getView();
view.setVisibility(show ? View.VISIBLE : View.GONE);
view.setImageResource(muted ?
R.drawable.ic_volume_off_white_24dp : R.drawable.ic_volume_up_white_24dp);
}
public void startPreviewInTransition(PostImage postImage) {
ThumbnailView startImageView = getTransitionImageView(postImage);

@ -20,8 +20,10 @@ package org.floens.chan.ui.view;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Build;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
@ -81,23 +83,19 @@ public class MultiImageView extends FrameLayout implements View.OnClickListener
private VideoView videoView;
private boolean videoError = false;
private MediaPlayer mediaPlayer;
public MultiImageView(Context context) {
super(context);
init();
this(context, null);
}
public MultiImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
this(context, attrs, 0);
}
public MultiImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public MultiImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
private void init() {
inject(this);
setOnClickListener(this);
@ -165,6 +163,13 @@ public class MultiImageView extends FrameLayout implements View.OnClickListener
return bigImage;
}
public void setVolume(boolean muted) {
if (mediaPlayer != null) {
final float volume = muted ? 0f : 1f;
mediaPlayer.setVolume(volume, volume);
}
}
@Override
public void onClick(View v) {
callback.onTap(this);
@ -374,23 +379,24 @@ public class MultiImageView extends FrameLayout implements View.OnClickListener
videoView.setZOrderOnTop(true);
videoView.setMediaController(new MediaController(getContext()));
addView(videoView, 0, new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, Gravity.CENTER));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
videoView.setAudioFocusRequest(AudioManager.AUDIOFOCUS_NONE);
}
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
addView(videoView, 0, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, Gravity.CENTER));
videoView.setOnPreparedListener(mp -> {
mediaPlayer = mp;
mp.setLooping(true);
mp.setVolume(0f, 0f);
onModeLoaded(Mode.MOVIE, videoView);
}
callback.onVideoLoaded(this, hasMediaPlayerAudioTracks(mp));
});
videoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
videoView.setOnErrorListener((mp, what, extra) -> {
onVideoError();
return true;
}
});
videoView.setVideoPath(file.getAbsolutePath());
@ -404,6 +410,21 @@ public class MultiImageView extends FrameLayout implements View.OnClickListener
}
}
private boolean hasMediaPlayerAudioTracks(MediaPlayer mediaPlayer) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
for (MediaPlayer.TrackInfo trackInfo : mediaPlayer.getTrackInfo()) {
if (trackInfo.getTrackType() == MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_AUDIO) {
return true;
}
}
return false;
} else {
// It'll just show the icon without doing anything. Remove when 4.0 is dropped.
return true;
}
}
private void onVideoError() {
if (!videoError) {
videoError = true;
@ -411,6 +432,11 @@ public class MultiImageView extends FrameLayout implements View.OnClickListener
}
}
private void cleanupVideo(VideoView videoView) {
videoView.stopPlayback();
mediaPlayer = null;
}
private void setBitImageFileInternal(File file, boolean tiling, final Mode forMode) {
final CustomScaleImageView image = new CustomScaleImageView(getContext());
image.setImage(ImageSource.uri(file.getAbsolutePath()).tiling(tiling));
@ -482,8 +508,7 @@ public class MultiImageView extends FrameLayout implements View.OnClickListener
if (child != playView) {
if (child != view) {
if (child instanceof VideoView) {
VideoView item = (VideoView) child;
item.stopPlayback();
cleanupVideo((VideoView) child);
}
removeViewAt(i);
@ -511,6 +536,8 @@ public class MultiImageView extends FrameLayout implements View.OnClickListener
void onVideoError(MultiImageView multiImageView);
void onVideoLoaded(MultiImageView multiImageView, boolean hasAudio);
void onModeLoaded(MultiImageView multiImageView, Mode mode);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 433 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 532 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 455 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 753 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 654 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1005 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 878 B

Loading…
Cancel
Save