首页 Android 正文
  • 本文约1892字,阅读需9分钟
  • 41
  • 0

Android 航线缩略图简易绘制实现

摘要

记录下在航线列表要显示航线缩略图预览航线,通过经纬度航线数据绘制生成预览图。项目上要求缩略图要带卫星地图背景,需要通过地图TextureView去截图,此方案就没有在实际项目上应用。 一、实现效果预览 以下是不含地图背景的航线缩略图绘制效果,根据经纬度参数来绘制航线。 二、实现代码 绘制实现类 import android.graphics.Bitmap; ...

记录下在航线列表要显示航线缩略图预览航线,通过经纬度航线数据绘制生成预览图。项目上要求缩略图要带卫星地图背景,需要通过地图TextureView去截图,此方案就没有在实际项目上应用。

一、实现效果预览

以下是不含地图背景的航线缩略图绘制效果,根据经纬度参数来绘制航线。

Android 航线缩略图简易绘制实现
Android 航线缩略图简易绘制实现
Android 航线缩略图简易绘制实现

二、实现代码

绘制实现类

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import com.ht.airnavi.core.entity.WayPoint;
import java.util.List;

public class FlightPathDrawer {
    private float padding; // 边距
    private Paint mPaint = new Paint();
    private  Path mPath = new Path();

    public FlightPathDrawer(int color, float padding) {
        this.padding = padding;
        mPaint.setColor(color);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(1);
        mPaint.setAntiAlias(true);
    }

    // 计算最小和最大经纬度,确定航线的边界范围
    private float[] calculateBoundingBox(List<WayPoint> flightPathCoordinates) {
        float minLat = Float.MAX_VALUE, minLon = Float.MAX_VALUE;
        float maxLat = Float.MIN_VALUE, maxLon = Float.MIN_VALUE;

        for (WayPoint loc : flightPathCoordinates) {
            float lat = (float) loc.getLatitude();
            float lon = (float) loc.getLongitude();

            if (lat < minLat) minLat = lat;
            if (lat > maxLat) maxLat = lat;
            if (lon < minLon) minLon = lon;
            if (lon > maxLon) maxLon = lon;
        }

        return new float[]{minLat, maxLat, minLon, maxLon};
    }

    // 经纬度转换为屏幕坐标
    private PointF latLngToScreen(float latitude, float longitude, float minLat, float maxLat, float minLon, float maxLon, float mapWidth, float mapHeight) {
        // 将经纬度按范围缩放到图片尺寸内,并预留边距
        float x = (longitude - minLon) / (maxLon - minLon) * (mapWidth - 2 * padding) + padding;
        float y = (maxLat - latitude) / (maxLat - minLat) * (mapHeight - 2 * padding) + padding;
        return new PointF(x, y);
    }

    // 绘制航线并只显示航线范围,四周留边距
    public Bitmap drawFlightPathWithPadding(List<WayPoint> flightPathCoordinates, int outputWidth, int outputHeight) {
        // 创建一个新的 Bitmap,宽高由传入参数指定
        Bitmap resultBitmap = Bitmap.createBitmap(outputWidth, outputHeight, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(resultBitmap);

        // 获取航线的边界范围 (minLat, maxLat, minLon, maxLon)
        float[] boundingBox = calculateBoundingBox(flightPathCoordinates);
        float minLat = boundingBox[0], maxLat = boundingBox[1];
        float minLon = boundingBox[2], maxLon = boundingBox[3];

        // 创建路径
        mPath.reset();

        // 遍历航线的坐标点,将经纬度转换为屏幕坐标并添加到路径中
        for (int i = 0; i < flightPathCoordinates.size(); i++) {
            WayPoint location = flightPathCoordinates.get(i);
            PointF point = latLngToScreen((float) location.getLatitude(), (float) location.getLongitude(),
                    minLat, maxLat, minLon, maxLon, outputWidth, outputHeight);

            if (i == 0) {
                mPath.moveTo(point.x, point.y);  // 移动到路径的起始点
            } else {
                mPath.lineTo(point.x, point.y);  // 绘制线段到下一个点
            }
        }

        // 绘制路径到画布上
        canvas.drawPath(mPath, mPaint);

        return resultBitmap;
    }
}

WayPoint对象类:

data class WayPoint(
    var latitude: Long,
    var longitude: Long,
)

生成缩略图保存到SD卡,调用代码范例:

private fun generateThumbnail(wayPointList: List<WayPoint>?) {
        // 创建航线绘制类
        val drawer = FlightPathDrawer(resources.getColor(android.R.color.holo_green_light), 50f) // 50为边距
        // 输出的Bitmap宽高
        val outputWidth = 128
        val outputHeight = 128
        // 绘制航线到Bitmap上
        try {
            wayPointList?.let {
                val resultBitmap = drawer.drawFlightPathWithPadding(
                    wayPointList,
                    outputWidth,
                    outputHeight
                )
                saveBitmapToPNG(resultBitmap, System.currentTimeMillis().toString())
            }
        } catch (e: Exception) {

        }
    }

    fun saveBitmapToPNG(bitmap: Bitmap, fileName: String): Boolean {
        val sdCard = Environment.getExternalStorageDirectory()
        val dir = File(sdCard.absolutePath + "/naviLine/")

        if (!dir.exists()) {
            dir.mkdirs()
        }

        val file = File(dir, "$fileName.png")
        return try {
            val fOut = FileOutputStream(file)
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut)
            fOut.flush()
            fOut.close()
            true
        } catch (e: Exception) {
            e.printStackTrace()
            false
        }
    }
标签:航线

扫描二维码,在手机上阅读


    评论