Update post view layout and a height related bug. Use exo's internal layout for controls.

This commit is contained in:
Ammar Githam 2021-05-08 15:49:20 +09:00
parent 59c8a325fe
commit 2f4eff741e
20 changed files with 1174 additions and 702 deletions

View File

@ -504,11 +504,12 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
@SuppressLint("RestrictedApi") final Deque<NavBackStackEntry> backStack = navController.getBackStack();
setupMenu(backStack.size(), destinationId);
final boolean contains = showBottomViewDestinations.contains(destinationId);
binding.bottomNavView.setVisibility(contains ? View.VISIBLE : View.GONE);
if (contains && behavior != null) {
behavior.slideUp(binding.bottomNavView);
}
binding.getRoot().post(() -> {
binding.bottomNavView.setVisibility(contains ? View.VISIBLE : View.GONE);
if (contains && behavior != null) {
behavior.slideUp(binding.bottomNavView);
}
});
// explicitly hide keyboard when we navigate
final View view = getCurrentFocus();
Utils.hideKeyboard(view);

View File

@ -4,7 +4,6 @@ import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.core.util.Pair;
import androidx.recyclerview.widget.ItemTouchHelper;
import com.facebook.drawee.backends.pipeline.Fresco;
@ -23,6 +22,7 @@ import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
import awais.instagrabber.repositories.responses.directmessages.DirectItemAnimatedMedia;
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
import awais.instagrabber.utils.NullSafePair;
import awais.instagrabber.utils.NumberUtils;
import awais.instagrabber.utils.Utils;
@ -48,7 +48,7 @@ public class DirectItemAnimatedMediaViewHolder extends DirectItemViewHolder {
final AnimatedMediaFixedHeight fixedHeight = images.getFixedHeight();
if (fixedHeight == null) return;
final String url = fixedHeight.getWebp();
final Pair<Integer, Integer> widthHeight = NumberUtils.calculateWidthHeight(
final NullSafePair<Integer, Integer> widthHeight = NumberUtils.calculateWidthHeight(
fixedHeight.getHeight(),
fixedHeight.getWidth(),
mediaImageMaxHeight,
@ -56,8 +56,8 @@ public class DirectItemAnimatedMediaViewHolder extends DirectItemViewHolder {
);
binding.ivAnimatedMessage.setVisibility(View.VISIBLE);
final ViewGroup.LayoutParams layoutParams = binding.ivAnimatedMessage.getLayoutParams();
final int width = widthHeight.first != null ? widthHeight.first : 0;
final int height = widthHeight.second != null ? widthHeight.second : 0;
final int width = widthHeight.first;
final int height = widthHeight.second;
layoutParams.width = width;
layoutParams.height = height;
binding.ivAnimatedMessage.requestLayout();

View File

@ -6,7 +6,6 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.util.Pair;
import androidx.recyclerview.widget.ItemTouchHelper;
import com.facebook.drawee.drawable.ScalingUtils;
@ -31,6 +30,7 @@ import awais.instagrabber.repositories.responses.directmessages.DirectItem;
import awais.instagrabber.repositories.responses.directmessages.DirectItemClip;
import awais.instagrabber.repositories.responses.directmessages.DirectItemFelixShare;
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
import awais.instagrabber.utils.NullSafePair;
import awais.instagrabber.utils.NumberUtils;
import awais.instagrabber.utils.ResponseBodyUtils;
import awais.instagrabber.utils.Utils;
@ -103,15 +103,15 @@ public class DirectItemMediaShareViewHolder extends DirectItemViewHolder {
.setActualImageScaleType(ScalingUtils.ScaleType.CENTER_CROP)
.setRoundingParams(roundingParams)
.build());
final Pair<Integer, Integer> widthHeight = NumberUtils.calculateWidthHeight(
final NullSafePair<Integer, Integer> widthHeight = NumberUtils.calculateWidthHeight(
media.getOriginalHeight(),
media.getOriginalWidth(),
mediaImageMaxHeight,
mediaImageMaxWidth
);
final ViewGroup.LayoutParams layoutParams = binding.mediaPreview.getLayoutParams();
layoutParams.width = widthHeight.first != null ? widthHeight.first : 0;
layoutParams.height = widthHeight.second != null ? widthHeight.second : 0;
layoutParams.width = widthHeight.first;
layoutParams.height = widthHeight.second;
binding.mediaPreview.requestLayout();
binding.mediaPreview.setTag(url);
binding.mediaPreview.setImageURI(url);

View File

@ -4,7 +4,6 @@ import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.core.util.Pair;
import com.facebook.drawee.drawable.ScalingUtils;
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder;
@ -14,11 +13,11 @@ import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmMediaBinding;
import awais.instagrabber.models.enums.MediaItemType;
import awais.instagrabber.repositories.responses.ImageVersions2;
import awais.instagrabber.repositories.responses.Media;
import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
import awais.instagrabber.utils.NullSafePair;
import awais.instagrabber.utils.NumberUtils;
import awais.instagrabber.utils.ResponseBodyUtils;
@ -53,16 +52,16 @@ public class DirectItemMediaViewHolder extends DirectItemViewHolder {
binding.typeIcon.setVisibility(modelMediaType == MediaItemType.MEDIA_TYPE_VIDEO || modelMediaType == MediaItemType.MEDIA_TYPE_SLIDER
? View.VISIBLE
: View.GONE);
final Pair<Integer, Integer> widthHeight = NumberUtils.calculateWidthHeight(
final NullSafePair<Integer, Integer> widthHeight = NumberUtils.calculateWidthHeight(
media.getOriginalHeight(),
media.getOriginalWidth(),
mediaImageMaxHeight,
mediaImageMaxWidth
);
final ViewGroup.LayoutParams layoutParams = binding.mediaPreview.getLayoutParams();
final int width = widthHeight.first != null ? widthHeight.first : 0;
final int width = widthHeight.first;
layoutParams.width = width;
layoutParams.height = widthHeight.second != null ? widthHeight.second : 0;
layoutParams.height = widthHeight.second;
binding.mediaPreview.requestLayout();
binding.bgTime.getLayoutParams().width = width;
binding.bgTime.requestLayout();

View File

@ -4,7 +4,6 @@ import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.core.util.Pair;
import com.facebook.drawee.drawable.ScalingUtils;
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder;
@ -21,6 +20,7 @@ import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
import awais.instagrabber.repositories.responses.directmessages.DirectItemVisualMedia;
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
import awais.instagrabber.utils.NullSafePair;
import awais.instagrabber.utils.NumberUtils;
import awais.instagrabber.utils.ResponseBodyUtils;
import awais.instagrabber.utils.TextUtils;
@ -170,15 +170,15 @@ public class DirectItemRavenMediaViewHolder extends DirectItemViewHolder {
binding.typeIcon.setVisibility(modelMediaType == MediaItemType.MEDIA_TYPE_VIDEO || modelMediaType == MediaItemType.MEDIA_TYPE_SLIDER
? View.VISIBLE
: View.GONE);
final Pair<Integer, Integer> widthHeight = NumberUtils.calculateWidthHeight(
final NullSafePair<Integer, Integer> widthHeight = NumberUtils.calculateWidthHeight(
media.getOriginalHeight(),
media.getOriginalWidth(),
mediaImageMaxHeight,
maxWidth
);
final ViewGroup.LayoutParams layoutParams = binding.preview.getLayoutParams();
layoutParams.width = widthHeight.first != null ? widthHeight.first : 0;
layoutParams.height = widthHeight.second != null ? widthHeight.second : 0;
layoutParams.width = widthHeight.first;
layoutParams.height = widthHeight.second;
binding.preview.requestLayout();
final String thumbUrl = ResponseBodyUtils.getThumbUrl(media);
binding.preview.setImageURI(thumbUrl);

View File

@ -5,7 +5,6 @@ import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.core.util.Pair;
import androidx.recyclerview.widget.ItemTouchHelper;
import com.facebook.drawee.drawable.ScalingUtils;
@ -17,12 +16,12 @@ import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmStoryShareBinding;
import awais.instagrabber.models.enums.MediaItemType;
import awais.instagrabber.repositories.responses.ImageVersions2;
import awais.instagrabber.repositories.responses.Media;
import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
import awais.instagrabber.repositories.responses.directmessages.DirectItemStoryShare;
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
import awais.instagrabber.utils.NullSafePair;
import awais.instagrabber.utils.NumberUtils;
import awais.instagrabber.utils.ResponseBodyUtils;
import awais.instagrabber.utils.TextUtils;
@ -76,15 +75,15 @@ public class DirectItemStoryShareViewHolder extends DirectItemViewHolder {
.setRoundingParams(roundingParams)
.setActualImageScaleType(ScalingUtils.ScaleType.CENTER_CROP)
.build());
final Pair<Integer, Integer> widthHeight = NumberUtils.calculateWidthHeight(
final NullSafePair<Integer, Integer> widthHeight = NumberUtils.calculateWidthHeight(
storyShareMedia.getOriginalHeight(),
storyShareMedia.getOriginalWidth(),
mediaImageMaxHeight,
mediaImageMaxWidth
);
final ViewGroup.LayoutParams layoutParams = binding.ivMediaPreview.getLayoutParams();
layoutParams.width = widthHeight.first != null ? widthHeight.first : 0;
layoutParams.height = widthHeight.second != null ? widthHeight.second : 0;
layoutParams.width = widthHeight.first;
layoutParams.height = widthHeight.second;
binding.ivMediaPreview.requestLayout();
final String thumbUrl = ResponseBodyUtils.getThumbUrl(storyShareMedia);
binding.ivMediaPreview.setImageURI(thumbUrl);

View File

@ -4,7 +4,6 @@ import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.core.util.Pair;
import androidx.recyclerview.widget.ItemTouchHelper;
import com.facebook.drawee.backends.pipeline.Fresco;
@ -16,6 +15,7 @@ import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
import awais.instagrabber.repositories.responses.directmessages.DirectItemXma;
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
import awais.instagrabber.utils.NullSafePair;
import awais.instagrabber.utils.NumberUtils;
public class DirectItemXmaViewHolder extends DirectItemViewHolder {
@ -43,7 +43,7 @@ public class DirectItemXmaViewHolder extends DirectItemViewHolder {
}
final DirectItemXma.XmaUrlInfo urlInfo = playableUrlInfo != null ? playableUrlInfo : previewUrlInfo;
final String url = urlInfo.getUrl();
final Pair<Integer, Integer> widthHeight = NumberUtils.calculateWidthHeight(
final NullSafePair<Integer, Integer> widthHeight = NumberUtils.calculateWidthHeight(
urlInfo.getHeight(),
urlInfo.getWidth(),
mediaImageMaxHeight,
@ -51,8 +51,8 @@ public class DirectItemXmaViewHolder extends DirectItemViewHolder {
);
binding.ivAnimatedMessage.setVisibility(View.VISIBLE);
final ViewGroup.LayoutParams layoutParams = binding.ivAnimatedMessage.getLayoutParams();
final int width = widthHeight.first != null ? widthHeight.first : 0;
final int height = widthHeight.second != null ? widthHeight.second : 0;
final int width = widthHeight.first;
final int height = widthHeight.second;
layoutParams.width = width;
layoutParams.height = height;
binding.ivAnimatedMessage.requestLayout();

View File

@ -0,0 +1,157 @@
package awais.instagrabber.customviews;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatTextView;
import androidx.transition.TransitionManager;
import java.time.Duration;
import awais.instagrabber.customviews.helpers.ChangeText;
import awais.instagrabber.utils.NumberUtils;
public class FormattedNumberTextView extends AppCompatTextView {
private static final String TAG = FormattedNumberTextView.class.getSimpleName();
private static final ChangeText TRANSITION = new ChangeText().setChangeBehavior(ChangeText.CHANGE_BEHAVIOR_OUT_IN);
private long number = Long.MIN_VALUE;
private boolean showAbbreviation = true;
private boolean animateChanges = true;
private boolean toggleOnClick = true;
private boolean autoToggleToAbbreviation = true;
private long autoToggleTimeoutMs = Duration.ofSeconds(2).toMillis();
private boolean initDone = false;
public FormattedNumberTextView(@NonNull final Context context) {
super(context);
init();
}
public FormattedNumberTextView(@NonNull final Context context, @Nullable final AttributeSet attrs) {
super(context, attrs);
init();
}
public FormattedNumberTextView(@NonNull final Context context, @Nullable final AttributeSet attrs, final int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
if (initDone) return;
setupClickToggle();
initDone = true;
}
private void setupClickToggle() {
setOnClickListener(null);
}
private OnClickListener getWrappedClickListener(@Nullable final OnClickListener l) {
if (!toggleOnClick) {
return l;
}
return v -> {
toggleAbbreviation();
if (l != null) {
l.onClick(this);
}
};
}
public void setNumber(final long number) {
if (this.number == number) return;
this.number = number;
format();
}
public void clearNumber() {
if (number == Long.MIN_VALUE) return;
number = Long.MIN_VALUE;
format();
}
public void setShowAbbreviation(final boolean showAbbreviation) {
if (this.showAbbreviation && showAbbreviation) return;
this.showAbbreviation = showAbbreviation;
format();
}
public boolean isShowAbbreviation() {
return showAbbreviation;
}
private void toggleAbbreviation() {
if (number == Long.MIN_VALUE) return;
setShowAbbreviation(!showAbbreviation);
}
public void setToggleOnClick(final boolean toggleOnClick) {
this.toggleOnClick = toggleOnClick;
}
public boolean isToggleOnClick() {
return toggleOnClick;
}
public void setAutoToggleToAbbreviation(final boolean autoToggleToAbbreviation) {
this.autoToggleToAbbreviation = autoToggleToAbbreviation;
}
public boolean isAutoToggleToAbbreviation() {
return autoToggleToAbbreviation;
}
public void setAutoToggleTimeoutMs(final long autoToggleTimeoutMs) {
this.autoToggleTimeoutMs = autoToggleTimeoutMs;
}
public long getAutoToggleTimeoutMs() {
return autoToggleTimeoutMs;
}
public void setAnimateChanges(final boolean animateChanges) {
this.animateChanges = animateChanges;
}
public boolean isAnimateChanges() {
return animateChanges;
}
@Override
public void setOnClickListener(@Nullable final OnClickListener l) {
super.setOnClickListener(getWrappedClickListener(l));
}
private void format() {
post(() -> {
if (animateChanges) {
try {
TransitionManager.beginDelayedTransition((ViewGroup) getParent(), TRANSITION);
} catch (Exception e) {
Log.e(TAG, "format: ", e);
}
}
if (number == Long.MIN_VALUE) {
setText(null);
return;
}
if (showAbbreviation) {
setText(NumberUtils.abbreviate(number));
return;
}
setText(String.valueOf(number));
if (autoToggleToAbbreviation) {
getHandler().postDelayed(() -> setShowAbbreviation(true), autoToggleTimeoutMs);
}
});
}
}

View File

@ -6,6 +6,7 @@ import android.net.Uri;
import android.os.Looper;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.PopupMenu;
@ -22,11 +23,13 @@ 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.ui.AspectRatioFrameLayout;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.material.button.MaterialButton;
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";
@ -149,25 +152,25 @@ public class VideoPlayerViewHelper implements Player.EventListener {
if (thumbnailUrl != null) {
thumbnailRequest = ImageRequestBuilder.newBuilderWithSource(Uri.parse(thumbnailUrl)).build();
}
final PipelineDraweeControllerBuilder builder = Fresco.newDraweeControllerBuilder()
.setControllerListener(new BaseControllerListener<ImageInfo>() {
@Override
public void onFailure(final String id,
final Throwable throwable) {
if (videoPlayerCallback != null) {
videoPlayerCallback.onThumbnailLoaded();
}
}
final PipelineDraweeControllerBuilder builder = Fresco
.newDraweeControllerBuilder()
.setControllerListener(new BaseControllerListener<ImageInfo>() {
@Override
public void onFailure(final String id, final Throwable throwable) {
if (videoPlayerCallback != null) {
videoPlayerCallback.onThumbnailLoaded();
}
}
@Override
public void onFinalImageSet(final String id,
final ImageInfo imageInfo,
final Animatable animatable) {
if (videoPlayerCallback != null) {
videoPlayerCallback.onThumbnailLoaded();
}
}
});
@Override
public void onFinalImageSet(final String id,
final ImageInfo imageInfo,
final Animatable animatable) {
if (videoPlayerCallback != null) {
videoPlayerCallback.onThumbnailLoaded();
}
}
});
if (thumbnailRequest != null) {
builder.setImageRequest(thumbnailRequest);
}
@ -176,8 +179,8 @@ public class VideoPlayerViewHelper implements Player.EventListener {
private void loadPlayer() {
if (videoUrl == null) return;
if (binding.root.getDisplayedChild() == 0) {
binding.root.showNext();
if (binding.getRoot().getDisplayedChild() == 0) {
binding.getRoot().showNext();
}
if (videoPlayerCallback != null) {
videoPlayerCallback.onPlayerViewLoaded();
@ -186,6 +189,10 @@ public class VideoPlayerViewHelper implements Player.EventListener {
if (player != null) {
player.release();
}
final ViewGroup.LayoutParams playerViewLayoutParams = binding.playerView.getLayoutParams();
if (playerViewLayoutParams.height > Utils.displayMetrics.heightPixels * 0.8) {
playerViewLayoutParams.height = (int) (Utils.displayMetrics.heightPixels * 0.8);
}
player = new SimpleExoPlayer.Builder(context)
.setLooper(Looper.getMainLooper())
.build();
@ -206,8 +213,11 @@ public class VideoPlayerViewHelper implements Player.EventListener {
// setupControls();
player.prepare();
binding.playerView.setPlayer(player);
binding.playerView.setShowFastForwardButton(false);
binding.playerView.setShowRewindButton(false);
// binding.playerView.setShowFastForwardButton(false);
// binding.playerView.setShowRewindButton(false);
binding.playerView.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FIXED_HEIGHT);
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);

View File

@ -0,0 +1,320 @@
package awais.instagrabber.customviews.helpers;
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.graphics.Color;
import android.util.Log;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.transition.Transition;
import androidx.transition.TransitionListenerAdapter;
import androidx.transition.TransitionValues;
import java.util.Map;
import java.util.Objects;
import awais.instagrabber.BuildConfig;
/**
* This transition tracks changes to the text in TextView targets. If the text
* changes between the start and end scenes, the transition ensures that the
* starting text stays until the transition ends, at which point it changes
* to the end text. This is useful in situations where you want to resize a
* text view to its new size before displaying the text that goes there.
*/
public class ChangeText extends Transition {
private static final String LOG_TAG = "TextChange";
private static final String PROPNAME_TEXT = "android:textchange:text";
private static final String PROPNAME_TEXT_SELECTION_START =
"android:textchange:textSelectionStart";
private static final String PROPNAME_TEXT_SELECTION_END =
"android:textchange:textSelectionEnd";
private static final String PROPNAME_TEXT_COLOR = "android:textchange:textColor";
private int mChangeBehavior = CHANGE_BEHAVIOR_KEEP;
private boolean crossFade;
/**
* Flag specifying that the text in affected/changing TextView targets will keep
* their original text during the transition, setting it to the final text when
* the transition ends. This is the default behavior.
*
* @see #setChangeBehavior(int)
*/
public static final int CHANGE_BEHAVIOR_KEEP = 0;
/**
* Flag specifying that the text changing animation should first fade
* out the original text completely. The new text is set on the target
* view at the end of the fade-out animation. This transition is typically
* used with a later {@link #CHANGE_BEHAVIOR_IN} transition, allowing more
* flexibility than the {@link #CHANGE_BEHAVIOR_OUT_IN} by allowing other
* transitions to be run sequentially or in parallel with these fades.
*
* @see #setChangeBehavior(int)
*/
public static final int CHANGE_BEHAVIOR_OUT = 1;
/**
* Flag specifying that the text changing animation should fade in the
* end text into the affected target view(s). This transition is typically
* used in conjunction with an earlier {@link #CHANGE_BEHAVIOR_OUT}
* transition, possibly with other transitions running as well, such as
* a sequence to fade out, then resize the view, then fade in.
*
* @see #setChangeBehavior(int)
*/
public static final int CHANGE_BEHAVIOR_IN = 2;
/**
* Flag specifying that the text changing animation should first fade
* out the original text completely and then fade in the
* new text.
*
* @see #setChangeBehavior(int)
*/
public static final int CHANGE_BEHAVIOR_OUT_IN = 3;
private static final String[] sTransitionProperties = {
PROPNAME_TEXT,
PROPNAME_TEXT_SELECTION_START,
PROPNAME_TEXT_SELECTION_END
};
/**
* Sets the type of changing animation that will be run, one of
* {@link #CHANGE_BEHAVIOR_KEEP}, {@link #CHANGE_BEHAVIOR_OUT},
* {@link #CHANGE_BEHAVIOR_IN}, and {@link #CHANGE_BEHAVIOR_OUT_IN}.
*
* @param changeBehavior The type of fading animation to use when this
* transition is run.
* @return this textChange object.
*/
public ChangeText setChangeBehavior(int changeBehavior) {
if (changeBehavior >= CHANGE_BEHAVIOR_KEEP && changeBehavior <= CHANGE_BEHAVIOR_OUT_IN) {
mChangeBehavior = changeBehavior;
}
return this;
}
public ChangeText setCrossFade(final boolean crossFade) {
this.crossFade = crossFade;
return this;
}
@Override
public String[] getTransitionProperties() {
return sTransitionProperties;
}
/**
* Returns the type of changing animation that will be run.
*
* @return either {@link #CHANGE_BEHAVIOR_KEEP}, {@link #CHANGE_BEHAVIOR_OUT},
* {@link #CHANGE_BEHAVIOR_IN}, or {@link #CHANGE_BEHAVIOR_OUT_IN}.
*/
public int getChangeBehavior() {
return mChangeBehavior;
}
private void captureValues(TransitionValues transitionValues) {
if (transitionValues.view instanceof TextView) {
TextView textview = (TextView) transitionValues.view;
transitionValues.values.put(PROPNAME_TEXT, textview.getText());
if (textview instanceof EditText) {
transitionValues.values.put(PROPNAME_TEXT_SELECTION_START,
textview.getSelectionStart());
transitionValues.values.put(PROPNAME_TEXT_SELECTION_END,
textview.getSelectionEnd());
}
if (mChangeBehavior > CHANGE_BEHAVIOR_KEEP) {
transitionValues.values.put(PROPNAME_TEXT_COLOR, textview.getCurrentTextColor());
}
}
}
@Override
public void captureStartValues(@NonNull TransitionValues transitionValues) {
captureValues(transitionValues);
}
@Override
public void captureEndValues(@NonNull TransitionValues transitionValues) {
captureValues(transitionValues);
}
@Override
public Animator createAnimator(@NonNull ViewGroup sceneRoot, TransitionValues startValues,
TransitionValues endValues) {
if (startValues == null || endValues == null ||
!(startValues.view instanceof TextView) || !(endValues.view instanceof TextView)) {
return null;
}
final TextView view = (TextView) endValues.view;
Map<String, Object> startVals = startValues.values;
Map<String, Object> endVals = endValues.values;
final CharSequence startText = startVals.get(PROPNAME_TEXT) != null ?
(CharSequence) startVals.get(PROPNAME_TEXT) : "";
final CharSequence endText = endVals.get(PROPNAME_TEXT) != null ?
(CharSequence) endVals.get(PROPNAME_TEXT) : "";
final int startSelectionStart, startSelectionEnd, endSelectionStart, endSelectionEnd;
if (view instanceof EditText) {
startSelectionStart = startVals.get(PROPNAME_TEXT_SELECTION_START) != null ?
(Integer) startVals.get(PROPNAME_TEXT_SELECTION_START) : -1;
startSelectionEnd = startVals.get(PROPNAME_TEXT_SELECTION_END) != null ?
(Integer) startVals.get(PROPNAME_TEXT_SELECTION_END) : startSelectionStart;
endSelectionStart = endVals.get(PROPNAME_TEXT_SELECTION_START) != null ?
(Integer) endVals.get(PROPNAME_TEXT_SELECTION_START) : -1;
endSelectionEnd = endVals.get(PROPNAME_TEXT_SELECTION_END) != null ?
(Integer) endVals.get(PROPNAME_TEXT_SELECTION_END) : endSelectionStart;
} else {
startSelectionStart = startSelectionEnd = endSelectionStart = endSelectionEnd = -1;
}
if (!Objects.equals(startText, endText)) {
final int startColor;
final int endColor;
if (mChangeBehavior != CHANGE_BEHAVIOR_IN) {
view.setText(startText);
if (view instanceof EditText) {
setSelection(((EditText) view), startSelectionStart, startSelectionEnd);
}
}
Animator anim;
if (mChangeBehavior == CHANGE_BEHAVIOR_KEEP) {
startColor = endColor = 0;
anim = ValueAnimator.ofFloat(0, 1);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (Objects.equals(startText, view.getText())) {
// Only set if it hasn't been changed since anim started
view.setText(endText);
if (view instanceof EditText) {
setSelection(((EditText) view), endSelectionStart, endSelectionEnd);
}
}
}
});
} else {
startColor = (Integer) startVals.get(PROPNAME_TEXT_COLOR);
endColor = (Integer) endVals.get(PROPNAME_TEXT_COLOR);
// Fade out start text
ValueAnimator outAnim = null, inAnim = null;
if (mChangeBehavior == CHANGE_BEHAVIOR_OUT_IN ||
mChangeBehavior == CHANGE_BEHAVIOR_OUT) {
outAnim = ValueAnimator.ofInt(Color.alpha(startColor), 0);
outAnim.addUpdateListener(animation -> {
int currAlpha = (Integer) animation.getAnimatedValue();
view.setTextColor(currAlpha << 24 | startColor & 0xffffff);
});
outAnim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (Objects.equals(startText, view.getText())) {
// Only set if it hasn't been changed since anim started
view.setText(endText);
if (view instanceof EditText) {
setSelection(((EditText) view), endSelectionStart,
endSelectionEnd);
}
}
// restore opaque alpha and correct end color
view.setTextColor(endColor);
}
});
}
if (mChangeBehavior == CHANGE_BEHAVIOR_OUT_IN ||
mChangeBehavior == CHANGE_BEHAVIOR_IN) {
inAnim = ValueAnimator.ofInt(0, Color.alpha(endColor));
inAnim.addUpdateListener(animation -> {
int currAlpha = (Integer) animation.getAnimatedValue();
view.setTextColor(currAlpha << 24 | endColor & 0xffffff);
});
inAnim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationCancel(Animator animation) {
// restore opaque alpha and correct end color
view.setTextColor(endColor);
}
});
}
if (outAnim != null && inAnim != null) {
anim = new AnimatorSet();
final AnimatorSet animatorSet = (AnimatorSet) anim;
if (crossFade) {
animatorSet.playTogether(outAnim, inAnim);
} else {
animatorSet.playSequentially(outAnim, inAnim);
}
} else if (outAnim != null) {
anim = outAnim;
} else {
// Must be an in-only animation
anim = inAnim;
}
}
TransitionListener transitionListener = new TransitionListenerAdapter() {
int mPausedColor = 0;
@Override
public void onTransitionPause(@NonNull Transition transition) {
if (mChangeBehavior != CHANGE_BEHAVIOR_IN) {
view.setText(endText);
if (view instanceof EditText) {
setSelection(((EditText) view), endSelectionStart, endSelectionEnd);
}
}
if (mChangeBehavior > CHANGE_BEHAVIOR_KEEP) {
mPausedColor = view.getCurrentTextColor();
view.setTextColor(endColor);
}
}
@Override
public void onTransitionResume(@NonNull Transition transition) {
if (mChangeBehavior != CHANGE_BEHAVIOR_IN) {
view.setText(startText);
if (view instanceof EditText) {
setSelection(((EditText) view), startSelectionStart, startSelectionEnd);
}
}
if (mChangeBehavior > CHANGE_BEHAVIOR_KEEP) {
view.setTextColor(mPausedColor);
}
}
@Override
public void onTransitionEnd(Transition transition) {
transition.removeListener(this);
}
};
addListener(transitionListener);
if (BuildConfig.DEBUG) {
Log.d(LOG_TAG, "createAnimator returning " + anim);
}
return anim;
}
return null;
}
private void setSelection(EditText editText, int start, int end) {
if (start >= 0 && end >= 0) {
editText.setSelection(start, end);
}
}
}

View File

@ -1,6 +1,5 @@
package awais.instagrabber.fragments;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@ -12,10 +11,8 @@ import android.os.Bundle;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.util.Log;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
@ -25,9 +22,8 @@ import androidx.annotation.Nullable;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.appcompat.view.ContextThemeWrapper;
import androidx.appcompat.widget.PopupMenu;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.content.PermissionChecker;
import androidx.core.util.Pair;
import androidx.core.widget.NestedScrollView;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.LiveData;
@ -42,10 +38,11 @@ import androidx.transition.TransitionManager;
import androidx.viewpager2.widget.ViewPager2;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.drawee.drawable.ScalingUtils;
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.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.snackbar.BaseTransientBottomBar;
import com.google.android.material.snackbar.Snackbar;
@ -60,7 +57,11 @@ import awais.instagrabber.customviews.VerticalImageSpan;
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.ZoomableDraweeView;
import awais.instagrabber.databinding.DialogPostViewBinding;
import awais.instagrabber.databinding.LayoutPostViewBottomBinding;
import awais.instagrabber.databinding.LayoutVideoPlayerWithThumbnailBinding;
import awais.instagrabber.dialogs.EditTextDialogFragment;
import awais.instagrabber.models.Resource;
import awais.instagrabber.models.enums.MediaItemType;
@ -71,6 +72,7 @@ import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.repositories.responses.VideoVersion;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.DownloadUtils;
import awais.instagrabber.utils.NullSafePair;
import awais.instagrabber.utils.NumberUtils;
import awais.instagrabber.utils.ResponseBodyUtils;
import awais.instagrabber.utils.TextUtils;
@ -85,30 +87,26 @@ import static awais.instagrabber.utils.Utils.settingsHelper;
public class PostViewV2Fragment extends Fragment implements EditTextDialogFragment.EditTextDialogFragmentCallback {
private static final String TAG = "PostViewV2Fragment";
private static final int DETAILS_HIDE_DELAY_MILLIS = 2000;
// private static final int DETAILS_HIDE_DELAY_MILLIS = 2000;
public static final String ARG_MEDIA = "media";
public static final String ARG_SLIDER_POSITION = "position";
private static final int STORAGE_PERM_REQUEST_CODE = 8020;
// private Media media;
private DialogPostViewBinding binding;
// private MediaService mediaService;
// private Context context;
private BottomSheetBehavior<NestedScrollView> bottomSheetBehavior;
private boolean detailsVisible = true;
private boolean video;
private VideoPlayerViewHelper videoPlayerViewHelper;
private SliderItemsAdapter sliderItemsAdapter;
// private boolean wasControlsVisible;
private int captionState = BottomSheetBehavior.STATE_HIDDEN;
private int sliderPosition = -1;
private boolean hasBeenToggled = false;
private PostViewV2ViewModel viewModel;
private PopupMenu optionsPopup;
private EditTextDialogFragment editTextDialogFragment;
private boolean wasDeleted;
private MutableLiveData<Object> backStackSavedStateResultLiveData;
private OnDeleteListener onDeleteListener;
@Nullable
private ViewPager2 sliderParent;
private LayoutPostViewBottomBinding bottom;
private final Observer<Object> backStackSavedStateObserver = result -> {
if (result == null) return;
@ -119,13 +117,6 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
// clear result
backStackSavedStateResultLiveData.postValue(null);
};
private final GestureDetector.OnGestureListener videoPlayerViewGestureListener = new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapConfirmed(final MotionEvent e) {
binding.videoPost.playerView.performClick();
return true;
}
};
public void setOnDeleteListener(final OnDeleteListener onDeleteListener) {
if (onDeleteListener == null) return;
@ -143,8 +134,6 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
public void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
viewModel = new ViewModelProvider(this).get(PostViewV2ViewModel.class);
captionState = settingsHelper.getBoolean(Constants.SHOW_CAPTIONS) ?
BottomSheetBehavior.STATE_COLLAPSED : BottomSheetBehavior.STATE_HIDDEN;
}
@Nullable
@ -153,6 +142,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
@Nullable final ViewGroup container,
@Nullable final Bundle savedInstanceState) {
binding = DialogPostViewBinding.inflate(inflater, container, false);
bottom = LayoutPostViewBottomBinding.bind(binding.getRoot());
return binding.getRoot();
}
@ -166,9 +156,6 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
public void onPause() {
super.onPause();
// wasPaused = true;
if (bottomSheetBehavior != null) {
captionState = bottomSheetBehavior.getState();
}
if (settingsHelper.getBoolean(Constants.PLAY_IN_BACKGROUND)) return;
final Media media = viewModel.getMedia();
if (media == null) return;
@ -284,33 +271,35 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
viewModel.getLocation().observe(getViewLifecycleOwner(), location -> binding.getRoot().post(() -> setupLocation(location)));
viewModel.getDate().observe(getViewLifecycleOwner(), date -> binding.getRoot().post(() -> {
if (date == null) {
binding.date.setVisibility(View.GONE);
bottom.date.setVisibility(View.GONE);
return;
}
binding.date.setVisibility(View.VISIBLE);
binding.date.setText(date);
bottom.date.setVisibility(View.VISIBLE);
bottom.date.setText(date);
}));
viewModel.getLikeCount().observe(getViewLifecycleOwner(), count -> {
final long safeCount = getSafeCount(count);
final String likesString = getResources().getQuantityString(R.plurals.likes_count, (int) safeCount, safeCount);
binding.likesCount.setText(likesString);
bottom.likesCount.setAnimateChanges(false);
bottom.likesCount.setNumber(getSafeCount(count));
// final String likesString = getResources().getQuantityString(R.plurals.likes_count, (int) safeCount, safeCount);
// bottom.likesCount.setText(likesString);
});
if (!viewModel.getMedia().isCommentsDisabled()) {
viewModel.getCommentCount().observe(getViewLifecycleOwner(), count -> {
final long safeCount = getSafeCount(count);
final String likesString = getResources().getQuantityString(R.plurals.comments_count, (int) safeCount, safeCount);
binding.commentsCount.setText(likesString);
bottom.commentsCount.setAnimateChanges(false);
bottom.commentsCount.setNumber(getSafeCount(count));
// final String likesString = getResources().getQuantityString(R.plurals.comments_count, (int) safeCount, safeCount);
// bottom.commentsCount.setText(likesString);
});
}
viewModel.getViewCount().observe(getViewLifecycleOwner(), count -> {
if (count == null) {
binding.viewsCount.setVisibility(View.GONE);
bottom.viewsCount.setVisibility(View.GONE);
return;
}
binding.viewsCount.setVisibility(View.VISIBLE);
bottom.viewsCount.setVisibility(View.VISIBLE);
final long safeCount = getSafeCount(count);
final String viewString = getResources().getQuantityString(R.plurals.views_count, (int) safeCount, safeCount);
binding.viewsCount.setText(viewString);
bottom.viewsCount.setText(viewString);
});
viewModel.getType().observe(getViewLifecycleOwner(), this::setupPostTypeLayout);
viewModel.getLiked().observe(getViewLifecycleOwner(), this::setLikedResources);
@ -340,12 +329,12 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
private void setupComment() {
if (!viewModel.hasPk() || viewModel.getMedia().isCommentsDisabled()) {
binding.comment.setVisibility(View.GONE);
binding.commentsCount.setVisibility(View.GONE);
bottom.comment.setVisibility(View.GONE);
// bottom.commentsCount.setVisibility(View.GONE);
return;
}
binding.comment.setVisibility(View.VISIBLE);
binding.comment.setOnClickListener(v -> {
bottom.comment.setVisibility(View.VISIBLE);
bottom.comment.setOnClickListener(v -> {
final Media media = viewModel.getMedia();
final User user = media.getUser();
if (user == null) return;
@ -361,7 +350,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
Log.e(TAG, "setupComment: ", e);
}
});
binding.comment.setOnLongClickListener(v -> {
bottom.comment.setOnLongClickListener(v -> {
final Context context = getContext();
if (context == null) return false;
Utils.displayToastAboveView(context, v, getString(R.string.comment));
@ -370,7 +359,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
}
private void setupDownload() {
binding.download.setOnClickListener(v -> {
bottom.download.setOnClickListener(v -> {
final Context context = getContext();
if (context == null) return;
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) {
@ -379,7 +368,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
}
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
});
binding.download.setOnLongClickListener(v -> {
bottom.download.setOnLongClickListener(v -> {
final Context context = getContext();
if (context == null) return false;
Utils.displayToastAboveView(context, v, getString(R.string.action_download));
@ -390,19 +379,19 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
private void setupLike() {
final boolean likableMedia = viewModel.hasPk() /*&& viewModel.getMedia().isCommentLikesEnabled()*/;
if (!likableMedia) {
binding.like.setVisibility(View.GONE);
binding.likesCount.setVisibility(View.GONE);
bottom.like.setVisibility(View.GONE);
// bottom.likesCount.setVisibility(View.GONE);
return;
}
if (!viewModel.isLoggedIn()) {
binding.like.setVisibility(View.GONE);
bottom.like.setVisibility(View.GONE);
return;
}
binding.like.setOnClickListener(v -> {
bottom.like.setOnClickListener(v -> {
v.setEnabled(false);
handleLikeUnlikeResourceLiveData(viewModel.toggleLike());
});
binding.like.setOnLongClickListener(v -> {
bottom.like.setOnLongClickListener(v -> {
final NavController navController = getNavController();
if (navController != null && viewModel.isLoggedIn()) {
final Bundle bundle = new Bundle();
@ -419,14 +408,14 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
resource.observe(getViewLifecycleOwner(), value -> {
switch (value.status) {
case SUCCESS:
binding.like.setEnabled(true);
bottom.like.setEnabled(true);
break;
case ERROR:
binding.like.setEnabled(true);
bottom.like.setEnabled(true);
unsuccessfulLike();
break;
case LOADING:
binding.like.setEnabled(false);
bottom.like.setEnabled(false);
break;
}
});
@ -464,20 +453,20 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
tintResource = getAttrValue(context, R.attr.colorPrimary);
// textResId = R.string.like_without_count;
}
binding.like.setIconResource(iconResource);
binding.like.setIconTint(ColorStateList.valueOf(tintResource));
bottom.like.setIconResource(iconResource);
bottom.like.setIconTint(ColorStateList.valueOf(tintResource));
}
private void setupSave() {
if (!viewModel.isLoggedIn() || !viewModel.hasPk() || !viewModel.getMedia().canViewerSave()) {
binding.save.setVisibility(View.GONE);
bottom.save.setVisibility(View.GONE);
return;
}
binding.save.setOnClickListener(v -> {
binding.save.setEnabled(false);
bottom.save.setOnClickListener(v -> {
bottom.save.setEnabled(false);
handleSaveUnsaveResourceLiveData(viewModel.toggleSave());
});
binding.save.setOnLongClickListener(v -> {
bottom.save.setOnLongClickListener(v -> {
final NavController navController = NavHostFragment.findNavController(this);
final Bundle bundle = new Bundle();
bundle.putBoolean("isSaving", true);
@ -491,14 +480,14 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
if (value == null) return;
switch (value.status) {
case SUCCESS:
binding.save.setEnabled(true);
bottom.save.setEnabled(true);
break;
case ERROR:
binding.save.setEnabled(true);
bottom.save.setEnabled(true);
unsuccessfulSave();
break;
case LOADING:
binding.save.setEnabled(false);
bottom.save.setEnabled(false);
break;
}
});
@ -527,16 +516,16 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
final Resources resources = context.getResources();
if (resources == null) return;
if (saved) {
iconResource = R.drawable.ic_class_24;
iconResource = R.drawable.ic_bookmark;
tintResource = resources.getColor(R.color.blue_700);
// textResId = R.string.saved;
} else {
iconResource = R.drawable.ic_outline_class_24;
iconResource = R.drawable.ic_round_bookmark_border_24;
tintResource = getAttrValue(context, R.attr.colorPrimary);
// textResId = R.string.save;
}
binding.save.setIconResource(iconResource);
binding.save.setIconTint(ColorStateList.valueOf(tintResource));
bottom.save.setIconResource(iconResource);
bottom.save.setIconTint(ColorStateList.valueOf(tintResource));
}
private void setupProfilePic(final User user) {
@ -598,32 +587,32 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
private void setupCaption(final Caption caption) {
if (caption == null || TextUtils.isEmpty(caption.getText())) {
binding.caption.setVisibility(View.GONE);
binding.translate.setVisibility(View.GONE);
bottom.caption.setVisibility(View.GONE);
bottom.translate.setVisibility(View.GONE);
return;
}
final String postCaption = caption.getText();
binding.caption.addOnHashtagListener(autoLinkItem -> {
bottom.caption.addOnHashtagListener(autoLinkItem -> {
final NavController navController = NavHostFragment.findNavController(this);
final Bundle bundle = new Bundle();
final String originalText = autoLinkItem.getOriginalText().trim();
bundle.putString(ARG_HASHTAG, originalText);
navController.navigate(R.id.action_global_hashTagFragment, bundle);
});
binding.caption.addOnMentionClickListener(autoLinkItem -> {
bottom.caption.addOnMentionClickListener(autoLinkItem -> {
final String originalText = autoLinkItem.getOriginalText().trim();
navigateToProfile(originalText);
});
binding.caption.addOnEmailClickListener(autoLinkItem -> Utils.openEmailAddress(getContext(), autoLinkItem.getOriginalText().trim()));
binding.caption.addOnURLClickListener(autoLinkItem -> Utils.openURL(getContext(), autoLinkItem.getOriginalText().trim()));
binding.caption.setOnLongClickListener(v -> {
bottom.caption.addOnEmailClickListener(autoLinkItem -> Utils.openEmailAddress(getContext(), autoLinkItem.getOriginalText().trim()));
bottom.caption.addOnURLClickListener(autoLinkItem -> Utils.openURL(getContext(), autoLinkItem.getOriginalText().trim()));
bottom.caption.setOnLongClickListener(v -> {
final Context context = getContext();
if (context == null) return false;
Utils.copyText(context, postCaption);
return true;
});
binding.caption.setText(postCaption);
binding.translate.setOnClickListener(v -> handleTranslateCaptionResource(viewModel.translateCaption()));
bottom.caption.setText(postCaption);
bottom.translate.setOnClickListener(v -> handleTranslateCaptionResource(viewModel.translateCaption()));
}
private void handleTranslateCaptionResource(@NonNull final LiveData<Resource<String>> data) {
@ -631,11 +620,11 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
if (resource == null) return;
switch (resource.status) {
case SUCCESS:
binding.translate.setVisibility(View.GONE);
binding.caption.setText(resource.data);
bottom.translate.setVisibility(View.GONE);
bottom.caption.setText(resource.data);
break;
case ERROR:
binding.translate.setEnabled(true);
bottom.translate.setEnabled(true);
String message = resource.message;
if (TextUtils.isEmpty(resource.message)) {
message = getString(R.string.downloader_unknown_error);
@ -645,7 +634,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
snackbar.show();
break;
case LOADING:
binding.translate.setEnabled(false);
bottom.translate.setEnabled(false);
break;
}
});
@ -671,17 +660,17 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
private void setupShare() {
if (!viewModel.hasPk()) {
binding.share.setVisibility(View.GONE);
bottom.share.setVisibility(View.GONE);
return;
}
binding.share.setVisibility(View.VISIBLE);
binding.share.setOnLongClickListener(v -> {
bottom.share.setVisibility(View.VISIBLE);
bottom.share.setOnLongClickListener(v -> {
final Context context = getContext();
if (context == null) return false;
Utils.displayToastAboveView(context, v, getString(R.string.share));
return true;
});
binding.share.setOnClickListener(v -> {
bottom.share.setOnClickListener(v -> {
final Media media = viewModel.getMedia();
final User profileModel = media.getUser();
if (profileModel == null) return;
@ -692,7 +681,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
// is this necessary?
Toast.makeText(context, R.string.share_private_post, Toast.LENGTH_LONG).show();
}
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
final Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, "https://instagram.com/p/" + media.getCode());
startActivity(Intent.createChooser(sharingIntent,
@ -715,82 +704,86 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
}
}
@SuppressLint("ClickableViewAccessibility")
private void setupPostImage() {
binding.videoPost.root.setVisibility(View.GONE);
binding.sliderParent.setVisibility(View.GONE);
// binding.playerControlsToggle.setVisibility(View.GONE);
// binding.playerControls.getRoot().setVisibility(View.GONE);
binding.mediaCounter.setVisibility(View.GONE);
binding.postImage.setVisibility(View.VISIBLE);
final Context context = getContext();
if (context == null) return;
final Resources resources = context.getResources();
if (resources == null) return;
final Media media = viewModel.getMedia();
final String imageUrl = ResponseBodyUtils.getImageUrl(media);
if (TextUtils.isEmpty(imageUrl)) return;
final ViewGroup.LayoutParams layoutParams = binding.postImage.getLayoutParams();
final Pair<Integer, Integer> widthHeight = NumberUtils.calculateWidthHeight(media.getOriginalHeight(),
media.getOriginalWidth(),
(int) (Utils.displayMetrics.heightPixels * 0.8),
Utils.displayMetrics.widthPixels);
layoutParams.height = widthHeight.second;
final ImageRequest requestBuilder = ImageRequestBuilder.newBuilderWithSource(Uri.parse(imageUrl))
.setLocalThumbnailPreviewsEnabled(true)
.build();
final DraweeController controller = Fresco
.newDraweeControllerBuilder()
.setLowResImageRequest(ImageRequest.fromUri(ResponseBodyUtils.getThumbUrl(media)))
.setImageRequest(requestBuilder)
.build();
binding.postImage.setController(controller);
// binding.postImage.setOnClickListener(v -> toggleDetails());
final AnimatedZoomableController zoomableController = (AnimatedZoomableController) binding.postImage.getZoomableController();
final ZoomableDraweeView postImage = new ZoomableDraweeView(context);
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);
layoutParams.topToBottom = binding.topBarrier.getId();
layoutParams.bottomToTop = bottom.buttonsTopBarrier.getId();
layoutParams.startToStart = ConstraintLayout.LayoutParams.PARENT_ID;
layoutParams.endToEnd = ConstraintLayout.LayoutParams.PARENT_ID;
postImage.setLayoutParams(layoutParams);
postImage.setHierarchy(new GenericDraweeHierarchyBuilder(resources)
.setActualImageScaleType(ScalingUtils.ScaleType.FIT_CENTER)
.build());
postImage.setController(Fresco.newDraweeControllerBuilder()
.setLowResImageRequest(ImageRequest.fromUri(ResponseBodyUtils.getThumbUrl(media)))
.setImageRequest(ImageRequestBuilder.newBuilderWithSource(Uri.parse(imageUrl))
.setLocalThumbnailPreviewsEnabled(true)
.build())
.build());
final AnimatedZoomableController zoomableController = (AnimatedZoomableController) postImage.getZoomableController();
zoomableController.setMaxScaleFactor(3f);
zoomableController.setGestureZoomEnabled(true);
zoomableController.setEnabled(true);
binding.postImage.setZoomingEnabled(true);
binding.postImage.setTapListener(new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(final MotionEvent e) {
// toggleDetails();
return true;
}
});
postImage.setZoomingEnabled(true);
postImage.setTapListener(new DoubleTapGestureListener(postImage));
binding.contentRoot.addView(postImage, 0);
// binding.postImage.setAllowTouchInterceptionWhileZoomed(true);
// binding.postImage.setOnVerticalDragListener(onVerticalDragListener);
}
private void setupSlider() {
final Media media = viewModel.getMedia();
binding.postImage.setVisibility(View.GONE);
binding.videoPost.root.setVisibility(View.GONE);
// binding.playerControlsToggle.setVisibility(View.GONE);
// binding.playerControls.getRoot().setVisibility(View.GONE);
binding.sliderParent.setVisibility(View.VISIBLE);
binding.mediaCounter.setVisibility(View.VISIBLE);
final Pair<Integer, Integer> maxHW = media
final Context context = getContext();
if (context == null) return;
sliderParent = new ViewPager2(context);
final NullSafePair<Integer, Integer> maxHW = media
.getCarouselMedia()
.stream()
.reduce(new Pair<>(0, 0),
.reduce(new NullSafePair<>(0, 0),
(prev, m) -> {
final int height = m.getOriginalHeight() > prev.first ? m.getOriginalHeight() : prev.first;
final int width = m.getOriginalWidth() > prev.second ? m.getOriginalWidth() : prev.second;
return new Pair<>(height, width);
return new NullSafePair<>(height, width);
},
(p1, p2) -> {
final int height = p1.first > p2.first ? p1.first : p2.first;
final int width = p1.second > p2.second ? p1.second : p2.second;
return new Pair<>(height, width);
return new NullSafePair<>(height, width);
});
final ViewGroup.LayoutParams layoutParams = binding.sliderParent.getLayoutParams();
final Pair<Integer, Integer> widthHeight = NumberUtils.calculateWidthHeight(maxHW.first,
maxHW.second,
(int) (Utils.displayMetrics.heightPixels * 0.8),
Utils.displayMetrics.widthPixels);
layoutParams.height = widthHeight.second;
final NullSafePair<Integer, Integer> widthHeight = NumberUtils.calculateWidthHeight(maxHW.first,
maxHW.second,
(int) (Utils.displayMetrics.heightPixels * 0.8),
Utils.displayMetrics.widthPixels);
final ConstraintLayout.LayoutParams layoutParams = new ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.MATCH_PARENT,
widthHeight.second);
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);
binding.contentRoot.addView(sliderParent, 0);
final boolean hasVideo = media.getCarouselMedia()
.stream()
.anyMatch(postChild -> postChild.getMediaType() == MediaItemType.MEDIA_TYPE_VIDEO);
if (hasVideo) {
final View child = binding.sliderParent.getChildAt(0);
final View child = sliderParent.getChildAt(0);
if (child instanceof RecyclerView) {
((RecyclerView) child).setItemViewCacheSize(media.getCarouselMedia().size());
((RecyclerView) child).addRecyclerListener(holder -> {
@ -837,17 +830,17 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
Utils.disableKeepScreenOn(activity);
}
});
binding.sliderParent.setAdapter(sliderItemsAdapter);
sliderParent.setAdapter(sliderItemsAdapter);
if (sliderPosition >= 0 && sliderPosition < media.getCarouselMedia().size()) {
binding.sliderParent.setCurrentItem(sliderPosition);
sliderParent.setCurrentItem(sliderPosition);
}
binding.sliderParent.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
sliderParent.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
int prevPosition = -1;
@Override
public void onPageScrolled(final int position, final float positionOffset, final int positionOffsetPixels) {
if (prevPosition != -1) {
final View view = binding.sliderParent.getChildAt(0);
final View view = sliderParent.getChildAt(0);
if (view instanceof RecyclerView) {
pausePlayerAtPosition(prevPosition, (RecyclerView) view);
pausePlayerAtPosition(position, (RecyclerView) view);
@ -905,9 +898,9 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
}
private void pauseSliderPlayer() {
if (binding.sliderParent.getVisibility() != View.VISIBLE) return;
final int currentItem = binding.sliderParent.getCurrentItem();
final View view = binding.sliderParent.getChildAt(0);
if (sliderParent == null) return;
final int currentItem = sliderParent.getCurrentItem();
final View view = sliderParent.getChildAt(0);
if (!(view instanceof RecyclerView)) return;
final RecyclerView.ViewHolder viewHolder = ((RecyclerView) view).findViewHolderForAdapterPosition(currentItem);
if (!(viewHolder instanceof SliderVideoViewHolder)) return;
@ -915,8 +908,8 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
}
private void releaseAllSliderPlayers() {
if (binding.sliderParent.getVisibility() != View.VISIBLE) return;
final View view = binding.sliderParent.getChildAt(0);
if (sliderParent == null) return;
final View view = sliderParent.getChildAt(0);
if (!(view instanceof RecyclerView)) return;
final int itemCount = sliderItemsAdapter.getItemCount();
for (int position = itemCount - 1; position >= 0; position--) {
@ -926,30 +919,38 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
}
}
@SuppressLint("ClickableViewAccessibility")
private void setupVideo() {
video = true;
final Media media = viewModel.getMedia();
binding.postImage.setVisibility(View.GONE);
binding.sliderParent.setVisibility(View.GONE);
binding.mediaCounter.setVisibility(View.GONE);
// binding.playerControls.getRoot().setVisibility(View.VISIBLE);
final ViewGroup.LayoutParams layoutParams = binding.videoPost.root.getLayoutParams();
final Pair<Integer, Integer> widthHeight = NumberUtils.calculateWidthHeight(media.getOriginalHeight(),
media.getOriginalWidth(),
(int) (Utils.displayMetrics.heightPixels * 0.8),
Utils.displayMetrics.widthPixels);
layoutParams.height = widthHeight.second;
binding.videoPost.root.setVisibility(View.VISIBLE);
// enablePlayerControls(true);
// binding.videoPost.playerView.setOnClickListener(v -> toggleDetails());
final Context context = getContext();
if (context == null) return;
final GestureDetector gestureDetector = new GestureDetector(context, videoPlayerViewGestureListener);
binding.videoPost.playerView.setOnTouchListener((v, event) -> {
gestureDetector.onTouchEvent(event);
return true;
});
final LayoutVideoPlayerWithThumbnailBinding videoPost = LayoutVideoPlayerWithThumbnailBinding
.inflate(LayoutInflater.from(context), binding.contentRoot, false);
final ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) videoPost.getRoot().getLayoutParams();
final NullSafePair<Integer, Integer> widthHeight = NumberUtils.calculateWidthHeight(media.getOriginalHeight(),
media.getOriginalWidth(),
(int) (Utils.displayMetrics.heightPixels * 0.8),
Utils.displayMetrics.widthPixels);
layoutParams.width = ConstraintLayout.LayoutParams.MATCH_PARENT;
layoutParams.height = widthHeight.second;
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);
// final GestureDetector gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
// @Override
// public boolean onSingleTapConfirmed(final MotionEvent e) {
// videoPost.playerView.performClick();
// return true;
// }
// });
// videoPost.playerView.setOnTouchListener((v, event) -> {
// gestureDetector.onTouchEvent(event);
// return true;
// });
final float vol = settingsHelper.getBoolean(Constants.MUTED_VIDEOS) ? 0f : 1f;
final VideoPlayerViewHelper.VideoPlayerCallback videoPlayerCallback = new VideoPlayerCallbackAdapter() {
@Override
@ -960,13 +961,13 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
@Override
public void onPlayerViewLoaded() {
// binding.playerControls.getRoot().setVisibility(View.VISIBLE);
final ViewGroup.LayoutParams layoutParams = binding.videoPost.playerView.getLayoutParams();
final ViewGroup.LayoutParams layoutParams = videoPost.playerView.getLayoutParams();
final int requiredWidth = Utils.displayMetrics.widthPixels;
final int resultingHeight = NumberUtils
.getResultingHeight(requiredWidth, media.getOriginalHeight(), media.getOriginalWidth());
layoutParams.width = requiredWidth;
layoutParams.height = resultingHeight;
binding.videoPost.playerView.requestLayout();
videoPost.playerView.requestLayout();
}
@Override
@ -1005,13 +1006,12 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
if (videoUrl != null) {
videoPlayerViewHelper = new VideoPlayerViewHelper(
binding.getRoot().getContext(),
binding.videoPost,
videoPost,
videoUrl,
vol,
aspectRatio,
ResponseBodyUtils.getThumbUrl(media),
true,
// /*binding.playerControls*/null,
videoPlayerCallback);
}
}
@ -1234,7 +1234,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
}
private void toggleDetails() {
hasBeenToggled = true;
// hasBeenToggled = true;
final Media media = viewModel.getMedia();
binding.getRoot().post(() -> {
TransitionManager.beginDelayedTransition(binding.getRoot());
@ -1249,20 +1249,17 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
if (media.getLocation() != null) {
binding.location.setVisibility(View.GONE);
}
// binding.captionParent.setVisibility(View.GONE);
binding.bottomBg.setVisibility(View.GONE);
binding.likesCount.setVisibility(View.GONE);
binding.commentsCount.setVisibility(View.GONE);
binding.date.setVisibility(View.GONE);
binding.comment.setVisibility(View.GONE);
// binding.captionToggle.setVisibility(View.GONE);
// binding.playerControlsToggle.setVisibility(View.GONE);
binding.like.setVisibility(View.GONE);
binding.save.setVisibility(View.GONE);
binding.share.setVisibility(View.GONE);
binding.download.setVisibility(View.GONE);
// bottom.bottomBg.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.download.setVisibility(View.GONE);
binding.mediaCounter.setVisibility(View.GONE);
binding.viewsCount.setVisibility(View.GONE);
bottom.viewsCount.setVisibility(View.GONE);
final List<Integer> options = viewModel.getOptions().getValue();
if (options != null && !options.isEmpty()) {
binding.options.setVisibility(View.GONE);
@ -1282,30 +1279,30 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
if (media.getLocation() != null) {
binding.location.setVisibility(View.VISIBLE);
}
binding.bottomBg.setVisibility(View.VISIBLE);
// bottom.bottomBg.setVisibility(View.VISIBLE);
if (viewModel.hasPk()) {
binding.likesCount.setVisibility(View.VISIBLE);
binding.date.setVisibility(View.VISIBLE);
// bottom.likesCount.setVisibility(View.VISIBLE);
bottom.date.setVisibility(View.VISIBLE);
// binding.captionParent.setVisibility(View.VISIBLE);
// binding.captionToggle.setVisibility(View.VISIBLE);
binding.share.setVisibility(View.VISIBLE);
// bottom.share.setVisibility(View.VISIBLE);
}
if (viewModel.hasPk() && !viewModel.getMedia().isCommentsDisabled()) {
binding.comment.setVisibility(View.VISIBLE);
binding.commentsCount.setVisibility(View.VISIBLE);
bottom.comment.setVisibility(View.VISIBLE);
// bottom.commentsCount.setVisibility(View.VISIBLE);
}
binding.download.setVisibility(View.VISIBLE);
bottom.download.setVisibility(View.VISIBLE);
final List<Integer> options = viewModel.getOptions().getValue();
if (options != null && !options.isEmpty()) {
binding.options.setVisibility(View.VISIBLE);
}
if (viewModel.isLoggedIn() && viewModel.hasPk()) {
binding.like.setVisibility(View.VISIBLE);
binding.save.setVisibility(View.VISIBLE);
bottom.like.setVisibility(View.VISIBLE);
bottom.save.setVisibility(View.VISIBLE);
}
if (video) {
// binding.playerControlsToggle.setVisibility(View.VISIBLE);
binding.viewsCount.setVisibility(View.VISIBLE);
bottom.viewsCount.setVisibility(View.VISIBLE);
}
// if (wasControlsVisible) {
// showPlayerControls();

View File

@ -0,0 +1,91 @@
package awais.instagrabber.utils;
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.util.ObjectsCompat;
/**
* Container to ease passing around a tuple of two objects. This object provides a sensible
* implementation of equals(), returning true if equals() is true on each of the contained
* objects.
*/
public class NullSafePair<F, S> {
public final @NonNull
F first;
public final @NonNull
S second;
/**
* Constructor for a Pair.
*
* @param first the first object in the Pair
* @param second the second object in the pair
*/
public NullSafePair(@NonNull F first, @NonNull S second) {
this.first = first;
this.second = second;
}
/**
* Checks the two objects for equality by delegating to their respective
* {@link Object#equals(Object)} methods.
*
* @param o the {@link androidx.core.util.Pair} to which this one is to be checked for equality
* @return true if the underlying objects of the Pair are both considered
* equal
*/
@Override
public boolean equals(Object o) {
if (!(o instanceof androidx.core.util.Pair)) {
return false;
}
androidx.core.util.Pair<?, ?> p = (androidx.core.util.Pair<?, ?>) o;
return ObjectsCompat.equals(p.first, first) && ObjectsCompat.equals(p.second, second);
}
/**
* Compute a hash code using the hash codes of the underlying objects
*
* @return a hashcode of the Pair
*/
@Override
public int hashCode() {
return first.hashCode() ^ second.hashCode();
}
@NonNull
@Override
public String toString() {
return "Pair{" + first + " " + second + "}";
}
/**
* Convenience method for creating an appropriately typed pair.
*
* @param a the first object in the Pair
* @param b the second object in the pair
* @return a Pair that is templatized with the types of a and b
*/
@NonNull
public static <A, B> androidx.core.util.Pair<A, B> create(@Nullable A a, @Nullable B b) {
return new androidx.core.util.Pair<A, B>(a, b);
}
}

View File

@ -1,8 +1,9 @@
package awais.instagrabber.utils;
import androidx.annotation.NonNull;
import androidx.core.util.Pair;
import androidx.annotation.Nullable;
import java.util.Locale;
import java.util.Random;
public final class NumberUtils {
@ -56,7 +57,7 @@ public final class NumberUtils {
}
@NonNull
public static Pair<Integer, Integer> calculateWidthHeight(final int height, final int width, final int maxHeight, final int maxWidth) {
public static NullSafePair<Integer, Integer> calculateWidthHeight(final int height, final int width, final int maxHeight, final int maxWidth) {
if (width > maxWidth) {
int tempHeight = getResultingHeight(maxWidth, height, width);
int tempWidth = maxWidth;
@ -64,7 +65,7 @@ public final class NumberUtils {
tempWidth = getResultingWidth(maxHeight, tempHeight, tempWidth);
tempHeight = maxHeight;
}
return new Pair<>(tempWidth, tempHeight);
return new NullSafePair<>(tempWidth, tempHeight);
}
if ((height < maxHeight && width < maxWidth) || (height > maxHeight)) {
int tempWidth = getResultingWidth(maxHeight, height, width);
@ -73,12 +74,76 @@ public final class NumberUtils {
tempHeight = getResultingHeight(maxWidth, tempHeight, tempWidth);
tempWidth = maxWidth;
}
return new Pair<>(tempWidth, tempHeight);
return new NullSafePair<>(tempWidth, tempHeight);
}
return new Pair<>(width, height);
return new NullSafePair<>(width, height);
}
public static float roundFloat2Decimals(final float value) {
return ((int) ((value + (value >= 0 ? 1 : -1) * 0.005f) * 100)) / 100f;
}
@NonNull
public static String abbreviate(final long number) {
return abbreviate(number, null);
}
@NonNull
public static String abbreviate(final long number, @Nullable final AbbreviateOptions options) {
// adapted from https://stackoverflow.com/a/9769590/1436766
int threshold = 1000;
boolean addSpace = false;
if (options != null) {
threshold = options.getThreshold();
addSpace = options.addSpaceBeforePrefix();
}
if (number < threshold) return "" + number;
int exp = (int) (Math.log(number) / Math.log(threshold));
return String.format(Locale.US,
"%.1f%s%c",
number / Math.pow(threshold, exp),
addSpace ? " " : "",
"kMGTPE".charAt(exp - 1));
}
public static final class AbbreviateOptions {
private final int threshold;
private final boolean addSpaceBeforePrefix;
public static final class Builder {
private int threshold = 1000;
private boolean addSpaceBeforePrefix = false;
public Builder setThreshold(final int threshold) {
this.threshold = threshold;
return this;
}
public Builder setAddSpaceBeforePrefix(final boolean addSpaceBeforePrefix) {
this.addSpaceBeforePrefix = addSpaceBeforePrefix;
return this;
}
@NonNull
public AbbreviateOptions build() {
return new AbbreviateOptions(threshold, addSpaceBeforePrefix);
}
}
private AbbreviateOptions(final int threshold, final boolean addSpaceBeforePrefix) {
this.threshold = threshold;
this.addSpaceBeforePrefix = addSpaceBeforePrefix;
}
public int getThreshold() {
return threshold;
}
public boolean addSpaceBeforePrefix() {
return addSpaceBeforePrefix;
}
}
}

View File

@ -1,10 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#333333">
<path
android:fillColor="@android:color/white"
android:pathData="M17,3H7c-1.1,0 -1.99,0.9 -1.99,2L5,21l7,-3 7,3V5c0,-1.1 -0.9,-2 -2,-2z"/>
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M17,3H7c-1.1,0 -1.99,0.9 -1.99,2L5,21l7,-3 7,3V5c0,-1.1 -0.9,-2 -2,-2z" />
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M17,3L7,3c-1.1,0 -2,0.9 -2,2v16l7,-3 7,3L19,5c0,-1.1 -0.9,-2 -2,-2zM17,18l-5,-2.18L7,18L7,6c0,-0.55 0.45,-1 1,-1h8c0.55,0 1,0.45 1,1v12z"/>
</vector>

View File

@ -3,59 +3,14 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
tools:context=".fragments.PostViewV2Fragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/content_root"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<awais.instagrabber.customviews.drawee.ZoomableDraweeView
android:id="@+id/post_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:clickable="true"
android:focusable="true"
android:transitionName="post_image"
app:actualImageScaleType="fitCenter"
app:layout_constraintBottom_toTopOf="@id/bottom_bg_barrier"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/top_barrier"
tools:background="@mipmap/ic_launcher"
tools:layout_height="400dp"
tools:visibility="gone" />
<include
android:id="@+id/video_post"
layout="@layout/layout_video_player_with_thumbnail"
android:layout_width="match_parent"
android:layout_height="0dp"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@id/bottom_bg_barrier"
app:layout_constraintTop_toBottomOf="@id/top_barrier"
tools:layout_height="400dp"
tools:visibility="visible" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/slider_parent"
android:layout_width="match_parent"
android:layout_height="0dp"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@id/bottom_bg_barrier"
app:layout_constraintTop_toBottomOf="@id/top_barrier"
tools:layout_height="400dp"
tools:visibility="gone" />
<!--<View-->
<!-- android:id="@+id/top_bg"-->
<!-- android:layout_width="0dp"-->
<!-- android:layout_height="0dp"-->
<!-- app:layout_constraintBottom_toBottomOf="@id/profile_pic"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toTopOf="parent" />-->
<awais.instagrabber.customviews.ProfilePicView
android:id="@+id/profile_pic"
android:layout_width="wrap_content"
@ -118,12 +73,6 @@
app:barrierAllowsGoneWidgets="true"
app:barrierDirection="bottom" />
<!--<androidx.constraintlayout.widget.Group-->
<!-- android:id="@+id/user_details_group"-->
<!-- android:layout_width="0dp"-->
<!-- android:layout_height="0dp"-->
<!-- app:constraint_referenced_ids="profile_pic,title,subtitle,options" />-->
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/media_counter"
android:layout_width="wrap_content"
@ -172,343 +121,7 @@
tools:text="Location, Location, Location, Location, "
tools:visibility="visible" />
<!--<androidx.coordinatorlayout.widget.CoordinatorLayout-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="0dp"-->
<!-- android:background="@null"-->
<!-- app:layout_constraintBottom_toBottomOf="@id/bottom_bg_barrier"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toTopOf="parent"-->
<!-- tools:visibility="gone">-->
<!-- <androidx.core.widget.NestedScrollView-->
<!-- android:id="@+id/caption_parent"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:background="@color/black_a80"-->
<!-- app:behavior_hideable="true"-->
<!-- app:behavior_peekHeight="100dp"-->
<!-- app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">-->
<!-- <ScrollView-->
<!-- android:id="@+id/bottom_scroll_view"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="match_parent"-->
<!-- android:background="@null">-->
<!-- <LinearLayout-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:orientation="vertical">-->
<!-- <awais.instagrabber.customviews.RamboTextViewV2-->
<!-- android:id="@+id/caption"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_gravity="bottom"-->
<!-- android:background="@null"-->
<!-- android:clickable="true"-->
<!-- android:focusable="true"-->
<!-- android:padding="16dp"-->
<!-- android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"-->
<!-- android:textColor="@color/white"-->
<!-- tools:text="Text text text" />-->
<!-- &lt;!&ndash;<androidx.appcompat.widget.AppCompatTextView&ndash;&gt;-->
<!-- &lt;!&ndash; android:id="@+id/editCaption"&ndash;&gt;-->
<!-- &lt;!&ndash; android:layout_width="match_parent"&ndash;&gt;-->
<!-- &lt;!&ndash; android:layout_height="wrap_content"&ndash;&gt;-->
<!-- &lt;!&ndash; android:layout_marginStart="16dp"&ndash;&gt;-->
<!-- &lt;!&ndash; android:layout_marginTop="8dp"&ndash;&gt;-->
<!-- &lt;!&ndash; android:background="@null"&ndash;&gt;-->
<!-- &lt;!&ndash; android:gravity="center_vertical"&ndash;&gt;-->
<!-- &lt;!&ndash; android:text="@string/edit_caption"&ndash;&gt;-->
<!-- &lt;!&ndash; android:textColor="?android:textColorSecondary"&ndash;&gt;-->
<!-- &lt;!&ndash; android:textSize="16sp"&ndash;&gt;-->
<!-- &lt;!&ndash; android:visibility="gone"&ndash;&gt;-->
<!-- &lt;!&ndash; app:layout_constraintBottom_toTopOf="@id/translatedCaption"&ndash;&gt;-->
<!-- &lt;!&ndash; app:layout_constraintTop_toBottomOf="@id/caption"&ndash;&gt;-->
<!-- &lt;!&ndash; tools:visibility="visible" />&ndash;&gt;-->
<!-- <androidx.appcompat.widget.AppCompatTextView-->
<!-- android:id="@+id/translate"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:background="@null"-->
<!-- android:gravity="center_vertical"-->
<!-- android:paddingStart="16dp"-->
<!-- android:paddingTop="8dp"-->
<!-- android:paddingEnd="16dp"-->
<!-- android:paddingBottom="8dp"-->
<!-- android:text="@string/translate_caption"-->
<!-- android:textColor="@color/blue_600"-->
<!-- android:textSize="16sp"-->
<!-- android:visibility="visible" />-->
<!-- &lt;!&ndash;<awais.instagrabber.customviews.RamboTextViewV2&ndash;&gt;-->
<!-- &lt;!&ndash; android:id="@+id/translatedCaption"&ndash;&gt;-->
<!-- &lt;!&ndash; android:layout_width="match_parent"&ndash;&gt;-->
<!-- &lt;!&ndash; android:layout_height="wrap_content"&ndash;&gt;-->
<!-- &lt;!&ndash; android:layout_gravity="bottom"&ndash;&gt;-->
<!-- &lt;!&ndash; android:background="@null"&ndash;&gt;-->
<!-- &lt;!&ndash; android:clickable="true"&ndash;&gt;-->
<!-- &lt;!&ndash; android:focusable="true"&ndash;&gt;-->
<!-- &lt;!&ndash; android:padding="16dp"&ndash;&gt;-->
<!-- &lt;!&ndash; android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"&ndash;&gt;-->
<!-- &lt;!&ndash; android:textColor="@color/white"&ndash;&gt;-->
<!-- &lt;!&ndash; android:visibility="gone"&ndash;&gt;-->
<!-- &lt;!&ndash; app:layout_constraintBottom_toBottomOf="parent"&ndash;&gt;-->
<!-- &lt;!&ndash; app:layout_constraintTop_toBottomOf="@id/translateTitle"&ndash;&gt;-->
<!-- &lt;!&ndash; tools:text="Text text text"&ndash;&gt;-->
<!-- &lt;!&ndash; tools:visibility="visible" />&ndash;&gt;-->
<!-- </LinearLayout>-->
<!-- </ScrollView>-->
<!-- </androidx.core.widget.NestedScrollView>-->
<!--</androidx.coordinatorlayout.widget.CoordinatorLayout>-->
<!--<include-->
<!-- android:id="@+id/player_controls"-->
<!-- layout="@layout/layout_exo_custom_controls"-->
<!-- android:layout_width="0dp"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:visibility="gone"-->
<!-- app:layout_constraintBottom_toTopOf="@id/bottom_bg_barrier"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- tools:visibility="gone" />-->
<View
android:id="@+id/bottom_bg"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/bottom_bg_barrier" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/bottom_bg_barrier"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:barrierAllowsGoneWidgets="true"
app:barrierDirection="top"
app:constraint_referenced_ids="likes_count,comments_count,views_count" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/likes_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp"
app:layout_constraintBottom_toTopOf="@id/counts_barrier"
app:layout_constraintEnd_toStartOf="@id/comments_count"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/bottom_bg_barrier"
tools:text="9999999999 likes"
tools:visibility="gone" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/comments_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp"
app:layout_constraintBottom_toTopOf="@id/counts_barrier"
app:layout_constraintEnd_toStartOf="@id/views_count"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toEndOf="@id/likes_count"
app:layout_constraintTop_toBottomOf="@id/bottom_bg_barrier"
tools:text="9999999 comments"
tools:visibility="gone" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/views_count"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="8dp"
app:layout_constraintBottom_toTopOf="@id/counts_barrier"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/comments_count"
app:layout_constraintTop_toBottomOf="@id/bottom_bg_barrier"
tools:text="9999999999 views"
tools:visibility="gone" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/counts_barrier"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:barrierAllowsGoneWidgets="true"
app:barrierDirection="top"
app:constraint_referenced_ids="date" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
app:layout_constraintBottom_toBottomOf="@id/buttons_barrier"
app:layout_constraintTop_toBottomOf="@id/counts_barrier"
tools:text="2020-11-07 11:18:55"
tools:visibility="visible" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/buttons_barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierAllowsGoneWidgets="true"
app:barrierDirection="bottom"
app:constraint_referenced_ids="date" />
<!--<com.google.android.material.button.MaterialButton-->
<!-- android:id="@+id/caption_toggle"-->
<!-- style="@style/Widget.MaterialComponents.Button.TextButton"-->
<!-- android:layout_width="0dp"-->
<!-- android:layout_height="48dp"-->
<!-- android:visibility="visible"-->
<!-- app:icon="@drawable/ic_notes_24"-->
<!-- app:iconGravity="textStart"-->
<!-- app:iconPadding="0dp"-->
<!-- app:iconSize="24dp"-->
<!-- app:layout_constraintBottom_toTopOf="@id/caption_barrier"-->
<!-- app:layout_constraintEnd_toStartOf="@id/like"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toBottomOf="@id/buttons_barrier"-->
<!-- tools:visibility="visible" />-->
<com.google.android.material.button.MaterialButton
android:id="@+id/like"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="0dp"
android:layout_height="48dp"
android:visibility="visible"
app:icon="@drawable/ic_not_liked"
app:iconGravity="textStart"
app:iconPadding="0dp"
app:iconSize="24dp"
app:layout_constraintBottom_toTopOf="@id/caption_barrier"
app:layout_constraintEnd_toStartOf="@id/comment"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/buttons_barrier"
tools:visibility="visible" />
<com.google.android.material.button.MaterialButton
android:id="@+id/comment"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="0dp"
android:layout_height="48dp"
android:visibility="visible"
app:icon="@drawable/ic_outline_comments_24"
app:iconGravity="textStart"
app:iconPadding="0dp"
app:iconSize="24dp"
app:layout_constraintBottom_toTopOf="@id/caption_barrier"
app:layout_constraintEnd_toStartOf="@id/save"
app:layout_constraintStart_toEndOf="@id/like"
app:layout_constraintTop_toBottomOf="@id/buttons_barrier"
tools:visibility="visible" />
<!--<com.google.android.material.button.MaterialButton-->
<!-- android:id="@+id/player_controls_toggle"-->
<!-- style="@style/Widget.MaterialComponents.Button.TextButton"-->
<!-- android:layout_width="0dp"-->
<!-- android:layout_height="48dp"-->
<!-- android:visibility="gone"-->
<!-- app:icon="@drawable/ic_play_circle_outline_24"-->
<!-- app:iconGravity="textStart"-->
<!-- app:iconPadding="0dp"-->
<!-- app:iconSize="24dp"-->
<!-- app:iconTint="@color/white"-->
<!-- app:layout_constraintBottom_toBottomOf="parent"-->
<!-- app:layout_constraintEnd_toStartOf="@id/save"-->
<!-- app:layout_constraintStart_toEndOf="@id/comment"-->
<!-- app:layout_constraintTop_toBottomOf="@id/buttons_barrier"-->
<!-- app:rippleColor="@color/grey_300"-->
<!-- tools:visibility="visible" />-->
<com.google.android.material.button.MaterialButton
android:id="@+id/save"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="0dp"
android:layout_height="48dp"
android:visibility="visible"
app:icon="@drawable/ic_outline_class_24"
app:iconGravity="textStart"
app:iconPadding="0dp"
app:iconSize="24dp"
app:layout_constraintBottom_toTopOf="@id/caption_barrier"
app:layout_constraintEnd_toStartOf="@id/share"
app:layout_constraintStart_toEndOf="@id/comment"
app:layout_constraintTop_toBottomOf="@id/buttons_barrier"
tools:visibility="visible" />
<com.google.android.material.button.MaterialButton
android:id="@+id/share"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="0dp"
android:layout_height="48dp"
android:visibility="visible"
app:icon="?attr/actionModeShareDrawable"
app:iconGravity="textStart"
app:iconPadding="0dp"
app:iconSize="24dp"
app:layout_constraintBottom_toTopOf="@id/caption_barrier"
app:layout_constraintEnd_toStartOf="@id/download"
app:layout_constraintStart_toEndOf="@id/save"
app:layout_constraintTop_toBottomOf="@id/buttons_barrier"
tools:visibility="visible" />
<com.google.android.material.button.MaterialButton
android:id="@+id/download"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="0dp"
android:layout_height="48dp"
android:visibility="visible"
app:icon="@drawable/ic_download"
app:iconGravity="textStart"
app:iconPadding="0dp"
app:iconSize="24dp"
app:layout_constraintBottom_toTopOf="@id/caption_barrier"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/share"
app:layout_constraintTop_toBottomOf="@id/buttons_barrier"
tools:visibility="visible" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/caption_barrier"
android:layout_width="0dp"
android:layout_height="0dp"
app:barrierAllowsGoneWidgets="true"
app:barrierDirection="bottom"
app:constraint_referenced_ids="like,comment,save,share,download" />
<awais.instagrabber.customviews.RamboTextViewV2
android:id="@+id/caption"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="@null"
android:clickable="true"
android:focusable="true"
android:padding="8dp"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
app:layout_constraintBottom_toTopOf="@id/translate"
app:layout_constraintTop_toBottomOf="@id/caption_barrier"
tools:text="Text text text Text text text Text text text Text text text Text text text"
tools:visibility="gone" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/translate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:gravity="center_vertical"
android:padding="8dp"
android:text="@string/translate_caption"
android:textColor="@color/blue_600"
android:textSize="16sp"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/caption" />
<include layout="@layout/layout_post_view_bottom" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>

View File

@ -12,47 +12,13 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/exo_position" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/exo_position"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp"
android:textColor="@color/white"
app:layout_constraintBottom_toBottomOf="@id/exo_progress"
app:layout_constraintEnd_toStartOf="@id/exo_progress"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/exo_progress"
tools:text="0:00" />
<com.google.android.exoplayer2.ui.DefaultTimeBar
android:id="@+id/exo_progress"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@id/progress_barrier"
app:layout_constraintEnd_toStartOf="@id/exo_duration"
app:layout_constraintStart_toEndOf="@id/exo_position"
app:layout_constraintVertical_bias="1"
app:layout_constraintVertical_chainStyle="packed" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/exo_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp"
android:textColor="@color/white"
app:layout_constraintBottom_toBottomOf="@id/exo_progress"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/exo_progress"
app:layout_constraintTop_toTopOf="@id/exo_progress"
tools:text="0:00" />
app:layout_constraintTop_toTopOf="@id/top_barrier" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/progress_barrier"
android:id="@+id/top_barrier"
android:layout_width="0dp"
android:layout_height="0dp"
app:barrierDirection="bottom" />
app:barrierDirection="top" />
<com.google.android.material.button.MaterialButton
android:id="@+id/exo_rew_with_amount"
@ -63,12 +29,12 @@
app:icon="@drawable/ic_replay_5_24_states"
app:iconSize="24dp"
app:iconTint="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintBottom_toTopOf="@id/progress_barrier"
app:layout_constraintEnd_toStartOf="@id/exo_play_pause"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/progress_barrier"
app:layout_constraintTop_toBottomOf="@id/top_barrier"
tools:enabled="false"
tools:visibility="visible" />
tools:visibility="gone" />
<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/exo_play_pause"
@ -79,10 +45,10 @@
android:padding="8dp"
android:scaleType="fitCenter"
android:src="@drawable/exo_styled_controls_play"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintBottom_toTopOf="@id/progress_barrier"
app:layout_constraintEnd_toStartOf="@id/exo_ffwd_with_amount"
app:layout_constraintStart_toEndOf="@id/exo_rew_with_amount"
app:layout_constraintTop_toBottomOf="@id/progress_barrier"
app:layout_constraintTop_toBottomOf="@id/top_barrier"
tools:enabled="false"
tools:visibility="visible" />
@ -94,12 +60,12 @@
app:icon="@drawable/ic_forward_5_24_states"
app:iconSize="24dp"
app:iconTint="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintBottom_toTopOf="@id/progress_barrier"
app:layout_constraintEnd_toStartOf="@id/mute"
app:layout_constraintStart_toEndOf="@id/exo_play_pause"
app:layout_constraintTop_toBottomOf="@id/progress_barrier"
app:layout_constraintTop_toBottomOf="@id/top_barrier"
tools:enabled="false"
tools:visibility="visible" />
tools:visibility="gone" />
<com.google.android.material.button.MaterialButton
android:id="@+id/mute"
@ -109,10 +75,10 @@
app:icon="@drawable/ic_volume_off_24_states"
app:iconSize="24dp"
app:iconTint="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintBottom_toTopOf="@id/progress_barrier"
app:layout_constraintEnd_toStartOf="@id/exo_settings"
app:layout_constraintStart_toEndOf="@id/exo_ffwd_with_amount"
app:layout_constraintTop_toBottomOf="@id/progress_barrier"
app:layout_constraintTop_toBottomOf="@id/top_barrier"
tools:enabled="false"
tools:visibility="visible" />
@ -124,10 +90,53 @@
app:icon="@drawable/exo_ic_settings"
app:iconSize="24dp"
app:iconTint="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintBottom_toTopOf="@id/progress_barrier"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/mute"
app:layout_constraintTop_toBottomOf="@id/progress_barrier"
app:layout_constraintTop_toBottomOf="@id/top_barrier"
tools:enabled="false"
tools:visibility="visible" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/progress_barrier"
android:layout_width="0dp"
android:layout_height="0dp"
app:barrierDirection="top" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/exo_position"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp"
android:textColor="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/exo_progress"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/progress_barrier"
tools:text="0:00"
tools:visibility="gone" />
<com.google.android.exoplayer2.ui.DefaultTimeBar
android:id="@+id/exo_progress"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/exo_duration"
app:layout_constraintStart_toEndOf="@id/exo_position"
app:layout_constraintTop_toBottomOf="@id/progress_barrier"
app:layout_constraintVertical_bias="1"
app:layout_constraintVertical_chainStyle="packed" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/exo_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp"
android:textColor="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/exo_progress"
app:layout_constraintTop_toBottomOf="@id/progress_barrier"
tools:text="0:00"
tools:visibility="gone" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,203 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
<androidx.constraintlayout.widget.Barrier
android:id="@+id/buttons_top_barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierAllowsGoneWidgets="true"
app:barrierDirection="bottom" />
<com.google.android.material.button.MaterialButton
android:id="@+id/like"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="36dp"
android:layout_height="40dp"
android:visibility="visible"
app:icon="@drawable/ic_not_liked"
app:iconGravity="textStart"
app:iconPadding="0dp"
app:iconSize="22dp"
app:layout_constraintBottom_toTopOf="@id/buttons_bottom_barrier"
app:layout_constraintEnd_toStartOf="@id/likes_count"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/buttons_top_barrier"
app:layout_constraintVertical_bias="0"
app:layout_constraintVertical_chainStyle="packed"
tools:visibility="visible" />
<awais.instagrabber.customviews.FormattedNumberTextView
android:id="@+id/likes_count"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_marginEnd="0dp"
android:background="@drawable/background_grey_ripple"
android:gravity="center_vertical"
android:maxWidth="100dp"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
android:textColor="?android:attr/textColorSecondary"
app:layout_constraintBottom_toBottomOf="@id/like"
app:layout_constraintEnd_toStartOf="@id/comment"
app:layout_constraintStart_toEndOf="@id/like"
app:layout_constraintTop_toTopOf="@id/like"
tools:text="9.9k" />
<com.google.android.material.button.MaterialButton
android:id="@+id/comment"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="36dp"
android:layout_height="40dp"
android:layout_marginStart="8dp"
app:icon="@drawable/ic_outline_comments_24"
app:iconPadding="0dp"
app:iconSize="22dp"
app:layout_constraintBottom_toTopOf="@id/buttons_bottom_barrier"
app:layout_constraintEnd_toStartOf="@id/comments_count"
app:layout_constraintStart_toEndOf="@id/likes_count"
app:layout_constraintTop_toBottomOf="@id/buttons_top_barrier" />
<awais.instagrabber.customviews.FormattedNumberTextView
android:id="@+id/comments_count"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:background="@drawable/background_grey_ripple"
android:ellipsize="end"
android:gravity="center_vertical"
android:maxWidth="100dp"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
android:textColor="?android:attr/textColorSecondary"
app:layout_constraintBottom_toTopOf="@id/buttons_bottom_barrier"
app:layout_constraintEnd_toStartOf="@id/space_1"
app:layout_constraintStart_toEndOf="@id/comment"
app:layout_constraintTop_toBottomOf="@id/buttons_top_barrier"
tools:text="9999999999999999999999999999999999999999" />
<Space
android:id="@+id/space_1"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@id/buttons_bottom_barrier"
app:layout_constraintEnd_toStartOf="@id/share"
app:layout_constraintStart_toEndOf="@id/comments_count"
app:layout_constraintTop_toBottomOf="@id/buttons_top_barrier" />
<com.google.android.material.button.MaterialButton
android:id="@+id/share"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="48dp"
android:layout_height="40dp"
app:icon="?attr/actionModeShareDrawable"
app:iconGravity="textStart"
app:iconPadding="0dp"
app:iconSize="18dp"
app:layout_constraintBottom_toTopOf="@id/buttons_bottom_barrier"
app:layout_constraintEnd_toStartOf="@id/save"
app:layout_constraintStart_toEndOf="@id/space_1"
app:layout_constraintTop_toBottomOf="@id/buttons_top_barrier" />
<com.google.android.material.button.MaterialButton
android:id="@+id/save"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="48dp"
android:layout_height="40dp"
android:visibility="visible"
app:icon="@drawable/ic_round_bookmark_border_24"
app:iconGravity="textStart"
app:iconPadding="0dp"
app:iconSize="18dp"
app:layout_constraintBottom_toTopOf="@id/buttons_bottom_barrier"
app:layout_constraintEnd_toStartOf="@id/download"
app:layout_constraintStart_toEndOf="@id/share"
app:layout_constraintTop_toBottomOf="@id/buttons_top_barrier"
tools:visibility="visible" />
<com.google.android.material.button.MaterialButton
android:id="@+id/download"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="48dp"
android:layout_height="40dp"
android:visibility="visible"
app:icon="@drawable/ic_download"
app:iconGravity="textStart"
app:iconPadding="0dp"
app:iconSize="18dp"
app:layout_constraintBottom_toTopOf="@id/buttons_bottom_barrier"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/save"
app:layout_constraintTop_toBottomOf="@id/buttons_top_barrier"
tools:visibility="visible" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/buttons_bottom_barrier"
android:layout_width="0dp"
android:layout_height="0dp"
app:barrierAllowsGoneWidgets="true"
app:barrierDirection="top" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/date"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="8dp"
app:layout_constraintBottom_toTopOf="@id/caption_barrier"
app:layout_constraintEnd_toStartOf="@id/views_count"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/buttons_bottom_barrier"
tools:layout_constraintVertical_chainStyle="packed"
tools:text="2020-11-07 11:18:55"
tools:visibility="visible" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/views_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp"
app:layout_constraintBottom_toBottomOf="@id/date"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/date"
app:layout_constraintTop_toTopOf="@id/date"
tools:text="9999999999 views"
tools:visibility="visible" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/caption_barrier"
android:layout_width="0dp"
android:layout_height="0dp"
app:barrierAllowsGoneWidgets="true"
app:barrierDirection="bottom" />
<awais.instagrabber.customviews.RamboTextViewV2
android:id="@+id/caption"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="@null"
android:clickable="true"
android:focusable="true"
android:padding="8dp"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
app:layout_constraintBottom_toTopOf="@id/translate"
app:layout_constraintTop_toBottomOf="@id/caption_barrier"
app:layout_constraintVertical_bias="0"
app:layout_constraintVertical_chainStyle="packed"
tools:text="Text text text Text text text Text text text Text text text Text text text"
tools:visibility="visible" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/translate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:gravity="center_vertical"
android:padding="8dp"
android:text="@string/translate_caption"
android:textColor="@color/blue_600"
android:textSize="16sp"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/caption" />
</merge>

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<ViewSwitcher xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent">
@ -15,7 +14,7 @@
android:id="@+id/thumbnail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:actualImageScaleType="centerCrop"
app:actualImageScaleType="fitCenter"
app:viewAspectRatio="1" />
<androidx.appcompat.widget.AppCompatImageView
@ -25,14 +24,13 @@
app:srcCompat="@drawable/ic_video_24" />
</FrameLayout>
<!--app:controller_layout_id="@layout/layout_exo_custom_controls"-->
<com.google.android.exoplayer2.ui.StyledPlayerView
android:id="@+id/playerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
app:animation_enabled="false"
app:controller_layout_id="@layout/layout_exo_custom_controls"
app:resize_mode="fit"
app:show_timeout="2000"
app:use_controller="true" />
android:id="@+id/playerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
app:resize_mode="fixed_width"
app:show_timeout="2000"
app:use_controller="true" />
</ViewSwitcher>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<drawable name="exo_styled_controls_play">@drawable/ic_play_arrow_24</drawable>
<drawable name="exo_styled_controls_pause">@drawable/ic_pause_24</drawable>
<!--<drawable name="exo_styled_controls_play">@drawable/ic_play_arrow_24</drawable>-->
<!--<drawable name="exo_styled_controls_pause">@drawable/ic_pause_24</drawable>-->
</resources>