Baike.dev
All toolsOnline toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
T

TileView

> 编程语言
Open source

TileView is a subclass of android.view.ViewGroup that asynchronously displays, pans and zooms tile-based images. Plugins are available for features like marker

1.5K stars0 likes1 views
WebsiteGitHub

About

TileView is a subclass of android.view.ViewGroup that asynchronously displays, pans and zooms tile-based images. Plugins are available for features like marker

This project isn't maintained anymore. It is now recommended to use https://github.com/peterLaurence/MapView.

MapView is maintained by Peter, one of our main contributors. MapView is an highly optimized Kotlin version (which can be used from Java projects) that's very cool and fast. It's 100% production ready and open source. Peter uses this widget in his app at https://github.com/peterLaurence/TrekMe/.

TileView: Version 4

The TileView widget is a subclass of ViewGroup renders and positions bitmap tiles to compose a larger, original image, often one too large to display normally.

Vesion 4 is effectively the promotion of version 3 from beta to production-ready, fixing the issues brought up by you, the users. While normally this'd probably be done using a series of minor version bumps, and this might be 3.4.11, there was a change to the base package name, and this requires a major change according to semver, since it's a breaking change for past versions.

Also of note, the universal (2-D) ScrollView class, and related classes like ScalingScrollView (which is a subclass of the 2D universal ScrollView, but also manages scaling and scale gestures) is now it's own repository: https://github.com/moagrius/ScrollView, and available with implementation 'com.moagrius:scrollview:1.0.3'. It is now included in the TileView project using normal gradle dependency operations, specifically using api rather than implementation but otherwise similar to other dependencies and is being pulled down from jcenter and reconciled normally.

Demos for ScrollView are in the ScrollView repo. Demos for TileView are in this repository.

Feel free to use ScrollView as a standalone widget if you don't need image tiling.

Change Log

4.0.7 (most recent)

  • Fixed bug with MarkerPlugin where markers clipped when scaled beyond 100%.

4.0.5 (most recent)

  • Save and restore instance state properly implemented.
  • Removed a bug that produced an increasing number of delayed callbacks from a Handler. This is a serious memory leak and all users on versions 4.0.3 and 4.0.4 should immediately upgrade to 4.0.5.

4.0.4

  • Update ScalingScrollView to version 1.0.10, which provides additional methods and method exposure (many private access methods became protected)

4.0.3

  • You can scale greater than 1f now without flicker, and without clipping.
  • Remote images should decode now with a much higher rate of success, nearing 100%.
  • Marker plugin API has been updated and show now work propertly (see TileViewDemoAdvanced Activity).
  • LowFidelityBackgroundPlugin now scaled and positions appropriately with the TileView host.
  • The COVER and CONTAIN MinimumScaleModes should work properly now.
  • Upgraded from com.moagrius:scrollview:1.0.4 to 1.0.9

TileView

Very large images in Android will often result in an OutOfMemoryError. Memory is finite, and bitmaps take a great deal of it. TileView solves this by stitching together small pieces of the image (tiles) and displaying them reconstructed in the area of the screen visible to your user.

Out of the box, the TileView will manage the tiled image, including subsampling when needed, flinging, dragging, scaling, and multiple levels of detail.

Additional plugins are provided to allow adding overlaying Views (markers), info windows, hot spots, path drawing, and coordinate translation.

Version 4 is fairly young. If you're need a stable version, the last release of version 2 is 2.7.7, and is available as a branch, here: https://github.com/moagrius/TileView/tree/version-2.7.7, or from the releases page. You can also get it from gradle using the old namespace: implementation 'com.qozix:tileview:2.7.7'

No further work will be done on version 2.

This is truly open source. I'm very happy to accept improvements or bug fixes - no caveats; create an issue, branch, and create a PR. While I'm not super interested in finding bugs and don't want the issues page to become a wasteland (I already know what most of them are, and will start to document them as this make its way into the wild), I am very interested in fixing those bugs - if you have the time to locate and correct a bug, please open a PR.

Installation

Add this to your app module's build.gradle.

implementation 'com.moagrius:tileview:4.0.7'
Quick Setup
  1. Tile an image into image slices of a set size, e.g., 256x256 instructions // TODO
  2. Name the tiles by the column and row number, e.g., 'tile-1-2.png' for the image tile that would be at the 2nd column from left and 3rd row from top.
  3. Create a new application with a single activity ('Main').
  4. Save the image tiles to your assets directory.
  5. Add the latest version to your gradle dependencies.
  6. In the Main Activity, use this for onCreate:
@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  TileView tileView = new TileView.Builder(this)
  	.setSize(3000, 3000)
  	.defineZoomLevel("tile-%d-%d.png")
  	.build();
  setContentView(tileView);
}

That's it. You should have a tiled image that only renders the pieces of the image that are within the current viewport, and pans and zooms with gestures.

Note that String replacements for rows and columns is not required - you can supply literally any Object instance to a DetailLevel, and a BitmapProvider implementation can use that Object to generate a Bitmap instance however you want.

What Changed

As a user, the biggest things you'll notice are:

  1. You no longer need redandant tile sets or detail levels. If your image doesn't change the details (e.g., show different images or labels at different zoom levels), you don't need to create tiles sets besides the original, full size one. The program will now use subsampling to do this work for you without any setup on your part: one call to defineDetail(anyObject) is sufficient.
  2. No more BitmapProvider. We're just doing way too much management of Bitmaps, including re-use and caching, to allow any stray Bitmap to wander in. This may change in the future, but the replacement for now is StreamProvider - basically the same thing but you just return an InputStream _instead of a Bitmap, and we take care of the rest.
  3. Greatly improved bitmap management. For details, see How It Works
  4. Touch events are now managed appropriately, rather than blindly consumed. We now use the same logic as the framework's ScrollView, so you can assign normal OnClickListeners or similiar gesture management devices on things like markers and callouts, without interrupting drag or fling operations.
  5. Plugin architecture. Only sign up for things you need - if you don't need markers, don't install the plugin, and keep things snappy and simple. Check TileViewDemoSimple for a very bare implementation, and TileViewDemoAdvanced for a more dressed up version.
  6. Much smaller codebase. Almost all the magic now happens in either Tile or TileView - if you understand those 2 classes, you understand the majority of the project.
  7. Decomposition. This takes a little explanation. There are now 3 major, public widgets: ScrollView, ScalingScrollView, and TileView. Each inherits from the last. You'll notice the demo module has Activities for each of these classes.
ScrollView

com.moagrius.widgets.ScrollView is a clone of AOSP's ScrollView and HorizontalScrollView, with some inspiration taken from RecyclerView and GestureDetector. That means the APIs will be very familiar to anyone who's used the framework-provided ScrollView. The big difference here is that com.moagrius.widgets.ScrollView functions along both axes, without configuation. For example, if you have a layout that matches parent width and expands vertically, ScrollView will scroll it vertically - the converse holds. If you have a layout that larger in both directions than the parent, ScrollView will scroll in any direction.

Again, no configration is required - there is no orientation attribute - it does it's best to figure out what makes sense.

ScalingScrollView

ScalingScrollView extends ScrollView and adds scaling APIs, as well as built-in scaling gesture managent (pinch and double tap to zoom). By default, it will visually scale its content, but that can be disabled with a single setter setShouldVisuallyScaleContents(false), and you can manage your content with a porportional scaled value. Similarly, it will lay itself out to the current scale value, unless that too is disabled setWillHandleContentSize(true)

At some point, ScalingScrollView will be it's own repository, and will be a dependency of TileView.

TileView inherits from ScalingScrollView, and adds tiling functionality.

From here down may be a bit dry but might be interesting to people interested in contributing to the process.

How It Works

Problem

You have an image too large to display with an OutOfMemoryError.

Solution

Chop the image into tiles and reconstruct them to fill the viewport, and only the viewport. As the user scrolls (or scales), aggressively recycle any bitmap data that is not visible to the user at any given time, and render any new "tiles" that are not within the viewable area.

Basic operation

Use the width and height of the view that contains this image, plus it's scroll position, to determine space we call the viewport.

Divide the corners of the viewport (left, top, right, bottom) by the size of the cell, which provide the start and end row and column. Round down the left and top and round up the right and bottom to make sure there are not empty patches - as long as any pixel of a tile is visible in the viewport, it must be rendered (one reason - among many - to carefully consider tile size, and not default to as large as possible).

From start column to end column and start row to end row are the tiles (imagine a 2D array) that should be rendered at that moment.

For example, let's consider...

  • image is 10,000 square
  • viewport is 1080 by 1920
  • viewport is at scroll position (1000, 500)
  • so our computed viewport is (1000, 500 - 2080, 2420)
  • out tiles are 256 square

so grid is

  1. start column 1000 / 256 = 3
  2. end column is 2080 / 256 = 9
  3. start row is 500 / 256 = 2
  4. end row is 2420 / 256 = 10

Iterate between those points...

for (int i = grid.columns.start; i < grid.columns.end; i++) {
  for (int j = grid.rows.start; j < grid.rows.end; j++) {

And your grid looks like this:

…

As long as there's only the one size, scale is uniformly applied - just multiple tile size in the previous math by the current scale, and your grid remains intact.

Scaling

At every half way point, the image is at 50% or smaller, so subsample it to save memory: https://developer.android.com/topic/performance/graphics/load-bitmap#load-bitmap

Remember that each subsample (representing half the size) will actually quarter the amount of memory required for the bitmap. Do this at every half: 50%, 25, 12.5, 6.25, 3.625, etc.

When you add another detail level, things get a little more complicated, but not terribly...

Detail/Zoom Levels
  • Subsampling starts over at the last provided detail level, so it's no longer directly taken from the scale
  • Your grid now has to be "unscaled" - now it's tile size * scale (as it was before), but now must be unscaled by an amount equal to the emulation of the detail level.
  • This unscaled value is effectively the inverse of the scale, so 50% scale would be times 2, 25% would be times 4, 12.5% would be times 8
  • However, this is a constant value, so anything from 50% to 26% would be times 2, so a better descript might be "zoom left shift one" or (zoom << 1)
  • This works fairly well as is at this point, but on

Issues· 19 open

View all issuesOpen on GitHub

No open issues yet, or sync has not completed.

> Tags

Javaandroidandroid-layoutandroid-libraryandroid-viewgroup

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
Category编程语言
PricingOpen source

> Related tools

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言