自定义view代码

public class ChinaMapView extends View {

private int[] colorArray = new int[]{0xFF239BD7, 0xFF30A9E5, 0xFF80CBF1, 0xFFFFFFFF};//各省地图显示的颜色
private Context context;//上下文
private List<ProviceItem> itemList;//各省地图列表 各省地图颜色 与路径
private Paint paint; //初始化画笔
private ProviceItem select; //选中的省份
private RectF totalRect;//中国地图的矩形范围
private float scale = 1.0f;//中国地图的缩放比例

public ChinaMapView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}


public ChinaMapView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

private void init(Context context) {
this.context = context;
paint = new Paint();
paint.setAntiAlias(true);
itemList = new ArrayList<>();
loadThread.start();

}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//获取当前控件的高度 让地图宽高适配当前控件
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
if (totalRect != null) {
double mapWidth = totalRect.width();
scale = (float) (width / mapWidth); //获取控件高度为了让地图能缩放到和控件宽高适配
}
setMeasuredDimension(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
}
//加载中国地图的路径相对比较耗时,这里开启子线程来加载
private Thread loadThread = new Thread() {
@Override
public void run() {
final InputStream inputStream = context.getResources().openRawResource(R.raw.china);//读取地图svg
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); //获取DocumentBuilderFactory实例
DocumentBuilder builder = null;
try {
builder = factory.newDocumentBuilder();
Document doc = builder.parse(inputStream);//解析svg的输入流
Element rootElement = doc.getDocumentElement();
NodeList items = rootElement.getElementsByTagName("path");
//获取地图的整个上下左右位置,
float left = -1;
float right = -1;
float top = -1;
float bottom = -1;
List<ProviceItem> list = new ArrayList<>();
for (int i = 0; i < items.getLength(); i++) {
Element element = (Element) items.item(i);
String pathData = element.getAttribute("android:pathData");
@SuppressLint("RestrictedApi")
Path path = PathParser.createPathFromPathData(pathData);
ProviceItem proviceItem = new ProviceItem(path);//设置路径
proviceItem.setDrawColor(colorArray[i % 4]);//设置颜色
//取每个省的上下左右 最后拿出最小或者最大的来充当 总地图的上下左右
RectF rect = new RectF();
path.computeBounds(rect, true);
left = left == -1 ? rect.left : Math.min(left, rect.left);
right = right == -1 ? rect.right : Math.max(right, rect.right);
top = top == -1 ? rect.top : Math.min(top, rect.top);
bottom = bottom == -1 ? rect.bottom : Math.max(bottom, rect.bottom);
list.add(proviceItem);
}
itemList = list;
totalRect = new RectF(left, top, right, bottom);//设置地图的上下左右位置

//加载完以后刷新界面
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
requestLayout();
invalidate();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
};

@Override
public boolean onTouchEvent(MotionEvent event) {
handleTouch(event.getX() / scale, event.getY() / scale);
return super.onTouchEvent(event);
}

private void handleTouch(float x, float y) {
if (itemList == null){
return;
}
ProviceItem selectItem = null;
for (ProviceItem proviceItem : itemList){
if (proviceItem.isTouch(x,y)){
selectItem = proviceItem;
}
}
if (selectItem != null){
select = selectItem;
postInvalidate();
}
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (itemList != null){
canvas.save();
canvas.scale(scale,scale);//把画布缩放匹配到本控件的宽高
for (ProviceItem proviceItem : itemList){
if (proviceItem != select){
proviceItem.drawItem(canvas,paint,false);
}else {
proviceItem.drawItem(canvas,paint,true);
}
}
}
}
}

---------------------

原文地址:https://www.cnblogs.com/hyhy904/p/11291160.html