1
$\begingroup$

This is a simple enough problem that I could just cover all corner cases, but I was wondering if there was an elegant way to do this.

Here is the starting point. It finds out which side of the image is taller and then sets that to match up with the size of the "b" boundary. So if it's wider than it is tall it'll set it to be the width of the boundary.

void setBoundsMaxSize(Drawable d, Rect b) {
    int bWidth = b.right - b.left + 1;
    int bHeight = b.bottom - b.top + 1;
    if(d.width() > d.height()) {
        // it's wider than it is tall
        int newHeight = bWidth * d.height() / d.width();
        int padding = (bHeight - newHeight) / 2;
        d.setBounds(b.left, b.top+padding, b.right, b.bottom-padding);
    } else {
        // the width and height are the same or it's taller than it is wide.
        int newWidth = bHeight * d.width() / d.height();
        int padding = (bWidth - newWidth) / 2;
        d.setBounds(b.left+padding, b.top, b.right-padding, b.bottom);
    }
}

This algorithm works if the "b" boundary is square. However, if it's not then I'll need special cases to check if the newWidth and newHeight are inside the boundary. If they're not then I'll need to shrink it down to fit.

So I'd be handling 4 separate special cases.

I was just curious if there was a cleaner way to deal with this.

EDIT:

FWIW this is what I've got now. It's pretty good, but I still wonder if there's a simple way to know at the beginning that I don't need to try one and then do the other.

public static void setBoundsMaxSize(Drawable d, Rect b) {
    if(d.getIntrinsicWidth() > d.getIntrinsicHeight()) {
        // it's wider than it is tall
        shrinkVert(d,b);
    } else {
        // the width and height are the same or it's taller than it is wide.
        shrinkHoriz(d,b);
    }
}

private static void shrinkVert(Drawable d, Rect b) {
    int bWidth = b.right - b.left + 1;
    int newHeight = bWidth * d.getIntrinsicHeight() / d.getIntrinsicWidth();
    int bHeight = b.bottom - b.top + 1;
    if(newHeight > bHeight) {
        shrinkHoriz(d,b);
    } else {
        int padding = (bHeight - newHeight) / 2;
        d.setBounds(b.left, b.top+padding, b.right, b.bottom-padding);
    }
}

private static void shrinkHoriz(Drawable d, Rect b) {
    int bHeight = b.bottom - b.top + 1;
    int newWidth = bHeight * d.getIntrinsicWidth() / d.getIntrinsicHeight();
    int bWidth = b.right - b.left + 1;
    if(newWidth > bWidth) {
        shrinkVert(d,b);
    } else {
        int padding = (bWidth - newWidth) / 2;
        d.setBounds(b.left+padding, b.top, b.right-padding, b.bottom);
    }
}
$\endgroup$
0

1 Answer 1

3
$\begingroup$

Compare the aspect rations (width / height) to determine which dimension of the rectangle will be limiting. That requires about five lines of code:

if (d.width / d.height > b.width / b.height) {
  scale = b.width / d.width 
} else {
  scale = b.height / d.height
}
newWidth = d.width * scale
newHeight = d.height * scale
$\endgroup$
1
  • $\begingroup$ Very nice. I knew there was something like that. $\endgroup$ Commented Sep 6, 2011 at 6:15

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .