moagrius / TileView

TileView is a subclass of android.view.ViewGroup that asynchronously displays, pans and zooms tile-based images. Plugins are available for features like markers, hotspots, and path drawing.
MIT License
1.46k stars 337 forks source link

Scale background #513

Closed inneke-dc closed 5 years ago

inneke-dc commented 5 years ago

How can I set a background that scales as the tiles scale? I have a low res image I want to show in the background while the tiles are loading. I set this on the 'container' view: tileView.container.background = lowResDrawable. This drawable is loaded with Glide and has the same size as the size being set on the tileview builder. This looks okay for the start state (I can see the top left corner of the background image), but when I zoom, the background remains on the same (deepest) zoom level.

moagrius commented 5 years ago

Try setting the background on the TileView itself. If that doesn't work, post back - I'll be doing some bug work tonight or tomorrow anyway so can include this

inneke-dc commented 5 years ago

@moagrius Setting the background on the TileView itself causes it to always be in a completely zoomed out state and it doesn't pan or zoom, so it's actually a static background that way. Setting it on the container was slightly better in the way that it panned correctly, just the zoom level was fixed.

moagrius commented 5 years ago

K. I'll check it out tonight

moagrius commented 5 years ago

OK, there's a plugin for that.

You need a bitmap, so if you have something in res/drawable, you could do this:

Bitmap background = BitmapFactory.decodeResource(getResources(), R.drawable.downsample, options);

Then in your builder, install it:

.installPlugin(new LowFidelityBackgroundPlugin(background))

e.g.,

Bitmap background = BitmapFactory.decodeResource(getResources(), R.drawable.downsample, options);
new TileView.Builder(tileView)
        .setSize(17934, 13452)
        .defineZoomLevel("tiles/phi-1000000-%1$d_%2$d.jpg")
        .installPlugin(new LowFidelityBackgroundPlugin(background))
        .build();
inneke-dc commented 5 years ago

I just tried that, but it's the same result as setting the low res image as background on the container: it doesn't scale. Looking into the code of LowFidelityBackgroundPlugin, I see that an ImageView is added to the container, so it's always the same size as the size provided to the TileView.Builder. No scale callbacks are handled. I'll try to create my own plugin which scales the bitmap in the imageview, but no clue if this will work.

inneke-dc commented 5 years ago

I got to a working solution!

class BackgroundPlugin(private val bitmap: Bitmap): TileView.Plugin, TileView.Listener {

    private lateinit var imageView: ImageView

    override fun install(tileView: TileView) {
        imageView = ImageView(tileView.context).apply {
            setImageBitmap(bitmap)
            scaleType = ImageView.ScaleType.MATRIX
        }

        tileView.addView(imageView, 0)
        tileView.addListener(this)
    }

    override fun onScaleChanged(scale: Float, previous: Float) {
        val scaleToFitImageView = imageView.width.toFloat() / bitmap.width
        val scaleToMatchZoom = scaleToFitImageView * scale

        val matrix = Matrix()
        matrix.setScale(scaleToMatchZoom, scaleToMatchZoom)
        imageView.imageMatrix = matrix
    }
}
moagrius commented 5 years ago

Hm I thought it was scaling already. I'll double check tomorrow; if not, I'll definitely look into including something like the solution you posted. Thanks for contributing!

On Wed, May 15, 2019 at 5:10 AM inneke-dc notifications@github.com wrote:

I got to a working solution!

`class BackgroundPlugin(private val bitmap: Bitmap): TileView.Plugin, TileView.Listener {

private lateinit var imageView: ImageView

override fun install(tileView: TileView) { imageView = ImageView(tileView.context).apply { setImageBitmap(bitmap) scaleType = ImageView.ScaleType.MATRIX }

tileView.addView(imageView, 0)
tileView.addListener(this)

}

override fun onScaleChanged(scale: Float, previous: Float) { val scaleToFitImageView = imageView.width.toFloat() / bitmap.width val scaleToMatchZoom = scaleToFitImageView * scale

val matrix = Matrix()
matrix.setScale(scaleToMatchZoom, scaleToMatchZoom)
imageView.imageMatrix = matrix

}

}`

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/moagrius/TileView/issues/513?email_source=notifications&email_token=AAFLHIBBUWNYIMHUC2OLKMLPVPOSHA5CNFSM4HMPGRL2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODVOGCQI#issuecomment-492593473, or mute the thread https://github.com/notifications/unsubscribe-auth/AAFLHIAFUDJS3FSD375MMVDPVPOSHANCNFSM4HMPGRLQ .

moagrius commented 5 years ago

Huh you're right! I'll modify your code and include it in the existing LowFidelityBackgroundPlugin class, and include that in the next update. Thanks again for contributing!

moagrius commented 5 years ago

I've used a similar version to your fix, just slightly simplified. It's in the latest version as an update to LowFidelityBackgroundPlugin. Thanks again for the contribution.