diff options
3 files changed, 76 insertions, 28 deletions
diff --git a/java/res/layout/chooser_grid_preview_image.xml b/java/res/layout/chooser_grid_preview_image.xml index 68b07846..b87cecda 100644 --- a/java/res/layout/chooser_grid_preview_image.xml +++ b/java/res/layout/chooser_grid_preview_image.xml @@ -43,8 +43,7 @@ android:layout_gravity="center_horizontal" android:background="?android:attr/colorBackground" app:itemInnerSpacing="3dp" - app:itemOuterSpacing="@dimen/chooser_edge_margin_normal_half" - app:maxWidthHint="@dimen/chooser_width" /> + app:itemOuterSpacing="@dimen/chooser_edge_margin_normal_half" /> <TextView android:id="@androidprv:id/content_preview_text" diff --git a/java/src/com/android/intentresolver/widget/ScrollableImagePreviewView.kt b/java/src/com/android/intentresolver/widget/ScrollableImagePreviewView.kt index 524b4f81..e760e6d0 100644 --- a/java/src/com/android/intentresolver/widget/ScrollableImagePreviewView.kt +++ b/java/src/com/android/intentresolver/widget/ScrollableImagePreviewView.kt @@ -78,7 +78,7 @@ class ScrollableImagePreviewView : RecyclerView, ImagePreviewView { TypedValue.COMPLEX_UNIT_DIP, 3f, context.resources.displayMetrics ).toInt() } - var outerSpacing = a.getDimensionPixelSize( + outerSpacing = a.getDimensionPixelSize( R.styleable.ScrollableImagePreviewView_itemOuterSpacing, -1 ) if (outerSpacing < 0) { @@ -104,12 +104,24 @@ class ScrollableImagePreviewView : RecyclerView, ImagePreviewView { var maxWidthHint: Int = -1 private var requestedHeight: Int = 0 private var isMeasured = false + private var maxAspectRatio = MAX_ASPECT_RATIO + private var maxAspectRatioString = MAX_ASPECT_RATIO_STRING + private var outerSpacing: Int = 0 override fun onMeasure(widthSpec: Int, heightSpec: Int) { super.onMeasure(widthSpec, heightSpec) if (!isMeasured) { isMeasured = true - batchLoader?.loadAspectRatios(getMaxWidth(), this::calcPreviewWidth) + updateMaxWidthHint(widthSpec) + updateMaxAspectRatio() + batchLoader?.loadAspectRatios(getMaxWidth(), this::updatePreviewSize) + } + } + + private fun updateMaxWidthHint(widthSpec: Int) { + if (maxWidthHint > 0) return + if (View.MeasureSpec.getMode(widthSpec) != View.MeasureSpec.UNSPECIFIED) { + maxWidthHint = View.MeasureSpec.getSize(widthSpec) } } @@ -146,7 +158,7 @@ class ScrollableImagePreviewView : RecyclerView, ImagePreviewView { } .apply { if (isMeasured) { - loadAspectRatios(getMaxWidth(), this@ScrollableImagePreviewView::calcPreviewWidth) + loadAspectRatios(getMaxWidth(), this@ScrollableImagePreviewView::updatePreviewSize) } } } @@ -160,14 +172,39 @@ class ScrollableImagePreviewView : RecyclerView, ImagePreviewView { else -> measuredWidth } - private fun calcPreviewWidth(bitmap: Bitmap): Int { + private fun updateMaxAspectRatio() { + val padding = outerSpacing * 2 + val w = maxOf(padding, getMaxWidth() - padding) + val h = if (isLaidOut) height else measuredHeight + if (w > 0 && h > 0) { + maxAspectRatio = (w.toFloat() / h.toFloat()) + .coerceIn(MIN_ASPECT_RATIO, MAX_ASPECT_RATIO) + maxAspectRatioString = when { + maxAspectRatio <= MIN_ASPECT_RATIO -> MIN_ASPECT_RATIO_STRING + maxAspectRatio >= MAX_ASPECT_RATIO -> MAX_ASPECT_RATIO_STRING + else -> "$w:$h" + } + } + } + + /** + * Sets [preview]'s aspect ratio based on the preview image size. + * @return adjusted preview width + */ + private fun updatePreviewSize(preview: Preview, width: Int, height: Int): Int { val effectiveHeight = if (isLaidOut) height else measuredHeight - return if (bitmap.width <= 0 || bitmap.height <= 0) { + return if (width <= 0 || height <= 0) { + preview.aspectRatioString = "1:1" effectiveHeight } else { - val ar = (bitmap.width.toFloat() / bitmap.height.toFloat()) - .coerceIn(MIN_ASPECT_RATIO, MAX_ASPECT_RATIO) - (effectiveHeight * ar).roundToInt() + val aspectRatio = (width.toFloat() / height.toFloat()) + .coerceIn(MIN_ASPECT_RATIO, maxAspectRatio) + preview.aspectRatioString = when { + aspectRatio <= MIN_ASPECT_RATIO -> MIN_ASPECT_RATIO_STRING + aspectRatio >= maxAspectRatio -> maxAspectRatioString + else -> "$width:$height" + } + (effectiveHeight * aspectRatio).toInt() } } @@ -177,16 +214,6 @@ class ScrollableImagePreviewView : RecyclerView, ImagePreviewView { internal var aspectRatioString: String ) { constructor(type: PreviewType, uri: Uri) : this(type, uri, "1:1") - - internal fun updateAspectRatio(width: Int, height: Int) { - if (width <= 0 || height <= 0) return - val aspectRatio = width.toFloat() / height.toFloat() - aspectRatioString = when { - aspectRatio <= MIN_ASPECT_RATIO -> MIN_ASPECT_RATIO_STRING - aspectRatio >= MAX_ASPECT_RATIO -> MAX_ASPECT_RATIO_STRING - else -> "$width:$height" - } - } } enum class PreviewType { @@ -398,7 +425,7 @@ class ScrollableImagePreviewView : RecyclerView, ImagePreviewView { scope = null } - fun loadAspectRatios(maxWidth: Int, previewWidthCalculator: (Bitmap) -> Int) { + fun loadAspectRatios(maxWidth: Int, previewSizeUpdater: (Preview, Int, Int) -> Int) { val scope = this.scope ?: return val updates = ArrayDeque<Preview>(pendingPreviews.size) // replay 2 items to guarantee that we'd get at least one update @@ -440,10 +467,11 @@ class ScrollableImagePreviewView : RecyclerView, ImagePreviewView { // TODO: decide on adding a timeout imageLoader(preview.uri, isVisible) }.getOrNull() ?: continue - preview.updateAspectRatio(bitmap.width, bitmap.height) + val previewWidth = + previewSizeUpdater(preview, bitmap.width, bitmap.height) updates.add(preview) if (isVisible) { - loadedPreviewWidth += previewWidthCalculator(bitmap) + loadedPreviewWidth += previewWidth if (loadedPreviewWidth >= maxWidth) { // notify that the preview now can be displayed reportFlow.emit(updateEvent) diff --git a/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java b/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java index de5498db..acced89f 100644 --- a/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java +++ b/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java @@ -81,6 +81,7 @@ import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; +import android.graphics.Rect; import android.graphics.drawable.Icon; import android.net.Uri; import android.os.Bundle; @@ -92,6 +93,7 @@ import android.util.HashedStringCache; import android.util.Pair; import android.util.SparseArray; import android.view.View; +import android.view.WindowManager; import androidx.annotation.CallSuper; import androidx.annotation.NonNull; @@ -959,7 +961,7 @@ public class UnbundledChooserActivityTest { Intent sendIntent = createSendUriIntentWithPreview(uris); ChooserActivityOverrideData.getInstance().imageLoader = - createImageLoader(uri, createBitmap()); + createImageLoader(uri, createWideBitmap()); ChooserActivityOverrideData.getInstance().isImageType = true; List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2); @@ -975,9 +977,14 @@ public class UnbundledChooserActivityTest { RecyclerView recyclerView = (RecyclerView) view; assertThat(recyclerView.getAdapter().getItemCount(), is(1)); assertThat(recyclerView.getChildCount(), is(1)); + View imageView = recyclerView.getChildAt(0); + Rect rect = new Rect(); + boolean isPartiallyVisible = imageView.getGlobalVisibleRect(rect); assertThat( - "image preview view is fully visible", - isDisplayed().matches(recyclerView.getChildAt(0))); + "image preview view is not fully visible", + isPartiallyVisible + && rect.width() == imageView.getWidth() + && rect.height() == imageView.getHeight()); }); } @@ -2785,8 +2792,22 @@ public class UnbundledChooserActivityTest { } private Bitmap createBitmap() { - int width = 200; - int height = 200; + return createBitmap(200, 200); + } + + private Bitmap createWideBitmap() { + WindowManager windowManager = InstrumentationRegistry.getInstrumentation() + .getTargetContext() + .getSystemService(WindowManager.class); + int width = 3000; + if (windowManager != null) { + Rect bounds = windowManager.getMaximumWindowMetrics().getBounds(); + width = bounds.width() + 200; + } + return createBitmap(width, 100); + } + + private Bitmap createBitmap(int width, int height) { Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); |