Search code examples
androidbitmapandroid-glidetouchimageview

Load higher res on zoom, prevent resource release


What I want to accomplish is to load an image into TouchImageView (https://github.com/MikeOrtiz/TouchImageView) with glide using default size (view's size) and then on zoom I would like to replace the bitmap with higher res.

My approach:

 lang-java
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    imageView.setOnTouchImageViewListener {
        if (!zoomedIn && imageView.currentZoom == MAX_ZOOM) {
            zoomedIn = true
            loadImage(uri, Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
        }
    }

    loadImage(uri)
}

private fun loadImage(uri: Uri, width: Int = 0, height: Int = 0) {
    Glide.with(context)
            .asBitmap()
            .load(uri)
            .let {
                if (width == 0 && height == 0) {
                    it
                } else {
                    it.override(width, height)
                }
            }
            .centerInside()
            .into(imageView)
}

The implementation causes the ImageView to display black background when higher res image is being loaded. I assume it is because Glide is releasing resources on each load (I am pretty sure I found this in the documentation).

Is there a way to prevent it in this particular scenario?

I do not want use Thumbnail feature for the above purpose as it will load high res image every time for every image (I would prefer to do it only on zoom for user to actually benefit from additional details of the image).

Maybe there is a totally different approach that I am not seeing?


Solution

  • Solution is actually fairly simple.

    Just use two TouchImageViews (iv, ivhighres) and replace them once the high res image is loaded.

    You can user ViewSwitcher (as Documentation suggests) if you would like to animate the change.

    Note that you need to call ivhighres.setZoom(iv) for the zoom properties to be mirrored from the low res image to the high res image.

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        iv.setOnTouchImageViewListener {
            ivhighres.setZoom(iv)
            if (!zoomedIn && imageView.currentZoom == MAX_ZOOM) {
                zoomedIn = true
                loadImageHighRes(uri)
            }
        }
    
        loadImage(uri)
    }
    
    private fun loadImage(uri: Uri) {
        Glide.with(context)
                .asBitmap()
                .load(uri)
                .centerInside()
                .into(iv)
    }
    
    private fun loadImageHighRes(uri: Uri) {
        Glide.with(context)
                .asBitmap()
                .load(uri)
                .override(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
                .centerInside()
                .into(object : CustomViewTarget<TouchImageView, Bitmap>(ivhighres) {
                        override fun onLoadFailed(errorDrawable: Drawable?) {
                        }
    
                        override fun onResourceCleared(placeholder: Drawable?) {
                            ivhighres?.setImageDrawable(placeholder)
                        }
    
                        override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
                            ivhighres?.setImageBitmap(resource)
                            ivhighres?.visibility = View.VISIBLE
                            iv?.visibility = View.GONE
                        }
    
                    })
    }