You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取指定缩放级别下BoundingBox对应的Drawable?

Got it, let's tackle this step by step. You're already on the right track with leveraging CacheManager and IFilesystemCache—the tricky part usually comes with correctly arranging those tiles in your custom view without gaps, misalignment, or scaling issues. Here's how to smooth out the manual tile stitching process:

1. First, nail down the tile coordinate mapping

Osmdroid uses the standard XYZ tile system, where each tile has a fixed x/y index for a given zoom level. The getTilesCoverage method already gives you all tiles covering your BoundingBox, but you'll need to extract the x, y, and zoom values from each Tile object to position them correctly.

Pro tip: You can cross-verify tile coordinates using Osmdroid's TileSystem utility class if needed—methods like TileSystem.longitudeToTileX(longitude, zoom) and TileSystem.latitudeToTileY(latitude, zoom) will confirm if the returned tiles match your BoundingBox.

2. Calculate tile positions relative to your custom view

Before drawing, you need to map each tile's grid position to pixel coordinates in your view:

  • First, find the min/max x and y tile indices from your tiles list—this tells you the full grid of tiles you're working with.
  • Calculate the total pixel size of the entire tile grid: each tile is 256x256px by default, so total width = (maxTileX - minTileX + 1) * 256, total height = (maxTileY - minTileY + 1) * 256.
  • Determine the scale factor to fit the tile grid into your view: use Math.min(viewWidth / totalWidth, viewHeight / totalHeight) to maintain aspect ratio.
  • For each tile, compute its pixel offset from the top-left of the grid: xOffset = (tile.getX() - minTileX) * 256, yOffset = (tile.getY() - minTileY) * 256. Multiply these by the scale factor to get the final position in your view.
3. Handle tile drawing & stitching

Once you have positions sorted, focus on clean rendering:

  • Convert each Drawable from loadTile to a Bitmap (use ((BitmapDrawable) drawable).getBitmap()—just add a null check first, since cached tiles might be missing).
  • Use Canvas.drawBitmap() with a destination rectangle to place each tile precisely. This ensures no gaps between tiles and correct scaling.
  • Watch out for Osmdroid's y-axis quirk: tile y-indices increase from north to south, so don't flip the order unless your custom view uses a different coordinate system.
4. Fix common pain points
  • Missing tiles: If loadTile returns null, add a placeholder drawable or skip the tile to avoid blank spots.
  • Scaling artifacts: If you need sharper rendering, consider scaling the tiles before drawing (or using a higher zoom level and downscaling).
  • Coordinate drift: Double-check that your BoundingBox is correctly converted to tile coordinates—mixing up lat/lon order can throw off the entire grid.
Example code snippet

Here's a quick implementation you can adapt for your custom view:

// Initialize these with your existing values
BoundingBox targetBoundingBox = ...;
int targetZoom = ...;
MapView mapView = ...; // Your existing osmdroid MapView

// Get tiles and cache reference
CacheManager cacheManager = new CacheManager(mapView.getTileProvider());
List<Tile> tiles = cacheManager.getTilesCoverage(targetBoundingBox, targetZoom);
IFilesystemCache fileCache = ((MapTileFilesystemProvider) mapView.getTileProvider().getTileProvider()).getFilesystemCache();

// Calculate tile grid bounds
int minTileX = Integer.MAX_VALUE, maxTileX = Integer.MIN_VALUE;
int minTileY = Integer.MAX_VALUE, maxTileY = Integer.MIN_VALUE;
for (Tile tile : tiles) {
    minTileX = Math.min(minTileX, tile.getX());
    maxTileX = Math.max(maxTileX, tile.getX());
    minTileY = Math.min(minTileY, tile.getY());
    maxTileY = Math.max(maxTileY, tile.getY());
}
int totalTileWidth = (maxTileX - minTileX + 1) * 256;
int totalTileHeight = (maxTileY - minTileY + 1) * 256;

// Custom View onDraw implementation
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    float scale = Math.min((float) getWidth() / totalTileWidth, (float) getHeight() / totalTileHeight);

    for (Tile tile : tiles) {
        Drawable tileDrawable = fileCache.loadTile(tile);
        if (tileDrawable == null) continue;

        Bitmap tileBitmap = ((BitmapDrawable) tileDrawable).getBitmap();
        int gridX = (tile.getX() - minTileX) * 256;
        int gridY = (tile.getY() - minTileY) * 256;

        // Define where to draw the tile in the view
        Rect destRect = new Rect(
            (int) (gridX * scale),
            (int) (gridY * scale),
            (int) ((gridX + 256) * scale),
            (int) ((gridY + 256) * scale)
        );
        canvas.drawBitmap(tileBitmap, null, destRect, null);
    }
}

内容的提问来源于stack exchange,提问作者Andrew

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:34:50