Resize image to full width and fixed height with Picasso

谁都会走 提交于 2019-12-17 05:40:21

问题


I have a vertical LinearLayout where one of the items is an ImageView loaded using Picasso. I need to rise the image's width to the full device width, and to display the center part of the image cropped by a fixed height (150dp). I currently have the following code:

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

Which values should I put into screenWidth and imageHeight (=150dp)?


回答1:


You are looking for:

.fit().centerCrop()

What these mean:

  • fit - wait until the ImageView has been measured and resize the image to exactly match its size.
  • centerCrop - scale the image honoring the aspect ratio until it fills the size. Crop either the top and bottom or left and right so it matches the size exactly.



回答2:


This blog explains Picasso's resize and fit functions in detail: https://futurestud.io/tutorials/picasso-image-resizing-scaling-and-fit.

Image Resizing with resize(x, y)

Generally it's optimal if your server or API deliver the image in the exact dimensions you need, which are a perfect trade-off between bandwidth, memory consumption and image quality.

Unfortunately, it's not always in your control to request images in the perfect dimensions. If the images are in a weird size you can use the resize(horizontalSize, verticalSize) call to change the dimensions of your image into a more suitable size. This will resize the image before displaying it in the 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);

Use of scaleDown()

When using the resize() option Picasso will also upscale your image. Since making a small image bigger without improving the quality of the image can be wasted computing time, call scaleDown(true) to only apply the resize() when the original image has larger dimensions than the target size.

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

Avoiding Stretched Images with Scaling

Now, as with any image manipulation, resizing images can really distort the aspect ratio and uglify the image display. In most of your use cases, you want to prevent this from happening. Picasso gives you two mitigation choices here, either call centerCrop() or centerInside().

CenterCrop

CenterCrop() is a cropping technique that scales the image so that it fills the requested bounds of the ImageView and then crops the extra. The ImageView will be filled completely, but the entire image might not be displayed.

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

CenterInside

CenterInside() is a cropping technique that scales the image so that both dimensions are equal to or less than the requested bounds of the ImageView. The image will be displayed completely, but might not fill the entire ImageView.

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

Last, but not least: Picasso's fit() The discussed options should cover your needs for functionality regarding image resizing and scaling. There is one last helper functionality of Picasso, which can be very useful: fit().

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

fit() is measuring the dimensions of the target ImageView and internally uses resize() to reduce the image size to the dimensions of the ImageView. There are two things to know about fit(). First, calling fit() can delay the image request since Picasso will need to wait until the size of the ImageView can be measured. Second, you only can use fit() with an ImageView as the target (we'll look at other targets later).

The advantage is that the image is at the lowest possible resolution, without affecting its quality. A lower resolution means less data to be hold in the cache. This can significantly reduce the impact of images in the memory footprint of your app. In summary, if you prefer a lower memory impact over a little faster loading times, fit() is a great tool.




回答3:


In some case the fit() is useless. Before you must wait for the width and height measurement to end. So you can use globallayoutlistener. for example;

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


来源:https://stackoverflow.com/questions/20823249/resize-image-to-full-width-and-fixed-height-with-picasso

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!