自定义开发是android的必不可少的技能之一,要熟练的掌握,需要大家不断的学习,写代码才能日积月累。好了,废话不多说了;看下面的步骤:
1,用的到的两个地址https://www.amcharts.com/svg-maps/?map=china (需要下载国家的svg)
http://inloop.github.io/svg2android/ 下载后需要把svg文件在该地址中解析为Android可识别的代码
2,打开android studio—— res文件下,新建一个raw文件夹,然后把vsg文件复制粘贴到raw文件中,以下图是放入后的效果
3,在java中创建Java类继承View ,实现该类的构成函数,如下代码:
public class ChinaMapView extends View { private Paint mPaint; private Context context; private int[] colors = new int[]{Color.RED, Color.GREEN, Color.YELLOW, Color.GREEN}; private ArrayListitemList = new ArrayList<>(); private ProvinceBean selectItem; private GestureDetectorCompat gestureDetectorCompat; public ChinaMapView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } private void init(Context context) { //准备画笔 mPaint = new Paint(); mPaint.setAntiAlias(true); this.context = context; thread.start(); //手势处理类 gestureDetectorCompat = new GestureDetectorCompat(context, new GestureDetector.SimpleOnGestureListener() { @Override public boolean onDown(MotionEvent e) { Log.d("event ", e.getAction() + ""); handlerTouch(e.getX(), e.getY()); return true; } }); } private void handlerTouch(float x, float y) { if (itemList != null) { for (ProvinceBean item : itemList) { if (item.isTouch((int) (x / 1.4), (int) (y / 1.4))) { selectItem = item; postInvalidate(); break; } } } } public ChinaMapView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean onTouchEvent(MotionEvent event) { return gestureDetectorCompat.onTouchEvent(event); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.save(); canvas.scale(1.4f, 1.4f); for (int i = 0; i < itemList.size(); i++) { if (selectItem != itemList.get(i)) { itemList.get(i).draw(mPaint, canvas, false); } } if (selectItem != null) { selectItem.draw(mPaint, canvas, true); } canvas.restore(); } Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (msg != null) { postInvalidate(); } } }; Thread thread = new Thread() { @Override public void run() { //dom解析xml InputStream inputStream = context.getResources().openRawResource(R.raw.chinahigh); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = null; try { builder = factory.newDocumentBuilder(); Document document = builder.parse(inputStream);//解析输入流 Element rootElement = document.getDocumentElement(); NodeList items = rootElement.getElementsByTagName("path"); Log.d("MyMapView:", "集合大小=" + items.getLength()); for (int i = 0; i < items.getLength(); i++) { int colorsIndex = i % 4; Element element = (Element) items.item(i); String pathData = element.getAttribute("android:pathData"); @SuppressLint("RestrictedApi") Path path = PathParser.createPathFromPathData(pathData); ProvinceBean provinceBean = new ProvinceBean(path); provinceBean.setColor(colors[colorsIndex]); itemList.add(provinceBean); } handler.sendEmptyMessage(1); } catch (Exception e) { e.printStackTrace(); } } }; } class ProvinceBean { private Path path; private int color; public ProvinceBean(Path path) { this.path = path; } public int getColor() { return color; } public void setColor(int color) { this.color = color; } /** * 绘制省份 * * @param paint * @param canvas * @param isSelected 是否被选中 */ public void draw(Paint paint, Canvas canvas, boolean isSelected) { if (isSelected) { //绘制点击后的背景 paint.setStrokeWidth(2); paint.setColor(color); paint.setStyle(Paint.Style.FILL); //添加阴影 paint.setShadowLayer(8, 0, 0, Color.BLACK); canvas.drawPath(path, paint); //绘制背景 paint.clearShadowLayer(); paint.setStrokeWidth(2); paint.setColor(color); paint.setStyle(Paint.Style.FILL); canvas.drawPath(path, paint); } else { //绘制背景 paint.setStrokeWidth(2); paint.clearShadowLayer(); paint.setColor(color); paint.setStyle(Paint.Style.FILL); canvas.drawPath(path, paint); //绘制边界线 paint.setStrokeWidth(1); paint.setColor(Color.GRAY); paint.setStyle(Paint.Style.STROKE); canvas.drawPath(path, paint); } } //触摸点是否在这个省的path内 public boolean isTouch(int x, int y) { //构造一个矩形对象 RectF rectF = new RectF(); //返回路径控制点的计算边界保存到rectF path.computeBounds(rectF, true); //构造一个区域对象 Region region = new Region(); //给区赋值 region.setPath(path, new Region((int) rectF.left, (int) rectF.top, (int) rectF.right, (int) rectF.bottom)); return region.contains(x, y); } }
4,在主类中调用该自定义的类:
需要注意的一些坑:
1.2、添加
compile 'com.android.support:appcompat-v7:25.3.1' //需要是23.2 版本以上的
1.3、Activity需要继承与AppCompatActivity
1.4、布局文件当中添加
xmlns:app="http://schemas.android.com/apk/res-auto"
2、使用在Actvity前面添加一个flag设置
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
2.1 ImageView/ImageButton
XML app:srcCompat
代码里面使用无区别
2.2 Button 不支持app:srcCompat
Xml 使用在Button的selector
2.3 RadioButton 直接使用
2.4 textview的drawable 直接使用
2.5 使用的动态Vector Drawable
主要是不能直接修改 pathData
不能使用自定义interpolator