Android ImageView topCrop/bottomCrop scaletype?

2020-07-18 11:01发布

问题:

I have a square ImageView which displays pictures of varying dimensions. I want to always maintain the original aspect ratio of the pictures and have no margin around the image (so that the image takes up the whole ImageView). For this, I am using the centerCrop scaleType on the ImageView. However, I want to make it so that if the top and bottom of the image are cut off (i.e.: the image is taller than it is wide), the image gets pulled towards the bottom of the container. So instead of having equal amounts of pixels cropped at the top and bottom, the image is flush with the top and sides of the ImageView and the bottom of the image has twice as much cropped off. Is this possible in xml, if not, is there a java solution?

回答1:

You won't be able to do that with a regular ImageView and it's properties in xml. You can accomplish that with a proper scaleType Matrix, but tbh writing it is a pain in the ass. I'd suggest you use a respected library that can handle this easily. For example CropImageView.



回答2:

You probably can't do this in layout. But it's possible with a piece of code like this:

final ImageView image = (ImageView) findViewById(R.id.image);
// Proposing that the ImageView's drawable was set
final int width = image.getDrawable().getIntrinsicWidth();
final int height = image.getDrawable().getIntrinsicHeight();
if (width < height) {
    // This is just one of possible ways to get a measured View size
    image.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            int measuredSize = image.getMeasuredWidth();
            int offset = (int) ((float) measuredSize * (height - width) / width / 2);
            image.setPadding(0, offset, 0, -offset);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                image.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            } else {
                image.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            }
        }
    });
}

Note that if your ImageView has predefined size (likely it has) then you need to put this size to dimen resources and the code will be even simpler:

ImageView image = (ImageView) findViewById(R.id.image2);
// For sure also proposing that the ImageView's drawable was set
int width = image.getDrawable().getIntrinsicWidth();
int height = image.getDrawable().getIntrinsicHeight();
if (width < height) {
    int imageSize = getResources().getDimensionPixelSize(R.dimen.image_size);
    int offset = (int) ((float) imageSize * (height - width) / width / 2);
    image.setPadding(0, offset, 0, -offset);
}

See also:

  • findViewById()
  • getResources()