Fix invisible media controls and notch jank.

Fixes #9993.
master
Cody Henthorne 2020-09-18 15:55:15 -04:00 committed by Greyson Parrelli
parent c61d731358
commit edaf17bdd4
4 changed files with 115 additions and 149 deletions

View File

@ -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);
}
}
}
}

View File

@ -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")

View File

@ -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);
}
}

View File

@ -72,6 +72,12 @@
android:background="@color/media_preview_bar_background"
app:elevation="0dp">
<View
android:id="@+id/toolbar_cutout_spacer"
android:layout_width="match_parent"
android:layout_height="0dp"
android:visibility="gone" />
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"