Dori Dori - 8 months ago 51
Android Question

ImageView scaling TOP_CROP

I have an

which is displaying a png that has a bigger aspect ratio than that of the device (vertically speaking - meaning its longer). I want to display this while maintaining aspect ratio, matching the width of the parent, and pinning the imageview to the top of the screen.

The problem i have with using
as the scale type is that it will (understandable) center the scaled image instead of aligning the top edge to the top edge f the image view.

The problem with
is that the image will fit the screen height and not fill the width.

I have solved this problem by using a custom ImageView and overriding
and handeling this manually using the canvas; the problem with this approach is that 1) I'm worried there may be a simpler solution, 2) I am getting a VM mem exception when calling
in the constructor when trying to set a src img of 330kb when the heap has 3 mb free (with a heap size of 6 mb) and cant work out why.

Any ideas / suggestions / solutions are much welcome :)


p.s. i thought that a solution may be to use a matrix scale type and do it myself, but that seems to to be the same or more work than my current solution!

Answer Source

Ok, I have a working solution. The prompt from Darko made me look again at the ImageView class (thanks) and have applied the transformation using a Matrix (as i originally suspected but did not have success on my first attempt!). In my custom imageView class I call setScaleType(ScaleType.MATRIX) after super() in the constructor, and have the following method.

    protected boolean setFrame(int l, int t, int r, int b)
        Matrix matrix = getImageMatrix(); 
        float scaleFactor = getWidth()/(float)getDrawable().getIntrinsicWidth();    
        matrix.setScale(scaleFactor, scaleFactor, 0, 0);
        return super.setFrame(l, t, r, b);

I have placed int in the setFrame() method as in ImageView the call to configureBounds() is within this method, which is where all the scaling and matrix stuff takes place, so seems logical to me (say if you disagree)

Below is the super.setFrame() method from AOSP

    protected boolean setFrame(int l, int t, int r, int b) {
        boolean changed = super.setFrame(l, t, r, b);
        mHaveFrame = true;
        return changed;

Find the full class src here