Monday, 2 June 2014

Scaling images in onCreate: Android


Android developers mostly face out of memory error when loading images into imageView. Primarily this error is raised because we try to load very large image and there is not much memory available. To prevent this, this is good idea to scale down the image according to imageView height/width. setScaledAvatar() method is doing this scaling.

private void setScaledAvatar(String avatarPath, ImageView imageView) {

        // Get the dimensions of the View
        int targetW = imageView.getWidth();
        int targetH = imageView.getHeight();

        // Get the dimensions of the bitmap
        BitmapFactory.Options bmOptions = new BitmapFactory.Options();

        bmOptions.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(avatarPath, bmOptions);
        int photoW = bmOptions.outWidth;
        int photoH = bmOptions.outHeight;

        if (targetW == 0 || targetH == 0) {
            throw new RuntimeException("ImageView height or width is zero");
        }


        // Determine how much to scale down the image
        int scaleFactor = Math.min(photoW / targetW, photoH / targetH);

        // Decode the image file into a Bitmap sized to fill the View
        bmOptions.inJustDecodeBounds = false;
        bmOptions.inSampleSize = scaleFactor;
        bmOptions.inPurgeable = true;

        Bitmap bitmap = BitmapFactory.decodeFile(avatarPath, bmOptions);
        imageView.setImageBitmap(bitmap);

   
    }

However if you want to use this method on activity onCreate, this will throw divided by zero exception. why? because in onCreate, view are not yet actually drawn and imageView height and width are zero. To handle this situation,we can getViewTree observer and override addGlobalLayout method to for scalling image according to imageView height/width.
 

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.main_fragment);

       String path = Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES).getAbsolutePath()
                + "/" + "sample.png";
        ImageView avatar = (ImageView) findViewById(R.id.ivAvatar);

      
        avatar.getViewTreeObserver().addOnGlobalLayoutListener(
                new ViewTreeObserver.OnGlobalLayoutListener() {

                    @Override
                    public void onGlobalLayout() {
                        if (path != null && avatar != null) {

                            setScaledAvatar(path, avatar);
                        }

                    }
                });

    }


No comments:

Post a Comment