ArcGIS Runtime for Android 自定义比例尺(100.x.x版本)

 ArcGIS Runtime for Android里没有提供比例尺控件。使用arcgis-runtime-toolkit-android这一工具箱可实现。链接:https://github.com/Esri/arcgis-runtime-toolkit-android ,但是工具箱中提供的比例尺有bug,在缩放时,偶尔会导致应用崩溃,所以我们自己实现比例尺控件.

参考:

https://blog.csdn.net/bit_kaki/article/details/72822617

该文中未提供完整源码,并且缺少几个方法,此处贴出完整源码.

 自定义View


import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.NinePatch;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;

import androidx.annotation.Nullable;

import com.esri.arcgisruntime.mapping.view.MapView;
import com.xys.lhk.R;

/**
 * 参考https://blog.csdn.net/bit_kaki/article/details/72822617
 */
public class MapScaleView extends View {
    Context context;
    int scaleWidth, scaleHeight;
    int textColor;
    String text;
    int scaleSpaceText;
    int textSize;
    Paint mPaint;

    MapView mapView;

    public MapScaleView(Context context) {
        this(context, null);
        this.context = context;
        this.initVariables();
    }

    public MapScaleView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
        this.context = context;
        this.initVariables();
    }

    public MapScaleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        this.initVariables();
    }

    public void setMapView(MapView mapView){
        this.mapView = mapView;
    }

    private void initVariables() {
        scaleWidth = 104;//
        scaleHeight = 30;//比例尺宽度例尺高度
        textColor = Color.BLACK;//比例尺字体颜色
        text = "20公里";//比例尺文本
        textSize = 18;//比例尺宽度
        scaleSpaceText = 8;//比例尺文本与图形的间隔高度
        mPaint = new Paint();//画笔
    }


    public void setText(String text){
        this.text = text;
    }

    public void setScaleWidth(int width){
        this.scaleWidth = width;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthSize = getWidthSize(widthMeasureSpec);
        int heightSize = getHeightSize(heightMeasureSpec);
        setMeasuredDimension(widthSize, heightSize);
    }


    /**
     * 测量ScaleView的宽度
     *
     * @param widthMeasureSpec
     * @return
     */
    private int getWidthSize(int widthMeasureSpec) {
        return MeasureSpec.getSize(widthMeasureSpec);
    }

    /**
     * 测量ScaleView的高度
     *
     * @param heightMeasureSpec
     * @return
     */
    private int getHeightSize(int heightMeasureSpec) {
        int mode = MeasureSpec.getMode(heightMeasureSpec);
        int height = 0;
        switch (mode) {
            case MeasureSpec.AT_MOST:
                height = textSize + scaleSpaceText + scaleHeight;
                break;
            case MeasureSpec.EXACTLY: {
                height = MeasureSpec.getSize(heightMeasureSpec);
                break;
            }
            case MeasureSpec.UNSPECIFIED: {
                height = Math.max(textSize + scaleSpaceText + scaleHeight, MeasureSpec.getSize(heightMeasureSpec));
                break;
            }
        }

        return height;
    }

    @SuppressLint("DrawAllocation")
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int width = scaleWidth ;
        mPaint.setColor(textColor);
        mPaint.setAntiAlias(true);
        mPaint.setTextSize(textSize);
        mPaint.setTypeface(Typeface.DEFAULT_BOLD);
        float textWidth = mPaint.measureText(text);
        canvas.drawText(text, (width - textWidth) / 2, textSize, mPaint);
        Rect scaleRect = new Rect(0, textSize + scaleSpaceText, width, textSize + scaleSpaceText + scaleHeight);
        drawNinepath(canvas, R.drawable.ic_ruler, scaleRect);
    }
    private void drawNinepath(Canvas canvas, int resId, Rect rect){
        Bitmap bmp= BitmapFactory.decodeResource(getResources(), resId);
        NinePatch patch = new NinePatch(bmp, bmp.getNinePatchChunk(), null);
        patch.draw(canvas, rect);
    }

    public void refreshScaleView() {
        if(mapView == null){
            throw new NullPointerException("you can call setMapView(MapView mapView) at first");
        }
        double scale=this.mapView.getMapScale()/100;//结果单位米,表示图上1厘米代表*米
        double ppi=getPPIOfDevice();
        if(scale>0&&scale<=20){//换算20米
            String unit = "20米";
            int scaleWidth=(int)(20*264/2.54/scale);//264为ppi,264/2.54为1厘米的像素数
            setText(unit);//更新文字
            setScaleWidth(scaleWidth);//更新比例尺长度
        }else if(scale>20&&scale<=50){//换算50米
            String unit = "50米";
            int scaleWidth=(int)(50*264/2.54/scale);
            setText(unit);//更新文字
            setScaleWidth(scaleWidth);//更新比例尺长度
        }else if(scale>50&&scale<=100){//换算20米
            String unit = "100米";
            int scaleWidth=(int)(100*264/2.54/scale);
            setText(unit);//更新文字
            setScaleWidth(scaleWidth);//更新比例尺长度
        }else if(scale>100&&scale<=200){//换算20米
            String unit = "200米";
            int scaleWidth=(int)(200*264/2.54/scale);
            setText(unit);//更新文字
            setScaleWidth(scaleWidth);//更新比例尺长度
        }else if(scale>200&&scale<=500){//换算20米
            String unit = "500米";
            int scaleWidth=(int)(500*264/2.54/scale);
            setText(unit);//更新文字
            setScaleWidth(scaleWidth);//更新比例尺长度
        }else if(scale>500&&scale<=1000){//换算20米
            String unit = "1公里";
            int scaleWidth=(int)(1000*264/2.54/scale);
            setText(unit);//更新文字
            setScaleWidth(scaleWidth);//更新比例尺长度
        }else if(scale>1000&&scale<=2000){//换算20米
            String unit = "2公里";
            int scaleWidth=(int)(2000*264/2.54/scale);
            setText(unit);//更新文字
            setScaleWidth(scaleWidth);//更新比例尺长度
        }else if(scale>2000&&scale<=5000){//换算20米
            String unit = "5公里";
            int scaleWidth=(int)(5000*264/2.54/scale);
            setText(unit);//更新文字
            setScaleWidth(scaleWidth);//更新比例尺长度
        }else if(scale>5000&&scale<=10000){//换算20米
            String unit = "10公里";
            int scaleWidth=(int)(10000*264/2.54/scale);
            setText(unit);//更新文字
            setScaleWidth(scaleWidth);//更新比例尺长度
        }else if(scale>10000&&scale<=20000){//换算20米
            String unit = "20公里";
            int scaleWidth=(int)(20000*264/2.54/scale);
            setText(unit);//更新文字
            setScaleWidth(scaleWidth);//更新比例尺长度
        }else if(scale>20000&&scale<=25000){//换算20米
            String unit = "25公里";
            int scaleWidth=(int)(25000*264/2.54/scale);
            setText(unit);//更新文字
            setScaleWidth(scaleWidth);//更新比例尺长度
        }else if(scale>25000&&scale<=50000){//换算20米
            String unit = "50公里";
            int scaleWidth=(int)(50000*264/2.54/scale);
            setText(unit);//更新文字
            setScaleWidth(scaleWidth);//更新比例尺长度
        }else if(scale>50000&&scale<=100000){//换算20米
            String unit = "100公里";
            int scaleWidth=(int)(100000*264/2.54/scale);
            setText(unit);//更新文字
            setScaleWidth(scaleWidth);//更新比例尺长度
        }else if(scale>100000&&scale<=200000){//换算20米
            String unit = "200公里";
            int scaleWidth=(int)(200000*264/2.54/scale);
            setText(unit);//更新文字
            setScaleWidth(scaleWidth);//更新比例尺长度
        }else if(scale>200000&&scale<=250000){//换算20米
            String unit = "250公里";
            int scaleWidth=(int)(250000*264/2.54/scale);
            setText(unit);//更新文字
            setScaleWidth(scaleWidth);//更新比例尺长度
        }else if(scale>250000&&scale<=500000){//换算20米
            String unit = "500公里";
            int scaleWidth=(int)(500000*264/2.54/scale);
            setText(unit);//更新文字
            setScaleWidth(scaleWidth);//更新比例尺长度
        }else if(scale>500000&&scale<=scale){//换算20米
            String unit = "1000公里";
            int scaleWidth=(int)(1000000*264/2.54/scale);
            setText(unit);//更新文字
            setScaleWidth(scaleWidth);//更新比例尺长度
        }

        invalidate();
    }

    private double getPPIOfDevice() {
        Point point = new Point();
        Activity activity=(Activity) context;
        activity.getWindowManager().getDefaultDisplay().getRealSize(point);//获取屏幕的真实分辨率
        DisplayMetrics dm = getResources().getDisplayMetrics();
        double x = Math.pow(point.x/ dm.xdpi, 2);//
        double y = Math.pow(point.y / dm.ydpi, 2);
        double screenInches = Math.sqrt(x + y);
        Double ppi=Math.sqrt(Math.pow(point.x, 2)+Math.pow(point.y, 2))/screenInches;
        return ppi;
    }
}

 布局文件

<com.xys.lhk.widget.MapScaleView
            android:id="@+id/scalebar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

绑定MapView

scalebar.setMapView(mapView)

添加监听

mapView.addMapChangeListener(new MapScaleChangedListener(){
    public void mapScaleChanged(MapScaleChangedEvent it) {
                     scaleView.refreshScaleView();
            }
})

自定义的.9图片,需要命名为 ic_ruler

效果图:

比例尺参考:ArcGIS for Android 自定义地图比例尺_arcgis for android tiled的宽高是怎么拼接上去的_bit_kaki的博客-CSDN博客

.9图片制作参考:

android 制作 .9图_android .9图制作_14skyang的博客-CSDN博客

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值