Изменение размера изображения до полной ширины и фиксированной высоты с помощью Picasso

У меня есть вертикальный LinearLayout, где один из элементов - это ImageView, загруженный с использованием Picasso. Мне нужно увеличить ширину изображения до полной ширины устройства и отобразить центральную часть изображения, обрезанную фиксированной высотой (150dp). В настоящее время у меня есть следующий код:

Picasso.with(getActivity()) 
    .load(imageUrl) 
    .placeholder(R.drawable.placeholder) 
    .error(R.drawable.error) 
    .resize(screenWidth, imageHeight)
    .centerInside() 
    .into(imageView);

Какие значения следует ввести в screenWidth и imageHeight (= 150dp)?

Ответ 1

Вы ищете:

.fit().centerCrop()

Что это означает:

  • fit - подождите, пока не будет измерено значение ImageView и измените размер изображения так, чтобы он соответствовал его размеру.
  • centerCrop - масштабируйте изображение, соблюдая пропорции, до тех пор, пока оно не заполнит размер. Обрезайте верхнюю и нижнюю, или левую и правую, чтобы он точно соответствовал размеру.

Ответ 2

В этом блоге подробно описываются функции изменения размера и подгонки Пикассо: https://futurestud.io/tutorials/picasso-image-resizing-scaling-and-fit.

Изменение размера изображения с помощью resize (x, y)

Обычно оптимально, если ваш сервер или API доставляют изображение в нужных вам размерах, что является идеальным компромиссом между пропускной способностью, потреблением памяти и качеством изображения.

К сожалению, вы не всегда можете запросить изображения в идеальных размерах. Если изображения имеют странный размер, вы можете использовать вызов resize (horizontalSize, verticalSize), чтобы изменить размеры вашего изображения на более подходящий размер. Это изменит размер изображения перед его отображением в ImageView.

Picasso  
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[0])
    .resize(600, 200) // resizes the image to these dimensions (in pixel). does not respect aspect ratio
    .into(imageViewResize);

Использование scaleDown()

При использовании опции resize() Picasso также увеличит изображение. Поскольку увеличение небольшого изображения без улучшения качества изображения может привести к потере вычислительного времени, вызовите scaleDown (true), чтобы применять функцию resize(), только если исходное изображение имеет размеры больше целевого размера.

Picasso  
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[0])
    .resize(6000, 2000)
    .onlyScaleDown() // the image will only be resized if it bigger than 6000x2000 pixels.
    .into(imageViewResizeScaleDown);

Избегание растянутых изображений с масштабированием

Теперь, как и при любой манипуляции с изображением, изменение размера изображения может реально исказить соотношение сторон и ухудшить отображение изображения. В большинстве случаев вы хотите предотвратить это. Picasso предлагает вам два варианта смягчения: call centerCrop() или centerInside().

CenterCrop

CenterCrop() - это метод обрезки, который масштабирует изображение так, чтобы оно заполняло запрошенные границы ImageView, а затем обрезал лишние. ImageView будет заполнен полностью, но все изображение может не отображаться.

Picasso  
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[0])
    .resize(600, 200) // resizes the image to these dimensions (in pixel)
    .centerCrop() 
    .into(imageViewResizeCenterCrop);

CenterInside

CenterInside() - это метод обрезки, который масштабирует изображение таким образом, чтобы оба измерения были равны или меньше запрошенных границ ImageView. Изображение будет отображаться полностью, но может не заполнять весь ImageView.

Picasso  
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[0])
    .resize(600, 200)
    .centerInside() 
    .into(imageViewResizeCenterInside);

И последнее, но не менее важное: Picasso fit() Обсуждаемые параметры должны охватывать ваши потребности в функциональности, связанной с изменением размера и масштабирования изображения. В Picasso есть еще одна вспомогательная функциональность, которая может быть очень полезна: fit().

Picasso  
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[0])
    .fit()
    // call .centerInside() or .centerCrop() to avoid a stretched image
    .into(imageViewFit);

fit() измеряет размеры целевого ImageView и внутренне использует resize(), чтобы уменьшить размер изображения до размеров ImageView. Есть две вещи, которые нужно знать о fit(). Во-первых, вызов fit() может задержать запрос изображения, поскольку Picasso нужно будет подождать, пока размер ImageView не будет измерен. Во-вторых, вы можете использовать только fit() с ImageView в качестве цели (мы рассмотрим другие цели позже).

Преимущество состоит в том, что изображение имеет минимально возможное разрешение, не влияя на его качество. Более низкое разрешение означает меньше данных, которые будут храниться в кэше. Это может значительно уменьшить влияние изображений на объем памяти вашего приложения. Таким образом, если вы предпочитаете меньшее влияние на память по сравнению с немного более быстрым временем загрузки, то fit() - отличный инструмент.

Ответ 3

вы можете сделать это: -

Picasso.with(context)
.load(-yourImgURL-)
.fit()
.centerCrop()
.into(-yourImageView-);

Ответ 4

В некоторых случаях функция fit() бесполезна. Прежде чем ждать окончания измерения ширины и высоты. Таким образом, вы можете использовать globallayoutlistener. например;

imageView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
            public void onGlobalLayout() {
                Picasso.with(getActivity())
                        .load(imageUrl)
                        .placeholder(R.drawable.placeholder)
                        .error(R.drawable.error)
                        .resize(screenWidth, imageHeight)
                        .fit
                        .centerInside()
                        .into(imageView);
                imageView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            }
        });