Add a delay between the photo picker and the crop UI.

This adds a short delay before showing the crop UI after the photo
picker, to allow the photo picker exit animation to complete.

An interaction between the picker exit animation and the crop entry
animation causes visual jank without this delay.

Bug: 224477967
Test: install and exercise UI
Change-Id: Iaae0703617c1a6eb2f0337e7642059d1788be058
This commit is contained in:
Oli Lan
2022-03-15 16:54:43 +00:00
parent af4514e549
commit 5676546cb7
2 changed files with 25 additions and 5 deletions

View File

@@ -78,6 +78,11 @@ class AvatarPhotoController {
static final int REQUEST_CODE_TAKE_PHOTO = 1002;
static final int REQUEST_CODE_CROP_PHOTO = 1003;
/**
* Delay to allow the photo picker exit animation to complete before the crop activity opens.
*/
private static final long DELAY_BEFORE_CROP_MILLIS = 150;
private static final String IMAGES_DIR = "multi_user";
private static final String PRE_CROP_PICTURE_FILE_NAME = "PreCropEditUserPhoto.jpg";
private static final String CROP_PICTURE_FILE_NAME = "CropEditUserPhoto.jpg";
@@ -131,13 +136,15 @@ class AvatarPhotoController {
mAvatarUi.returnUriResult(pictureUri);
return true;
case REQUEST_CODE_TAKE_PHOTO:
case REQUEST_CODE_CHOOSE_PHOTO:
if (mTakePictureUri.equals(pictureUri)) {
cropPhoto(pictureUri);
} else {
copyAndCropPhoto(pictureUri);
copyAndCropPhoto(pictureUri, false);
}
return true;
case REQUEST_CODE_CHOOSE_PHOTO:
copyAndCropPhoto(pictureUri, true);
return true;
}
return false;
}
@@ -154,7 +161,7 @@ class AvatarPhotoController {
mAvatarUi.startActivityForResult(intent, REQUEST_CODE_CHOOSE_PHOTO);
}
private void copyAndCropPhoto(final Uri pictureUri) {
private void copyAndCropPhoto(final Uri pictureUri, boolean delayBeforeCrop) {
try {
ThreadUtils.postOnBackgroundThread(() -> {
final ContentResolver cr = mContextInjector.getContentResolver();
@@ -165,11 +172,17 @@ class AvatarPhotoController {
Log.w(TAG, "Failed to copy photo", e);
return;
}
ThreadUtils.postOnMainThread(() -> {
Runnable cropRunnable = () -> {
if (!mAvatarUi.isFinishing()) {
cropPhoto(mPreCropPictureUri);
}
});
};
if (delayBeforeCrop) {
ThreadUtils.postOnMainThreadDelayed(cropRunnable, DELAY_BEFORE_CROP_MILLIS);
} else {
ThreadUtils.postOnMainThread(cropRunnable);
}
}).get();
} catch (InterruptedException | ExecutionException e) {
Log.e(TAG, "Error performing copy-and-crop", e);

View File

@@ -84,6 +84,13 @@ public class ThreadUtils {
getUiThreadHandler().post(runnable);
}
/**
* Posts the runnable on the main thread with a delay.
*/
public static void postOnMainThreadDelayed(Runnable runnable, long delayMillis) {
getUiThreadHandler().postDelayed(runnable, delayMillis);
}
private static synchronized ExecutorService getThreadExecutor() {
if (sThreadExecutor == null) {
sThreadExecutor = Executors.newFixedThreadPool(