Add fullscreen mode to post view

This commit is contained in:
Ammar Githam 2021-05-09 02:14:36 +09:00
parent 3dde61d91a
commit 5744a1a687
11 changed files with 434 additions and 554 deletions

View File

@ -1,11 +1,17 @@
package awais.instagrabber.adapters;
import android.view.View;
import com.google.android.exoplayer2.ui.StyledPlayerView;
import awais.instagrabber.repositories.responses.Media;
public class SliderCallbackAdapter implements SliderItemsAdapter.SliderCallback {
@Override
public void onThumbnailLoaded(final int position) {}
@Override
public void onItemClicked(final int position) {}
public void onItemClicked(final int position, final Media media, final View view) {}
@Override
public void onPlayerPlay(final int position) {}
@ -15,4 +21,12 @@ public class SliderCallbackAdapter implements SliderItemsAdapter.SliderCallback
@Override
public void onPlayerRelease(final int position) {}
@Override
public void onFullScreenModeChanged(final boolean isFullScreen, final StyledPlayerView playerView) {}
@Override
public boolean isInFullScreen() {
return false;
}
}

View File

@ -1,16 +1,18 @@
package awais.instagrabber.adapters;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.ListAdapter;
import com.google.android.exoplayer2.ui.StyledPlayerView;
import awais.instagrabber.adapters.viewholder.SliderItemViewHolder;
import awais.instagrabber.adapters.viewholder.SliderPhotoViewHolder;
import awais.instagrabber.adapters.viewholder.SliderVideoViewHolder;
import awais.instagrabber.customviews.VerticalDragHelper;
import awais.instagrabber.databinding.ItemSliderPhotoBinding;
import awais.instagrabber.databinding.LayoutVideoPlayerWithThumbnailBinding;
import awais.instagrabber.models.enums.MediaItemType;
@ -18,10 +20,8 @@ import awais.instagrabber.repositories.responses.Media;
public final class SliderItemsAdapter extends ListAdapter<Media, SliderItemViewHolder> {
private final VerticalDragHelper.OnVerticalDragListener onVerticalDragListener;
private final boolean loadVideoOnItemClick;
private final SliderCallback sliderCallback;
// private final LayoutExoCustomControlsBinding controlsBinding;
private static final DiffUtil.ItemCallback<Media> DIFF_CALLBACK = new DiffUtil.ItemCallback<Media>() {
@Override
@ -35,15 +35,11 @@ public final class SliderItemsAdapter extends ListAdapter<Media, SliderItemViewH
}
};
public SliderItemsAdapter(final VerticalDragHelper.OnVerticalDragListener onVerticalDragListener,
// final LayoutExoCustomControlsBinding controlsBinding,
final boolean loadVideoOnItemClick,
public SliderItemsAdapter(final boolean loadVideoOnItemClick,
final SliderCallback sliderCallback) {
super(DIFF_CALLBACK);
this.onVerticalDragListener = onVerticalDragListener;
this.loadVideoOnItemClick = loadVideoOnItemClick;
this.sliderCallback = sliderCallback;
// this.controlsBinding = controlsBinding;
}
@NonNull
@ -54,12 +50,12 @@ public final class SliderItemsAdapter extends ListAdapter<Media, SliderItemViewH
switch (mediaItemType) {
case MEDIA_TYPE_VIDEO: {
final LayoutVideoPlayerWithThumbnailBinding binding = LayoutVideoPlayerWithThumbnailBinding.inflate(inflater, parent, false);
return new SliderVideoViewHolder(binding, onVerticalDragListener, loadVideoOnItemClick);
return new SliderVideoViewHolder(binding, loadVideoOnItemClick);
}
case MEDIA_TYPE_IMAGE:
default:
final ItemSliderPhotoBinding binding = ItemSliderPhotoBinding.inflate(inflater, parent, false);
return new SliderPhotoViewHolder(binding, onVerticalDragListener);
return new SliderPhotoViewHolder(binding);
}
}
@ -142,12 +138,16 @@ public final class SliderItemsAdapter extends ListAdapter<Media, SliderItemViewH
public interface SliderCallback {
void onThumbnailLoaded(int position);
void onItemClicked(int position);
void onItemClicked(int position, final Media media, final View view);
void onPlayerPlay(int position);
void onPlayerPause(int position);
void onPlayerRelease(int position);
void onFullScreenModeChanged(boolean isFullScreen, final StyledPlayerView playerView);
boolean isInFullScreen();
}
}

View File

@ -2,7 +2,6 @@ package awais.instagrabber.adapters.viewholder;
import android.graphics.drawable.Animatable;
import android.net.Uri;
import android.view.GestureDetector;
import android.view.MotionEvent;
import androidx.annotation.NonNull;
@ -14,8 +13,8 @@ import com.facebook.imagepipeline.request.ImageRequest;
import com.facebook.imagepipeline.request.ImageRequestBuilder;
import awais.instagrabber.adapters.SliderItemsAdapter;
import awais.instagrabber.customviews.VerticalDragHelper;
import awais.instagrabber.customviews.drawee.AnimatedZoomableController;
import awais.instagrabber.customviews.drawee.DoubleTapGestureListener;
import awais.instagrabber.databinding.ItemSliderPhotoBinding;
import awais.instagrabber.repositories.responses.Media;
import awais.instagrabber.utils.ResponseBodyUtils;
@ -24,13 +23,10 @@ public class SliderPhotoViewHolder extends SliderItemViewHolder {
private static final String TAG = "FeedSliderPhotoViewHolder";
private final ItemSliderPhotoBinding binding;
private final VerticalDragHelper.OnVerticalDragListener onVerticalDragListener;
public SliderPhotoViewHolder(@NonNull final ItemSliderPhotoBinding binding,
final VerticalDragHelper.OnVerticalDragListener onVerticalDragListener) {
public SliderPhotoViewHolder(@NonNull final ItemSliderPhotoBinding binding) {
super(binding.getRoot());
this.binding = binding;
this.onVerticalDragListener = onVerticalDragListener;
}
public void bind(@NonNull final Media model,
@ -62,74 +58,19 @@ public class SliderPhotoViewHolder extends SliderItemViewHolder {
})
.setLowResImageRequest(ImageRequest.fromUri(ResponseBodyUtils.getThumbUrl(model)))
.build());
// binding.getRoot().setOnClickListener(v -> {
// if (sliderCallback != null) {
// sliderCallback.onItemClicked(position);
// }
// });
binding.getRoot().setTapListener(new GestureDetector.SimpleOnGestureListener() {
final DoubleTapGestureListener tapListener = new DoubleTapGestureListener(binding.getRoot()) {
@Override
public boolean onSingleTapUp(final MotionEvent e) {
public boolean onSingleTapConfirmed(final MotionEvent e) {
if (sliderCallback != null) {
sliderCallback.onItemClicked(position);
return true;
sliderCallback.onItemClicked(position, model, binding.getRoot());
}
return false;
return super.onSingleTapConfirmed(e);
}
});
};
binding.getRoot().setTapListener(tapListener);
final AnimatedZoomableController zoomableController = AnimatedZoomableController.newInstance();
zoomableController.setMaxScaleFactor(3f);
binding.getRoot().setZoomableController(zoomableController);
if (onVerticalDragListener != null) {
binding.getRoot().setOnVerticalDragListener(onVerticalDragListener);
}
binding.getRoot().setZoomingEnabled(true);
}
// private void setDimensions(final FeedModel feedModel, final int spanCount, final boolean animate) {
// final ViewGroup.LayoutParams layoutParams = binding.imageViewer.getLayoutParams();
// final int deviceWidth = Utils.displayMetrics.widthPixels;
// final int spanWidth = deviceWidth / spanCount;
// final int spanHeight = NumberUtils.getResultingHeight(spanWidth, feedModel.getImageHeight(), feedModel.getImageWidth());
// final int width = spanWidth == 0 ? deviceWidth : spanWidth;
// final int height = spanHeight == 0 ? deviceWidth + 1 : spanHeight;
// if (animate) {
// Animation animation = AnimationUtils.expand(
// binding.imageViewer,
// layoutParams.width,
// layoutParams.height,
// width,
// height,
// new Animation.AnimationListener() {
// @Override
// public void onAnimationStart(final Animation animation) {
// showOrHideDetails(spanCount);
// }
//
// @Override
// public void onAnimationEnd(final Animation animation) {
// // showOrHideDetails(spanCount);
// }
//
// @Override
// public void onAnimationRepeat(final Animation animation) {
//
// }
// });
// binding.imageViewer.startAnimation(animation);
// } else {
// layoutParams.width = width;
// layoutParams.height = height;
// binding.imageViewer.requestLayout();
// }
// }
//
// private void showOrHideDetails(final int spanCount) {
// if (spanCount == 1) {
// binding.itemFeedTop.getRoot().setVisibility(View.VISIBLE);
// binding.itemFeedBottom.getRoot().setVisibility(View.VISIBLE);
// } else {
// binding.itemFeedTop.getRoot().setVisibility(View.GONE);
// binding.itemFeedBottom.getRoot().setVisibility(View.GONE);
// }
// }
}

View File

@ -7,10 +7,11 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull;
import com.google.android.exoplayer2.ui.StyledPlayerView;
import java.util.List;
import awais.instagrabber.adapters.SliderItemsAdapter;
import awais.instagrabber.customviews.VerticalDragHelper;
import awais.instagrabber.customviews.VideoPlayerCallbackAdapter;
import awais.instagrabber.customviews.VideoPlayerViewHelper;
import awais.instagrabber.databinding.LayoutVideoPlayerWithThumbnailBinding;
@ -27,40 +28,23 @@ public class SliderVideoViewHolder extends SliderItemViewHolder {
private static final String TAG = "SliderVideoViewHolder";
private final LayoutVideoPlayerWithThumbnailBinding binding;
// private final LayoutExoCustomControlsBinding controlsBinding;
private final boolean loadVideoOnItemClick;
private final GestureDetector.OnGestureListener videoPlayerViewGestureListener = new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapConfirmed(final MotionEvent e) {
binding.playerView.performClick();
return true;
}
};
private VideoPlayerViewHelper videoPlayerViewHelper;
@SuppressLint("ClickableViewAccessibility")
public SliderVideoViewHolder(@NonNull final LayoutVideoPlayerWithThumbnailBinding binding,
final VerticalDragHelper.OnVerticalDragListener onVerticalDragListener,
// final LayoutExoCustomControlsBinding controlsBinding,
final boolean loadVideoOnItemClick) {
super(binding.getRoot());
this.binding = binding;
// this.controlsBinding = controlsBinding;
this.loadVideoOnItemClick = loadVideoOnItemClick;
// if (onVerticalDragListener != null) {
// final VerticalDragHelper thumbnailVerticalDragHelper = new VerticalDragHelper(binding.thumbnailParent);
// final VerticalDragHelper playerVerticalDragHelper = new VerticalDragHelper(binding.playerView);
// thumbnailVerticalDragHelper.setOnVerticalDragListener(onVerticalDragListener);
// playerVerticalDragHelper.setOnVerticalDragListener(onVerticalDragListener);
// binding.thumbnailParent.setOnTouchListener((v, event) -> {
// final boolean onDragTouch = thumbnailVerticalDragHelper.onDragTouch(event);
// if (onDragTouch) {
// return true;
// }
// return thumbnailVerticalDragHelper.onGestureTouchEvent(event);
// });
// }
final GestureDetector.OnGestureListener videoPlayerViewGestureListener = new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapConfirmed(final MotionEvent e) {
binding.playerView.performClick();
return true;
}
};
final GestureDetector gestureDetector = new GestureDetector(itemView.getContext(), videoPlayerViewGestureListener);
binding.playerView.setOnTouchListener((v, event) -> {
gestureDetector.onTouchEvent(event);
@ -77,7 +61,7 @@ public class SliderVideoViewHolder extends SliderItemViewHolder {
@Override
public void onThumbnailClick() {
if (sliderCallback != null) {
sliderCallback.onItemClicked(position);
sliderCallback.onItemClicked(position, media, binding.getRoot());
}
}
@ -120,6 +104,21 @@ public class SliderVideoViewHolder extends SliderItemViewHolder {
sliderCallback.onPlayerRelease(position);
}
}
@Override
public void onFullScreenModeChanged(final boolean isFullScreen, final StyledPlayerView playerView) {
if (sliderCallback != null) {
sliderCallback.onFullScreenModeChanged(isFullScreen, playerView);
}
}
@Override
public boolean isInFullScreen() {
if (sliderCallback != null) {
return sliderCallback.isInFullScreen();
}
return false;
}
};
final float aspectRatio = (float) media.getOriginalWidth() / media.getOriginalHeight();
String videoUrl = null;
@ -138,16 +137,10 @@ public class SliderVideoViewHolder extends SliderItemViewHolder {
aspectRatio,
ResponseBodyUtils.getThumbUrl(media),
loadVideoOnItemClick,
// controlsBinding,
videoPlayerCallback);
// binding.itemFeedBottom.btnMute.setOnClickListener(v -> {
// final float newVol = videoPlayerViewHelper.toggleMute();
// setMuteIcon(newVol);
// Utils.sessionVolumeFull = newVol == 1f;
// });
binding.playerView.setOnClickListener(v -> {
if (sliderCallback != null) {
sliderCallback.onItemClicked(position);
sliderCallback.onItemClicked(position, media, binding.getRoot());
}
});
}
@ -161,62 +154,4 @@ public class SliderVideoViewHolder extends SliderItemViewHolder {
if (videoPlayerViewHelper == null) return;
videoPlayerViewHelper.releasePlayer();
}
// public void resetPlayerTimeline() {
// if (videoPlayerViewHelper == null) return;
// videoPlayerViewHelper.resetTimeline();
// }
//
// public void removeCallbacks() {
// if (videoPlayerViewHelper == null) return;
// videoPlayerViewHelper.removeCallbacks();
// }
// private void setDimensions(final FeedModel feedModel, final int spanCount, final boolean animate) {
// final ViewGroup.LayoutParams layoutParams = binding.imageViewer.getLayoutParams();
// final int deviceWidth = Utils.displayMetrics.widthPixels;
// final int spanWidth = deviceWidth / spanCount;
// final int spanHeight = NumberUtils.getResultingHeight(spanWidth, feedModel.getImageHeight(), feedModel.getImageWidth());
// final int width = spanWidth == 0 ? deviceWidth : spanWidth;
// final int height = spanHeight == 0 ? deviceWidth + 1 : spanHeight;
// if (animate) {
// Animation animation = AnimationUtils.expand(
// binding.imageViewer,
// layoutParams.width,
// layoutParams.height,
// width,
// height,
// new Animation.AnimationListener() {
// @Override
// public void onAnimationStart(final Animation animation) {
// showOrHideDetails(spanCount);
// }
//
// @Override
// public void onAnimationEnd(final Animation animation) {
// // showOrHideDetails(spanCount);
// }
//
// @Override
// public void onAnimationRepeat(final Animation animation) {
//
// }
// });
// binding.imageViewer.startAnimation(animation);
// } else {
// layoutParams.width = width;
// layoutParams.height = height;
// binding.imageViewer.requestLayout();
// }
// }
//
// private void showOrHideDetails(final int spanCount) {
// if (spanCount == 1) {
// binding.itemFeedTop.getRoot().setVisibility(View.VISIBLE);
// binding.itemFeedBottom.getRoot().setVisibility(View.VISIBLE);
// } else {
// binding.itemFeedTop.getRoot().setVisibility(View.GONE);
// binding.itemFeedBottom.getRoot().setVisibility(View.GONE);
// }
// }
}

View File

@ -45,9 +45,9 @@ public class FeedSliderViewHolder extends FeedItemViewHolder {
final String text = "1/" + sliderItemLen;
binding.mediaCounter.setText(text);
binding.mediaList.setOffscreenPageLimit(1);
final SliderItemsAdapter adapter = new SliderItemsAdapter(null, false, new SliderCallbackAdapter() {
final SliderItemsAdapter adapter = new SliderItemsAdapter(false, new SliderCallbackAdapter() {
@Override
public void onItemClicked(final int position) {
public void onItemClicked(final int position, final Media media, final View view) {
feedItemCallback.onSliderClick(feedModel, position);
}
});

View File

@ -1,5 +1,7 @@
package awais.instagrabber.customviews;
import com.google.android.exoplayer2.ui.StyledPlayerView;
public class VideoPlayerCallbackAdapter implements VideoPlayerViewHelper.VideoPlayerCallback {
@Override
public void onThumbnailLoaded() {}
@ -18,4 +20,12 @@ public class VideoPlayerCallbackAdapter implements VideoPlayerViewHelper.VideoPl
@Override
public void onRelease() {}
@Override
public void onFullScreenModeChanged(final boolean isFullScreen, final StyledPlayerView playerView) {}
@Override
public boolean isInFullScreen() {
return false;
}
}

View File

@ -1,15 +1,19 @@
package awais.instagrabber.customviews;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.drawable.Animatable;
import android.net.Uri;
import android.os.Looper;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.PopupMenu;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatImageButton;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.drawee.backends.pipeline.PipelineDraweeControllerBuilder;
@ -23,18 +27,23 @@ import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.audio.AudioListener;
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
import com.google.android.exoplayer2.ui.StyledPlayerControlView;
import com.google.android.exoplayer2.ui.StyledPlayerView;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.material.button.MaterialButton;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import awais.instagrabber.R;
import awais.instagrabber.databinding.LayoutVideoPlayerWithThumbnailBinding;
import awais.instagrabber.utils.Utils;
public class VideoPlayerViewHelper implements Player.EventListener {
private static final String TAG = "VideoPlayerViewHelper";
// private static final long INITIAL_DELAY = 0;
// private static final long RECURRING_DELAY = 60;
private static final String TAG = VideoPlayerViewHelper.class.getSimpleName();
private final Context context;
private final LayoutVideoPlayerWithThumbnailBinding binding;
@ -42,74 +51,20 @@ public class VideoPlayerViewHelper implements Player.EventListener {
private final float thumbnailAspectRatio;
private final String thumbnailUrl;
private final boolean loadPlayerOnClick;
// private final LayoutExoCustomControlsBinding controlsBinding;
private final VideoPlayerCallback videoPlayerCallback;
private final String videoUrl;
private final DefaultDataSourceFactory dataSourceFactory;
private SimpleExoPlayer player;
private PopupMenu speedPopup;
// private PositionCheckRunnable positionChecker;
// private Handler positionUpdateHandler;
private AppCompatImageButton mute;
// private final Player.EventListener listener = new Player.EventListener() {
// @Override
// public void onPlaybackStateChanged(final int state) {
// // switch (state) {
// // case Player.STATE_BUFFERING:
// // case STATE_IDLE:
// // case STATE_ENDED:
// // positionUpdateHandler.removeCallbacks(positionChecker);
// // return;
// // case STATE_READY:
// // setupTimeline();
// // positionUpdateHandler.postDelayed(positionChecker, INITIAL_DELAY);
// // break;
// // }
// }
//
// @Override
// public void onPlayWhenReadyChanged(final boolean playWhenReady, final int reason) {
// // updatePlayPauseDrawable(playWhenReady);
// // if (positionUpdateHandler == null || positionChecker == null) return;
// // if (playWhenReady) {
// // positionUpdateHandler.removeCallbacks(positionChecker);
// // positionUpdateHandler.postDelayed(positionChecker, INITIAL_DELAY);
// // }
// }
// };
private final AudioListener audioListener = new AudioListener() {
@Override
public void onVolumeChanged(final float volume) {
updateMuteIcon(volume);
}
};
// private final Slider.OnChangeListener onChangeListener = (slider, value, fromUser) -> {
// if (!fromUser) return;
// long actualValue = (long) value;
// if (actualValue < 0) {
// actualValue = 0;
// } else if (actualValue > player.getDuration()) {
// actualValue = player.getDuration();
// }
// player.seekTo(actualValue);
// };
// private final View.OnClickListener onClickListener = v -> player.setPlayWhenReady(!player.getPlayWhenReady());
// // private final LabelFormatter labelFormatter = value -> TextUtils.millisToTimeString((long) value);
private final View.OnClickListener muteOnClickListener = v -> toggleMute();
private MaterialButton mute;
// private final View.OnClickListener rewOnClickListener = v -> {
// final long positionMs = player.getCurrentPosition() - 5000;
// player.seekTo(positionMs < 0 ? 0 : positionMs);
// };
// private final View.OnClickListener ffOnClickListener = v -> {
// long positionMs = player.getCurrentPosition() + 5000;
// long duration = player.getDuration();
// if (duration == TIME_UNSET) {
// duration = 0;
// }
// player.seekTo(Math.min(positionMs, duration));
// };
// private final View.OnClickListener showMenu = this::showMenu;
private Object layoutManager;
public VideoPlayerViewHelper(@NonNull final Context context,
@NonNull final LayoutVideoPlayerWithThumbnailBinding binding,
@ -118,7 +73,6 @@ public class VideoPlayerViewHelper implements Player.EventListener {
final float thumbnailAspectRatio,
final String thumbnailUrl,
final boolean loadPlayerOnClick,
// final LayoutExoCustomControlsBinding controlsBinding,
final VideoPlayerCallback videoPlayerCallback) {
this.context = context;
this.binding = binding;
@ -126,7 +80,6 @@ public class VideoPlayerViewHelper implements Player.EventListener {
this.thumbnailAspectRatio = thumbnailAspectRatio;
this.thumbnailUrl = thumbnailUrl;
this.loadPlayerOnClick = loadPlayerOnClick;
// this.controlsBinding = controlsBinding;
this.videoPlayerCallback = videoPlayerCallback;
this.videoUrl = videoUrl;
this.dataSourceFactory = new DefaultDataSourceFactory(binding.getRoot().getContext(), "instagram");
@ -143,7 +96,6 @@ public class VideoPlayerViewHelper implements Player.EventListener {
}
});
setThumbnail();
// setupControls();
}
private void setThumbnail() {
@ -196,11 +148,6 @@ public class VideoPlayerViewHelper implements Player.EventListener {
player = new SimpleExoPlayer.Builder(context)
.setLooper(Looper.getMainLooper())
.build();
// positionUpdateHandler = new Handler();
// positionChecker = new PositionCheckRunnable(positionUpdateHandler,
// player,
// controlsBinding.timeline,
// controlsBinding.fromTime);
player.addListener(this);
player.addAudioListener(audioListener);
player.setVolume(initialVolume);
@ -210,138 +157,118 @@ public class VideoPlayerViewHelper implements Player.EventListener {
final MediaItem mediaItem = MediaItem.fromUri(videoUrl);
final ProgressiveMediaSource mediaSource = sourceFactory.createMediaSource(mediaItem);
player.setMediaSource(mediaSource);
// setupControls();
player.prepare();
binding.playerView.setPlayer(player);
// binding.playerView.setShowFastForwardButton(false);
// binding.playerView.setShowRewindButton(false);
binding.playerView.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FIXED_HEIGHT);
binding.playerView.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FIT);
binding.playerView.setShowNextButton(false);
binding.playerView.setShowPreviousButton(false);
// binding.controls.setPlayer(player);
mute = binding.playerView.findViewById(R.id.mute);
// mute = binding.controls.findViewById(R.id.mute);
if (mute != null) {
mute.setOnClickListener(muteOnClickListener);
}
updateMuteIcon(player.getVolume());
binding.playerView.setControllerOnFullScreenModeChangedListener(isFullScreen -> {
if (videoPlayerCallback == null) return;
videoPlayerCallback.onFullScreenModeChanged(isFullScreen, binding.playerView);
});
setupControllerView();
}
// private void setupControls() {
// if (controlsBinding == null) return;
// // binding.playerView.setUseController(false);
// if (player == null) {
// // enableControls(false);
// // controlsBinding.playPause.setEnabled(true);
// // controlsBinding.playPause.setOnClickListener(new NoPlayerPlayPauseClickListener(binding.thumbnailParent));
// return;
// }
// // enableControls(true);
// // updatePlayPauseDrawable(player.getPlayWhenReady());
// // updateMuteIcon(player.getVolume());
// player.addListener(listener);
// // player.addAudioListener(audioListener);
// // controlsBinding.timeline.addOnChangeListener(onChangeListener);
// // controlsBinding.timeline.setLabelFormatter(labelFormatter);
// // controlsBinding.playPause.setOnClickListener(onClickListener);
// // controlsBinding.mute.setOnClickListener(muteOnClickListener);
// // controlsBinding.rewWithAmount.setOnClickListener(rewOnClickListener);
// // controlsBinding.ffWithAmount.setOnClickListener(ffOnClickListener);
// // controlsBinding.speed.setOnClickListener(showMenu);
// }
private void setupControllerView() {
try {
final StyledPlayerControlView controllerView = getStyledPlayerControlView();
if (controllerView == null) return;
layoutManager = setControlViewLayoutManager(controllerView);
if (videoPlayerCallback != null && videoPlayerCallback.isInFullScreen()) {
setControllerViewToFullScreenMode(controllerView);
}
final ViewGroup exoBasicControls = controllerView.findViewById(R.id.exo_basic_controls);
if (exoBasicControls == null) return;
mute = new AppCompatImageButton(context);
final Resources resources = context.getResources();
if (resources == null) return;
final int width = resources.getDimensionPixelSize(R.dimen.exo_small_icon_width);
final int height = resources.getDimensionPixelSize(R.dimen.exo_small_icon_height);
final int margin = resources.getDimensionPixelSize(R.dimen.exo_small_icon_horizontal_margin);
final int paddingHorizontal = resources.getDimensionPixelSize(R.dimen.exo_small_icon_padding_horizontal);
final int paddingVertical = resources.getDimensionPixelSize(R.dimen.exo_small_icon_padding_vertical);
final ViewGroup.MarginLayoutParams layoutParams = new ViewGroup.MarginLayoutParams(width, height);
layoutParams.setMargins(margin, 0, margin, 0);
mute.setLayoutParams(layoutParams);
mute.setPadding(paddingHorizontal, paddingVertical, paddingHorizontal, paddingVertical);
mute.setScaleType(ImageView.ScaleType.FIT_XY);
mute.setBackgroundResource(Utils.getAttrResId(context, android.R.attr.selectableItemBackground));
mute.setImageTintList(ColorStateList.valueOf(resources.getColor(R.color.white)));
updateMuteIcon(player.getVolume());
exoBasicControls.addView(mute, 0);
mute.setOnClickListener(muteOnClickListener);
} catch (Exception e) {
Log.e(TAG, "loadPlayer: ", e);
}
}
// private void setupTimeline() {
// final long duration = player.getDuration();
// controlsBinding.timeline.setEnabled(true);
// controlsBinding.timeline.setValueFrom(0);
// controlsBinding.timeline.setValueTo(duration);
// controlsBinding.fromTime.setText(TextUtils.millisToTimeString(0));
// controlsBinding.toTime.setText(TextUtils.millisToTimeString(duration));
// }
@Nullable
private Object setControlViewLayoutManager(@NonNull final StyledPlayerControlView controllerView)
throws NoSuchFieldException, IllegalAccessException {
final Field controlViewLayoutManagerField = controllerView.getClass().getDeclaredField("controlViewLayoutManager");
controlViewLayoutManagerField.setAccessible(true);
return controlViewLayoutManagerField.get(controllerView);
}
// private void enableControls(final boolean enable) {
// controlsBinding.speed.setEnabled(enable);
// controlsBinding.speed.setClickable(enable);
// controlsBinding.mute.setEnabled(enable);
// controlsBinding.mute.setClickable(enable);
// controlsBinding.ffWithAmount.setEnabled(enable);
// controlsBinding.ffWithAmount.setClickable(enable);
// controlsBinding.rewWithAmount.setEnabled(enable);
// controlsBinding.rewWithAmount.setClickable(enable);
// // controlsBinding.fromTime.setEnabled(enable);
// // controlsBinding.toTime.setEnabled(enable);
// controlsBinding.playPause.setEnabled(enable);
// controlsBinding.playPause.setClickable(enable);
// // controlsBinding.timeline.setEnabled(enable);
// }
private void setControllerViewToFullScreenMode(@NonNull final StyledPlayerControlView controllerView)
throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
// Exoplayer doesn't expose the fullscreen state, so using reflection
final Field fullScreenButtonField = controllerView.getClass().getDeclaredField("fullScreenButton");
fullScreenButtonField.setAccessible(true);
final ImageView fullScreenButton = (ImageView) fullScreenButtonField.get(controllerView);
final Field isFullScreen = controllerView.getClass().getDeclaredField("isFullScreen");
isFullScreen.setAccessible(true);
isFullScreen.set(controllerView, true);
final Method updateFullScreenButtonForState = controllerView
.getClass()
.getDeclaredMethod("updateFullScreenButtonForState", ImageView.class, boolean.class);
updateFullScreenButtonForState.setAccessible(true);
updateFullScreenButtonForState.invoke(controllerView, fullScreenButton, true);
// public void showMenu(View anchor) {
// PopupMenu popup = getPopupMenu(anchor);
// popup.show();
// }
}
// @NonNull
// private PopupMenu getPopupMenu(final View anchor) {
// if (speedPopup != null) {
// return speedPopup;
// }
// final ContextThemeWrapper themeWrapper = new ContextThemeWrapper(context, R.style.popupMenuStyle);
// // final ContextThemeWrapper themeWrapper = new ContextThemeWrapper(context, R.style.Widget_MaterialComponents_PopupMenu_Exoplayer);
// speedPopup = new PopupMenu(themeWrapper, anchor);
// speedPopup.getMenuInflater().inflate(R.menu.speed_menu, speedPopup.getMenu());
// speedPopup.setOnMenuItemClickListener(item -> {
// float nextSpeed;
// int textResId;
// int itemId = item.getItemId();
// if (itemId == R.id.pt_two_five_x) {
// nextSpeed = 0.25f;
// textResId = R.string.pt_two_five_x;
// } else if (itemId == R.id.pt_five_x) {
// nextSpeed = 0.5f;
// textResId = R.string.pt_five_x;
// } else if (itemId == R.id.pt_seven_five_x) {
// nextSpeed = 0.75f;
// textResId = R.string.pt_seven_five_x;
// } else if (itemId == R.id.one_x) {
// nextSpeed = 1f;
// textResId = R.string.one_x;
// } else if (itemId == R.id.one_pt_two_five_x) {
// nextSpeed = 1.25f;
// textResId = R.string.one_pt_two_five_x;
// } else if (itemId == R.id.one_pt_five_x) {
// nextSpeed = 1.5f;
// textResId = R.string.one_pt_five_x;
// } else if (itemId == R.id.two_x) {
// nextSpeed = 2f;
// textResId = R.string.two_x;
// } else {
// nextSpeed = 1;
// textResId = R.string.one_x;
// }
// player.setPlaybackParameters(new PlaybackParameters(nextSpeed));
// controlsBinding.speed.setText(textResId);
// return true;
// });
// return speedPopup;
// }
@Nullable
private StyledPlayerControlView getStyledPlayerControlView() throws NoSuchFieldException, IllegalAccessException {
final Field controller = binding.playerView.getClass().getDeclaredField("controller");
controller.setAccessible(true);
return (StyledPlayerControlView) controller.get(binding.playerView);
}
@Override
public void onTracksChanged(@NonNull TrackGroupArray trackGroups, @NonNull TrackSelectionArray trackSelections) {
if (trackGroups.isEmpty()) {
setHasAudio(false);
return;
}
boolean hasAudio = false;
for (int i = 0; i < trackGroups.length; i++) {
for (int g = 0; g < trackGroups.get(i).length; g++) {
final String sampleMimeType = trackGroups.get(i).getFormat(g).sampleMimeType;
if (sampleMimeType != null && sampleMimeType.contains("audio")) {
hasAudio = true;
break;
}
}
}
setHasAudio(hasAudio);
}
private void setHasAudio(final boolean hasAudio) {
if (mute == null) return;
mute.setEnabled(hasAudio);
mute.setAlpha(hasAudio ? 1f : 0.5f);
updateMuteIcon(hasAudio ? 1f : 0f);
}
private void updateMuteIcon(final float volume) {
if (mute == null) return;
if (volume == 0) {
mute.setIconResource(R.drawable.ic_volume_off_24_states);
mute.setImageResource(R.drawable.ic_volume_off_24);
return;
}
mute.setIconResource(R.drawable.ic_volume_up_24_states);
mute.setImageResource(R.drawable.ic_volume_up_24);
}
// private void updatePlayPauseDrawable(final boolean playWhenReady) {
// if (playWhenReady) {
// controlsBinding.playPause.setIconResource(R.drawable.ic_pause_24);
// return;
// }
// controlsBinding.playPause.setIconResource(R.drawable.ic_play_states);
// }
@Override
public void onPlayWhenReadyChanged(final boolean playWhenReady, final int reason) {
if (videoPlayerCallback == null) return;
@ -359,18 +286,18 @@ public class VideoPlayerViewHelper implements Player.EventListener {
private void toggleMute() {
if (player == null) return;
if (layoutManager != null) {
try {
final Method resetHideCallbacks = layoutManager.getClass().getDeclaredMethod("resetHideCallbacks");
resetHideCallbacks.invoke(layoutManager);
} catch (Exception e) {
Log.e(TAG, "toggleMute: ", e);
}
}
final float vol = player.getVolume() == 0f ? 1f : 0f;
player.setVolume(vol);
}
// public void togglePlayback() {
// if (player == null) return;
// final int playbackState = player.getPlaybackState();
// if (playbackState == STATE_IDLE || playbackState == STATE_ENDED) return;
// final boolean playWhenReady = player.getPlayWhenReady();
// player.setPlayWhenReady(!playWhenReady);
// }
public void releasePlayer() {
if (videoPlayerCallback != null) {
videoPlayerCallback.onRelease();
@ -379,86 +306,14 @@ public class VideoPlayerViewHelper implements Player.EventListener {
player.release();
player = null;
}
// if (positionUpdateHandler != null) {
// if (positionChecker != null) {
// positionUpdateHandler.removeCallbacks(positionChecker);
// positionChecker = null;
// }
// positionUpdateHandler = null;
// }
}
public void pause() {
if (player != null) {
player.pause();
}
// if (positionUpdateHandler != null) {
// if (positionChecker != null) {
// positionUpdateHandler.removeCallbacks(positionChecker);
// }
// }
}
// public void resetTimeline() {
// if (player == null) {
// enableControls(false);
// return;
// }
// setupTimeline();
// final long currentPosition = player.getCurrentPosition();
// controlsBinding.timeline.setValue(Math.min(currentPosition, player.getDuration()));
// setupControls();
// }
// public void removeCallbacks() {
// if (player != null) {
// player.removeListener(listener);
// player.removeAudioListener(audioListener);
// }
// controlsBinding.timeline.removeOnChangeListener(onChangeListener);
// controlsBinding.timeline.setLabelFormatter(null);
// controlsBinding.playPause.setOnClickListener(null);
// controlsBinding.mute.setOnClickListener(null);
// controlsBinding.rewWithAmount.setOnClickListener(null);
// controlsBinding.ffWithAmount.setOnClickListener(null);
// controlsBinding.speed.setOnClickListener(null);
// }
// private static class PositionCheckRunnable implements Runnable {
// private final Handler positionUpdateHandler;
// private final SimpleExoPlayer player;
// private final Slider timeline;
// private final AppCompatTextView fromTime;
//
// public PositionCheckRunnable(final Handler positionUpdateHandler,
// final SimpleExoPlayer simpleExoPlayer,
// final Slider slider,
// final AppCompatTextView fromTime) {
// this.positionUpdateHandler = positionUpdateHandler;
// this.player = simpleExoPlayer;
// this.timeline = slider;
// this.fromTime = fromTime;
// }
//
// @Override
// public void run() {
// if (positionUpdateHandler == null) return;
// positionUpdateHandler.removeCallbacks(this);
// if (player == null) return;
// final long currentPosition = player.getCurrentPosition();
// final long duration = player.getDuration();
// if (duration == TIME_UNSET) {
// timeline.setValueFrom(0);
// timeline.setValueTo(0);
// timeline.setEnabled(false);
// return;
// }
// timeline.setValue(Math.min(currentPosition, duration));
// fromTime.setText(TextUtils.millisToTimeString(currentPosition));
// positionUpdateHandler.postDelayed(this, RECURRING_DELAY);
// }
// }
public interface VideoPlayerCallback {
void onThumbnailLoaded();
@ -471,5 +326,9 @@ public class VideoPlayerViewHelper implements Player.EventListener {
void onPause();
void onRelease();
void onFullScreenModeChanged(boolean isFullScreen, final StyledPlayerView playerView);
boolean isInFullScreen();
}
}

View File

@ -6,6 +6,7 @@ import android.content.pm.PackageManager;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
@ -14,15 +15,18 @@ import android.text.Spanned;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.appcompat.view.ContextThemeWrapper;
import androidx.appcompat.widget.PopupMenu;
import androidx.appcompat.widget.Toolbar;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.content.PermissionChecker;
import androidx.fragment.app.Fragment;
@ -44,6 +48,8 @@ import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder;
import com.facebook.drawee.interfaces.DraweeController;
import com.facebook.imagepipeline.request.ImageRequest;
import com.facebook.imagepipeline.request.ImageRequestBuilder;
import com.google.android.exoplayer2.ui.StyledPlayerView;
import com.google.android.material.appbar.CollapsingToolbarLayout;
import com.google.android.material.snackbar.BaseTransientBottomBar;
import com.google.android.material.snackbar.Snackbar;
import com.skydoves.balloon.ArrowOrientation;
@ -59,6 +65,7 @@ import java.io.Serializable;
import java.util.List;
import awais.instagrabber.R;
import awais.instagrabber.activities.MainActivity;
import awais.instagrabber.adapters.SliderCallbackAdapter;
import awais.instagrabber.adapters.SliderItemsAdapter;
import awais.instagrabber.adapters.viewholder.SliderVideoViewHolder;
@ -67,6 +74,7 @@ import awais.instagrabber.customviews.VideoPlayerCallbackAdapter;
import awais.instagrabber.customviews.VideoPlayerViewHelper;
import awais.instagrabber.customviews.drawee.AnimatedZoomableController;
import awais.instagrabber.customviews.drawee.DoubleTapGestureListener;
import awais.instagrabber.customviews.drawee.ZoomableController;
import awais.instagrabber.customviews.drawee.ZoomableDraweeView;
import awais.instagrabber.databinding.DialogPostViewBinding;
import awais.instagrabber.databinding.LayoutPostViewBottomBinding;
@ -117,6 +125,12 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
@Nullable
private ViewPager2 sliderParent;
private LayoutPostViewBottomBinding bottom;
private View postView;
private int originalHeight;
private int originalSystemUi;
private boolean isInFullScreenMode;
private StyledPlayerView playerView;
private int playerViewOriginalHeight;
private final Observer<Object> backStackSavedStateObserver = result -> {
if (result == null) return;
@ -127,6 +141,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
// clear result
backStackSavedStateResultLiveData.postValue(null);
};
private Drawable originalRootBackground;
public void setOnDeleteListener(final OnDeleteListener onDeleteListener) {
if (onDeleteListener == null) return;
@ -197,6 +212,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
@Override
public void onDestroyView() {
super.onDestroyView();
showSystemUI();
final Media media = viewModel.getMedia();
if (media == null) return;
switch (media.getMediaType()) {
@ -753,7 +769,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
}
private void setupPostImage() {
binding.mediaCounter.setVisibility(View.GONE);
// binding.mediaCounter.setVisibility(View.GONE);
final Context context = getContext();
if (context == null) return;
final Resources resources = context.getResources();
@ -762,12 +778,14 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
final String imageUrl = ResponseBodyUtils.getImageUrl(media);
if (TextUtils.isEmpty(imageUrl)) return;
final ZoomableDraweeView postImage = new ZoomableDraweeView(context);
postView = postImage;
final NullSafePair<Integer, Integer> widthHeight = NumberUtils.calculateWidthHeight(media.getOriginalHeight(),
media.getOriginalWidth(),
(int) (Utils.displayMetrics.heightPixels * 0.8),
Utils.displayMetrics.widthPixels);
final int height = widthHeight.second;
final ConstraintLayout.LayoutParams layoutParams = new ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.MATCH_PARENT, height);
originalHeight = widthHeight.second;
final ConstraintLayout.LayoutParams layoutParams = new ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.MATCH_PARENT,
originalHeight);
layoutParams.topToBottom = binding.topBarrier.getId();
layoutParams.bottomToTop = bottom.buttonsTopBarrier.getId();
layoutParams.startToStart = ConstraintLayout.LayoutParams.PARENT_ID;
@ -788,10 +806,22 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
zoomableController.setGestureZoomEnabled(true);
zoomableController.setEnabled(true);
postImage.setZoomingEnabled(true);
postImage.setTapListener(new DoubleTapGestureListener(postImage));
final DoubleTapGestureListener tapListener = new DoubleTapGestureListener(postImage) {
@Override
public boolean onSingleTapConfirmed(final MotionEvent e) {
if (!isInFullScreenMode) {
zoomableController.reset();
hideSystemUI();
} else {
showSystemUI();
binding.getRoot().postDelayed(zoomableController::reset, 500);
}
return super.onSingleTapConfirmed(e);
}
};
postImage.setTapListener(tapListener);
// postImage.setAllowTouchInterceptionWhileZoomed(true);
binding.contentRoot.addView(postImage, 0);
// binding.postImage.setAllowTouchInterceptionWhileZoomed(true);
// binding.postImage.setOnVerticalDragListener(onVerticalDragListener);
}
private void setupSlider() {
@ -818,13 +848,15 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
maxHW.second,
(int) (Utils.displayMetrics.heightPixels * 0.8),
Utils.displayMetrics.widthPixels);
originalHeight = widthHeight.second;
final ConstraintLayout.LayoutParams layoutParams = new ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.MATCH_PARENT,
widthHeight.second);
originalHeight);
layoutParams.topToBottom = binding.topBarrier.getId();
layoutParams.bottomToTop = bottom.buttonsTopBarrier.getId();
layoutParams.startToStart = ConstraintLayout.LayoutParams.PARENT_ID;
layoutParams.endToEnd = ConstraintLayout.LayoutParams.PARENT_ID;
sliderParent.setLayoutParams(layoutParams);
postView = sliderParent;
binding.contentRoot.addView(sliderParent, 0);
final boolean hasVideo = media.getCarouselMedia()
@ -841,16 +873,23 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
});
}
}
sliderItemsAdapter = new SliderItemsAdapter(null, true, new SliderCallbackAdapter() {
sliderItemsAdapter = new SliderItemsAdapter(true, new SliderCallbackAdapter() {
@Override
public void onThumbnailLoaded(final int position) {
if (position != 0) return;
startPostponedEnterTransition();
}
@Override
public void onItemClicked(final int position) {
// toggleDetails();
public void onItemClicked(final int position, final Media media, final View view) {
if (media == null
|| media.getMediaType() != MediaItemType.MEDIA_TYPE_IMAGE
|| !(view instanceof ZoomableDraweeView)) {
return;
}
final ZoomableController zoomableController = ((ZoomableDraweeView) view).getZoomableController();
if (!(zoomableController instanceof AnimatedZoomableController)) return;
if (!isInFullScreenMode) {
((AnimatedZoomableController) zoomableController).reset();
hideSystemUI();
return;
}
showSystemUI();
binding.getRoot().postDelayed(((AnimatedZoomableController) zoomableController)::reset, 500);
}
@Override
@ -877,6 +916,21 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
if (activity == null) return;
Utils.disableKeepScreenOn(activity);
}
@Override
public void onFullScreenModeChanged(final boolean isFullScreen, final StyledPlayerView playerView) {
PostViewV2Fragment.this.playerView = playerView;
if (isFullScreen) {
hideSystemUI();
return;
}
showSystemUI();
}
@Override
public boolean isInFullScreen() {
return isInFullScreenMode;
}
});
sliderParent.setAdapter(sliderItemsAdapter);
if (sliderPosition >= 0 && sliderPosition < media.getCarouselMedia().size()) {
@ -981,12 +1035,14 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
(int) (Utils.displayMetrics.heightPixels * 0.8),
Utils.displayMetrics.widthPixels);
layoutParams.width = ConstraintLayout.LayoutParams.MATCH_PARENT;
layoutParams.height = widthHeight.second;
originalHeight = widthHeight.second;
layoutParams.height = originalHeight;
layoutParams.topToBottom = binding.topBarrier.getId();
layoutParams.bottomToTop = bottom.buttonsTopBarrier.getId();
layoutParams.startToStart = ConstraintLayout.LayoutParams.PARENT_ID;
layoutParams.endToEnd = ConstraintLayout.LayoutParams.PARENT_ID;
binding.contentRoot.addView(videoPost.getRoot(), 0);
postView = videoPost.getRoot();
binding.contentRoot.addView(postView, 0);
// final GestureDetector gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
// @Override
@ -1041,6 +1097,16 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
if (activity == null) return;
Utils.disableKeepScreenOn(activity);
}
@Override
public void onFullScreenModeChanged(final boolean isFullScreen, final StyledPlayerView playerView) {
PostViewV2Fragment.this.playerView = playerView;
if (isFullScreen) {
hideSystemUI();
return;
}
showSystemUI();
}
};
final float aspectRatio = (float) media.getOriginalWidth() / media.getOriginalHeight();
String videoUrl = null;
@ -1064,92 +1130,6 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
}
}
// private void enablePlayerControls(final boolean enable) {
// video = enable;
// if (enable) {
// binding.playerControlsToggle.setVisibility(View.VISIBLE);
// binding.playerControlsToggle.setOnClickListener(v -> {
// final int visibility = binding.playerControls.getRoot().getVisibility();
// if (visibility == View.GONE) {
// showPlayerControls();
// return;
// }
// hidePlayerControls();
// });
// return;
// }
// binding.playerControlsToggle.setVisibility(View.GONE);
// hidePlayerControls();
// }
// private void hideCaption() {
// if (bottomSheetBehavior == null) return;
// bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
// }
// private void showPlayerControls() {
// hideCaption();
// // previously invisible view
// View view = binding.playerControls.getRoot();
// if (view.getVisibility() == View.VISIBLE) {
// return;
// }
// if (!ViewCompat.isAttachedToWindow(view)) {
// view.setVisibility(View.VISIBLE);
// return;
// }
// // get the center for the clipping circle
// int cx = view.getWidth() / 2;
// // int cy = view.getHeight() / 2;
// int cy = view.getHeight();
//
// // get the final radius for the clipping circle
// float finalRadius = (float) Math.hypot(cx, cy);
//
// // create the animator for this view (the start radius is zero)
// Animator anim = ViewAnimationUtils.createCircularReveal(view, cx, cy, 0f, finalRadius);
//
// // make the view visible and start the animation
// view.setVisibility(View.VISIBLE);
// anim.start();
//
// }
// private void hidePlayerControls() {
// // previously visible view
// final View view = binding.playerControls.getRoot();
// if (view.getVisibility() == View.GONE) {
// return;
// }
// if (!ViewCompat.isAttachedToWindow(view)) {
// view.setVisibility(View.GONE);
// return;
// }
//
// // get the center for the clipping circle
// int cx = view.getWidth() / 2;
// // int cy = view.getHeight() / 2;
// int cy = view.getHeight();
//
// // get the initial radius for the clipping circle
// float initialRadius = (float) Math.hypot(cx, cy);
//
// // create the animation (the final radius is zero)
// Animator anim = ViewAnimationUtils.createCircularReveal(view, cx, cy, initialRadius, 0f);
//
// // make the view invisible when the animation is done
// anim.addListener(new AnimatorListenerAdapter() {
// @Override
// public void onAnimationEnd(Animator animation) {
// super.onAnimationEnd(animation);
// view.setVisibility(View.GONE);
// }
// });
//
// // start the animation
// anim.start();
// }
private void setupOptions(final Boolean show) {
if (!show) {
binding.options.setVisibility(View.GONE);
@ -1282,29 +1262,49 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
}
private void toggleDetails() {
// hasBeenToggled = true;
final boolean hasBeenToggled = true;
final Media media = viewModel.getMedia();
binding.getRoot().post(() -> {
TransitionManager.beginDelayedTransition(binding.getRoot());
if (detailsVisible) {
final Context context = getContext();
if (context == null) return;
originalRootBackground = binding.getRoot().getBackground();
final Resources resources = context.getResources();
if (resources == null) return;
final ColorDrawable colorDrawable = new ColorDrawable(resources.getColor(R.color.black));
binding.getRoot().setBackground(colorDrawable);
if (postView != null) {
// Make post match parent
final ViewGroup.LayoutParams layoutParams = postView.getLayoutParams();
final int fullHeight = Utils.displayMetrics.heightPixels + Utils.getNavigationBarSize(context).y;
layoutParams.height = fullHeight;
binding.contentRoot.getLayoutParams().height = fullHeight;
if (playerView != null) {
playerViewOriginalHeight = playerView.getLayoutParams().height;
playerView.getLayoutParams().height = fullHeight;
}
}
detailsVisible = false;
if (media.getUser() != null) {
binding.profilePic.setVisibility(View.GONE);
binding.title.setVisibility(View.GONE);
binding.subtitle.setVisibility(View.GONE);
// binding.topBg.setVisibility(View.GONE);
}
if (media.getLocation() != null) {
binding.location.setVisibility(View.GONE);
}
// bottom.bottomBg.setVisibility(View.GONE);
// bottom.likesCount.setVisibility(View.GONE);
// bottom.commentsCount.setVisibility(View.GONE);
if (media.getCaption() != null && !TextUtils.isEmpty(media.getCaption().getText())) {
bottom.caption.setVisibility(View.GONE);
bottom.translate.setVisibility(View.GONE);
}
bottom.likesCount.setVisibility(View.GONE);
bottom.commentsCount.setVisibility(View.GONE);
bottom.date.setVisibility(View.GONE);
bottom.comment.setVisibility(View.GONE);
bottom.like.setVisibility(View.GONE);
bottom.save.setVisibility(View.GONE);
// bottom.share.setVisibility(View.GONE);
bottom.share.setVisibility(View.GONE);
bottom.download.setVisibility(View.GONE);
binding.mediaCounter.setVisibility(View.GONE);
bottom.viewsCount.setVisibility(View.GONE);
@ -1312,12 +1312,21 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
if (options != null && !options.isEmpty()) {
binding.options.setVisibility(View.GONE);
}
// wasControlsVisible = binding.playerControls.getRoot().getVisibility() == View.VISIBLE;
// if (wasControlsVisible) {
// hidePlayerControls();
// }
return;
}
if (originalRootBackground != null) {
binding.getRoot().setBackground(originalRootBackground);
}
if (postView != null) {
// Make post height back to original
final ViewGroup.LayoutParams layoutParams = postView.getLayoutParams();
layoutParams.height = originalHeight;
binding.contentRoot.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;
if (playerView != null) {
playerView.getLayoutParams().height = playerViewOriginalHeight;
playerView = null;
}
}
if (media.getUser() != null) {
binding.profilePic.setVisibility(View.VISIBLE);
binding.title.setVisibility(View.VISIBLE);
@ -1327,17 +1336,20 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
if (media.getLocation() != null) {
binding.location.setVisibility(View.VISIBLE);
}
// bottom.bottomBg.setVisibility(View.VISIBLE);
if (media.getCaption() != null && !TextUtils.isEmpty(media.getCaption().getText())) {
bottom.caption.setVisibility(View.VISIBLE);
bottom.translate.setVisibility(View.VISIBLE);
}
if (viewModel.hasPk()) {
// bottom.likesCount.setVisibility(View.VISIBLE);
bottom.likesCount.setVisibility(View.VISIBLE);
bottom.date.setVisibility(View.VISIBLE);
// binding.captionParent.setVisibility(View.VISIBLE);
// binding.captionToggle.setVisibility(View.VISIBLE);
// bottom.share.setVisibility(View.VISIBLE);
bottom.share.setVisibility(View.VISIBLE);
}
if (viewModel.hasPk() && !viewModel.getMedia().isCommentsDisabled()) {
bottom.comment.setVisibility(View.VISIBLE);
// bottom.commentsCount.setVisibility(View.VISIBLE);
bottom.commentsCount.setVisibility(View.VISIBLE);
}
bottom.download.setVisibility(View.VISIBLE);
final List<Integer> options = viewModel.getOptions().getValue();
@ -1362,6 +1374,64 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
});
}
private void hideSystemUI() {
if (detailsVisible) {
toggleDetails();
}
final MainActivity activity = (MainActivity) getActivity();
if (activity == null) return;
final ActionBar actionBar = activity.getSupportActionBar();
if (actionBar != null) {
actionBar.hide();
}
final CollapsingToolbarLayout appbarLayout = activity.getCollapsingToolbarView();
if (appbarLayout != null) {
appbarLayout.setVisibility(View.GONE);
}
final Toolbar toolbar = activity.getToolbar();
if (toolbar != null) {
toolbar.setVisibility(View.GONE);
}
final View decorView = activity.getWindow().getDecorView();
originalSystemUi = decorView.getSystemUiVisibility();
decorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_IMMERSIVE
// Set the content to appear under the system bars so that the
// content doesn't resize when the system bars hide and show.
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
// Hide the nav bar and status bar
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN);
isInFullScreenMode = true;
}
// Shows the system bars by removing all the flags
// except for the ones that make the content appear under the system bars.
private void showSystemUI() {
if (!detailsVisible) {
toggleDetails();
}
final MainActivity activity = (MainActivity) getActivity();
if (activity == null) return;
final ActionBar actionBar = activity.getSupportActionBar();
if (actionBar != null) {
actionBar.show();
}
final CollapsingToolbarLayout appbarLayout = activity.getCollapsingToolbarView();
if (appbarLayout != null) {
appbarLayout.setVisibility(View.VISIBLE);
}
final Toolbar toolbar = activity.getToolbar();
if (toolbar != null) {
toolbar.setVisibility(View.VISIBLE);
}
final View decorView = activity.getWindow().getDecorView();
decorView.setSystemUiVisibility(originalSystemUi);
isInFullScreenMode = false;
}
private void navigateToProfile(final String username) {
final NavController navController = getNavController();
if (navController == null) return;

View File

@ -10,6 +10,7 @@ import android.content.Intent;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.media.MediaScannerConnection;
@ -22,6 +23,7 @@ import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Pair;
import android.util.TypedValue;
import android.view.Display;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
@ -294,6 +296,12 @@ public final class Utils {
return outValue.data;
}
public static int getAttrResId(@NonNull final Context context, final int attr) {
final TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(attr, outValue, true);
return outValue.resourceId;
}
public static void transparentStatusBar(final Activity activity,
final boolean enable,
final boolean fullscreen) {
@ -517,4 +525,41 @@ public final class Utils {
if (navRootString == null || tabOrderString == null) return false;
return tabOrderString.contains(navRootString);
}
@NonNull
public static Point getNavigationBarSize(@NonNull Context context) {
Point appUsableSize = getAppUsableScreenSize(context);
Point realScreenSize = getRealScreenSize(context);
// navigation bar on the right
if (appUsableSize.x < realScreenSize.x) {
return new Point(realScreenSize.x - appUsableSize.x, appUsableSize.y);
}
// navigation bar at the bottom
if (appUsableSize.y < realScreenSize.y) {
return new Point(appUsableSize.x, realScreenSize.y - appUsableSize.y);
}
// navigation bar is not present
return new Point();
}
@NonNull
public static Point getAppUsableScreenSize(@NonNull Context context) {
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = windowManager.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
return size;
}
@NonNull
public static Point getRealScreenSize(@NonNull Context context) {
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = windowManager.getDefaultDisplay();
Point size = new Point();
display.getRealSize(size);
return size;
}
}

View File

@ -4,6 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?colorSurface"
tools:context=".fragments.PostViewV2Fragment">
<androidx.constraintlayout.widget.ConstraintLayout

View File

@ -16,6 +16,7 @@
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="36dp"
android:layout_height="40dp"
android:background="@drawable/background_grey_ripple"
android:visibility="visible"
app:icon="@drawable/ic_not_liked"
app:iconGravity="textStart"
@ -51,6 +52,7 @@
android:layout_width="36dp"
android:layout_height="40dp"
android:layout_marginStart="8dp"
android:background="@drawable/background_grey_ripple"
app:icon="@drawable/ic_outline_comments_24"
app:iconPadding="0dp"
app:iconSize="22dp"
@ -90,6 +92,7 @@
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="48dp"
android:layout_height="40dp"
android:background="@drawable/background_grey_ripple"
app:icon="?attr/actionModeShareDrawable"
app:iconGravity="textStart"
app:iconPadding="0dp"
@ -104,6 +107,7 @@
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="48dp"
android:layout_height="40dp"
android:background="@drawable/background_grey_ripple"
android:visibility="visible"
app:icon="@drawable/ic_round_bookmark_border_24"
app:iconGravity="textStart"
@ -120,6 +124,7 @@
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="48dp"
android:layout_height="40dp"
android:background="@drawable/background_grey_ripple"
android:visibility="visible"
app:icon="@drawable/ic_download"
app:iconGravity="textStart"