diff --git a/app/src/main/java/org/thoughtcrime/securesms/AvatarPreviewActivity.java b/app/src/main/java/org/thoughtcrime/securesms/AvatarPreviewActivity.java index 3156dda22e..4fa1ada7ae 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/AvatarPreviewActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/AvatarPreviewActivity.java @@ -1,6 +1,5 @@ package org.thoughtcrime.securesms; -import android.annotation.TargetApi; import android.app.Activity; import android.content.Context; import android.content.Intent; @@ -10,12 +9,7 @@ import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; import android.transition.TransitionInflater; -import android.view.DisplayCutout; import android.view.View; -import android.view.ViewGroup; -import android.view.ViewTreeObserver; -import android.view.Window; -import android.view.WindowManager; import android.widget.ImageView; import androidx.annotation.NonNull; @@ -40,6 +34,7 @@ import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.mms.GlideApp; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; +import org.thoughtcrime.securesms.util.FullscreenHelper; /** * Activity for displaying avatars full screen. @@ -81,17 +76,7 @@ public final class AvatarPreviewActivity extends PassphraseRequiredActivity { setSupportActionBar(toolbar); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - - if (Build.VERSION.SDK_INT >= 28) { - getWindow().getAttributes().layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; - toolbar.getViewTreeObserver().addOnGlobalLayoutListener(new DisplayCutoutAdjuster(toolbar, findViewById(R.id.toolbar_cutout_spacer))); - } - - showSystemUI(); - - getSupportActionBar().setDisplayHomeAsUpEnabled(true); + requireSupportActionBar().setDisplayHomeAsUpEnabled(true); Context context = getApplicationContext(); RecipientId recipientId = RecipientId.from(getIntent().getStringExtra(RECIPIENT_ID_EXTRA)); @@ -140,47 +125,13 @@ public final class AvatarPreviewActivity extends PassphraseRequiredActivity { toolbar.setTitle(recipient.getDisplayName(context)); }); - avatar.setOnClickListener(v -> toggleUiVisibility()); + FullscreenHelper fullscreenHelper = new FullscreenHelper(this); - showAndHideWithSystemUI(getWindow(), findViewById(R.id.toolbar_layout)); - } + findViewById(android.R.id.content).setOnClickListener(v -> fullscreenHelper.toggleUiVisibility()); - private static void showAndHideWithSystemUI(@NonNull Window window, @NonNull View... views) { - window.getDecorView().setOnSystemUiVisibilityChangeListener(visibility -> { - boolean hide = (visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0; + fullscreenHelper.configureToolbarSpacer(findViewById(R.id.toolbar_cutout_spacer)); - for (View view : views) { - view.animate() - .alpha(hide ? 0 : 1) - .start(); - } - }); - } - - private void toggleUiVisibility() { - int systemUiVisibility = getWindow().getDecorView().getSystemUiVisibility(); - if ((systemUiVisibility & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0) { - showSystemUI(); - } else { - hideSystemUI(); - } - } - - private void hideSystemUI() { - getWindow().getDecorView().setSystemUiVisibility( - View.SYSTEM_UI_FLAG_IMMERSIVE | - View.SYSTEM_UI_FLAG_LAYOUT_STABLE | - View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | - View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | - View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | - View.SYSTEM_UI_FLAG_FULLSCREEN ); - } - - private void showSystemUI() { - getWindow().getDecorView().setSystemUiVisibility( - View.SYSTEM_UI_FLAG_LAYOUT_STABLE | - View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | - View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN ); + fullscreenHelper.showAndHideWithSystemUI(getWindow(), findViewById(R.id.toolbar_layout)); } @Override @@ -188,36 +139,4 @@ public final class AvatarPreviewActivity extends PassphraseRequiredActivity { onBackPressed(); return true; } - - /** - * Adjust a spacer for the toolbar when a display cutout is detected. Runs within - * a layout listener because the activity delays view attachment due to the transitions - * and needs to update on device rotation. - */ - @TargetApi(28) - private static class DisplayCutoutAdjuster implements ViewTreeObserver.OnGlobalLayoutListener { - - private final View view; - private final View spacer; - - private DisplayCutoutAdjuster(@NonNull View view, @NonNull View spacer) { - this.view = view; - this.spacer = spacer; - } - - @Override - public void onGlobalLayout() { - if (view.getRootWindowInsets() == null) { - return; - } - - DisplayCutout cutout = view.getRootWindowInsets().getDisplayCutout(); - if (cutout != null) { - ViewGroup.LayoutParams params = spacer.getLayoutParams(); - params.height = cutout.getSafeInsetTop(); - spacer.setLayoutParams(params); - spacer.setVisibility(View.VISIBLE); - } - } - } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java b/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java index ee2b2d636c..5c66327b22 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java @@ -31,8 +31,6 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowManager; import android.widget.TextView; import android.widget.Toast; @@ -69,6 +67,7 @@ import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.sharing.ShareActivity; import org.thoughtcrime.securesms.util.AttachmentUtil; import org.thoughtcrime.securesms.util.DateUtils; +import org.thoughtcrime.securesms.util.FullscreenHelper; import org.thoughtcrime.securesms.util.SaveAttachmentTask; import org.thoughtcrime.securesms.util.SaveAttachmentTask.Attachment; @@ -119,6 +118,7 @@ public final class MediaPreviewActivity extends PassphraseRequiredActivity private boolean cameFromAllMedia; private boolean showThread; private MediaDatabase.Sorting sorting; + private FullscreenHelper fullscreenHelper; private @Nullable Cursor cursor = null; @@ -147,10 +147,7 @@ public final class MediaPreviewActivity extends PassphraseRequiredActivity viewModel = ViewModelProviders.of(this).get(MediaPreviewViewModel.class); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - - showSystemUI(); + fullscreenHelper = new FullscreenHelper(this); getSupportActionBar().setDisplayHomeAsUpEnabled(true); @@ -273,9 +270,9 @@ public final class MediaPreviewActivity extends PassphraseRequiredActivity anchorMarginsToBottomInsets(detailsContainer); - anchorMarginsToTopInsets(toolbarLayout); + fullscreenHelper.configureToolbarSpacer(findViewById(R.id.toolbar_cutout_spacer)); - showAndHideWithSystemUI(getWindow(), detailsContainer, toolbarLayout); + fullscreenHelper.showAndHideWithSystemUI(getWindow(), detailsContainer, toolbarLayout); } private void initializeResources() { @@ -546,7 +543,7 @@ public final class MediaPreviewActivity extends PassphraseRequiredActivity @Override public boolean singleTapOnMedia() { - toggleUiVisibility(); + fullscreenHelper.toggleUiVisibility(); return true; } @@ -556,32 +553,6 @@ public final class MediaPreviewActivity extends PassphraseRequiredActivity finish(); } - private void toggleUiVisibility() { - int systemUiVisibility = getWindow().getDecorView().getSystemUiVisibility(); - if ((systemUiVisibility & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0) { - showSystemUI(); - } else { - hideSystemUI(); - } - } - - private void hideSystemUI() { - getWindow().getDecorView().setSystemUiVisibility( - View.SYSTEM_UI_FLAG_IMMERSIVE | - View.SYSTEM_UI_FLAG_LAYOUT_STABLE | - View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | - View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | - View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | - View.SYSTEM_UI_FLAG_FULLSCREEN ); - } - - private void showSystemUI() { - getWindow().getDecorView().setSystemUiVisibility( - View.SYSTEM_UI_FLAG_LAYOUT_STABLE | - View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | - View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN ); - } - private class ViewPagerListener extends ExtendedOnPageChangedListener { @Override @@ -697,33 +668,6 @@ public final class MediaPreviewActivity extends PassphraseRequiredActivity }); } - private static void anchorMarginsToTopInsets(@NonNull View viewToAnchor) { - ViewCompat.setOnApplyWindowInsetsListener(viewToAnchor, (view, insets) -> { - ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) view.getLayoutParams(); - - layoutParams.setMargins(insets.getSystemWindowInsetLeft(), - insets.getSystemWindowInsetTop(), - insets.getSystemWindowInsetRight(), - layoutParams.bottomMargin); - - view.setLayoutParams(layoutParams); - - return insets; - }); - } - - private static void showAndHideWithSystemUI(@NonNull Window window, @NonNull View... views) { - window.getDecorView().setOnSystemUiVisibilityChangeListener(visibility -> { - boolean hide = (visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0; - - for (View view : views) { - view.animate() - .alpha(hide ? 0 : 1) - .start(); - } - }); - } - private static class CursorPagerAdapter extends FragmentStatePagerAdapter implements MediaItemAdapter { @SuppressLint("UseSparseArrays") diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/FullscreenHelper.java b/app/src/main/java/org/thoughtcrime/securesms/util/FullscreenHelper.java new file mode 100644 index 0000000000..5b50d9f7c9 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/util/FullscreenHelper.java @@ -0,0 +1,97 @@ +package org.thoughtcrime.securesms.util; + +import android.app.Activity; +import android.os.Build; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; + +import androidx.annotation.NonNull; +import androidx.core.view.ViewCompat; + +/** + * Encapsulates logic to properly show/hide system UI/chrome in a full screen setting. Also + * handles adjusting to notched devices as long as you call {@link #configureToolbarSpacer(View)}. + */ +public final class FullscreenHelper { + + @NonNull private final Activity activity; + + public FullscreenHelper(@NonNull Activity activity) { + this.activity = activity; + + if (Build.VERSION.SDK_INT >= 28) { + activity.getWindow().getAttributes().layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; + } + + showSystemUI(); + } + + public void configureToolbarSpacer(@NonNull View spacer) { + if (Build.VERSION.SDK_INT == 19) { + setSpacerHeight(spacer, ViewUtil.getStatusBarHeight(spacer)); + return; + } + + ViewCompat.setOnApplyWindowInsetsListener(spacer, (view, insets) -> { + setSpacerHeight(view, insets.getSystemWindowInsetTop()); + return insets; + }); + } + + private void setSpacerHeight(@NonNull View spacer, int height) { + ViewGroup.LayoutParams params = spacer.getLayoutParams(); + + params.height = height; + + spacer.setLayoutParams(params); + spacer.setVisibility(View.VISIBLE); + } + + public void showAndHideWithSystemUI(@NonNull Window window, @NonNull View... views) { + window.getDecorView().setOnSystemUiVisibilityChangeListener(visibility -> { + boolean hide = (visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0; + + for (View view : views) { + view.animate() + .alpha(hide ? 0 : 1) + .withStartAction(() -> { + if (!hide) { + view.setVisibility(View.VISIBLE); + } + }) + .withEndAction(() -> { + if (hide) { + view.setVisibility(View.INVISIBLE); + } + }) + .start(); + } + }); + } + + public void toggleUiVisibility() { + int systemUiVisibility = activity.getWindow().getDecorView().getSystemUiVisibility(); + if ((systemUiVisibility & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0) { + showSystemUI(); + } else { + hideSystemUI(); + } + } + + public void hideSystemUI() { + activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_IMMERSIVE | + View.SYSTEM_UI_FLAG_LAYOUT_STABLE | + View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | + View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_FULLSCREEN); + } + + public void showSystemUI() { + activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | + View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); + } +} diff --git a/app/src/main/res/layout/media_preview_activity.xml b/app/src/main/res/layout/media_preview_activity.xml index ab190eea15..4631673b9f 100644 --- a/app/src/main/res/layout/media_preview_activity.xml +++ b/app/src/main/res/layout/media_preview_activity.xml @@ -72,6 +72,12 @@ android:background="@color/media_preview_bar_background" app:elevation="0dp"> + +