本文實(shí)例為大家分享了Android實(shí)現(xiàn)不規(guī)則區(qū)域點(diǎn)擊事件的具體代碼,供大家參考,具體內(nèi)容如下
先看看效果
對(duì)于上面的圖形實(shí)現(xiàn)主要用到svg,通過(guò)解析svg獲取不規(guī)則的圖形,對(duì)于svg文件這個(gè)一般需要美工提供,不需要我們開(kāi)發(fā)實(shí)現(xiàn)。
實(shí)現(xiàn)上面效果第一步是解析svg文件代碼如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
package demo.zjd.com.taiwandemo.utils; import android.graphics.RectF; import android.util.Xml; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import demo.zjd.com.taiwandemo.bean.CityPath; import demo.zjd.com.taiwandemo.bean.ViewAttr; import demo.zjd.com.taiwandemo.calback.ParserCallBack; /** * Created by zhangjd on 2017/6/1. * 解析svg xml */ public class SVGXmlParserUtils { public static void parserXml( final InputStream in, final ParserCallBack mParserCallBack){ new Thread( new Runnable() { @Override public void run() { List<CityPath> list= new ArrayList<>(); ViewAttr mViewAttr= new ViewAttr(); parserXml(in,list,mViewAttr); if (mParserCallBack!= null ){ mParserCallBack.callback(list,mViewAttr); } } }).start(); } private static void parserXml(InputStream in, List<CityPath> list, ViewAttr mViewAttr){ XmlPullParser parser = Xml.newPullParser(); RectF mRectF= new RectF(); try { parser.setInput(in, "UTF-8" ); int eventType = parser.getEventType(); String name = null ; CityPath mCityPath = null ; list.clear(); while (eventType != XmlPullParser.END_DOCUMENT) { switch (eventType) { case XmlPullParser.START_DOCUMENT: // 文檔開(kāi)始事件,可以進(jìn)行數(shù)據(jù)初始化處理 break ; case XmlPullParser.START_TAG: // 開(kāi)始元素事件 name = parser.getName(); if ( "path" .equals(name)) { mCityPath = new CityPath(); mCityPath.setId(parser.getAttributeValue( null , "id" )); mCityPath.setTitle(parser.getAttributeValue( null , "title" )); mCityPath.setPathData(parser.getAttributeValue( null , "d" )); } break ; case XmlPullParser.END_TAG: // 結(jié)束元素事件 name = parser.getName(); if ( "path" .equals(name)) { //這個(gè)地方主要處理屏幕適配問(wèn)題,后面后詳細(xì)講解 mCityPath.initPath(); //處理path的邊界 //計(jì)算控制點(diǎn)的邊界 mCityPath.getmPath().computeBounds(mRectF, true ); mViewAttr.colSize(mRectF); list.add(mCityPath); } break ; } eventType = parser.next(); } } catch (XmlPullParserException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (in!= null ){ try { in.close(); } catch (IOException e) { e.printStackTrace(); } } } } } |
解析完svg文件之后就是繪制圖像代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
@Override protected void onDraw(Canvas canvas) { super .onDraw(canvas); if (list == null ) { return ; } // Matrix mMatrix = new Matrix(); // mMatrix.postScale(0.5f,0.5f); // mMatrix.setScale(0.5f,0.5f);//這個(gè)地方要用concat方法不能用這個(gè)方法 // canvas.concat(mMatrix); //上面的方法也可以 // canvas.restore(); canvas.scale(scale, scale); canvas.drawColor(Color.YELLOW); for ( int i = 0 ; i < list.size(); i++) { CityPath path = list.get(i); //繪制邊的顏色 mPaint.setStrokeWidth( 2 ); mPaint.setStyle(Paint.Style.STROKE); mPaint.setColor(Color.GRAY); canvas.drawPath(path.getmPath(), mPaint); } if (mPath != null ) { //mPath代表的是選中區(qū)域的path,如果不為空則一點(diǎn)擊選中區(qū)域了 mPaint.setStrokeWidth( 1 ); mPaint.setStyle(Paint.Style.FILL); mPaint.setColor(Color.GREEN); mPaint.setShadowLayer( 8 , 2 , 2 ,Color.BLACK); canvas.drawPath(mPath, mPaint); } mPaint.clearShadowLayer(); } |
實(shí)現(xiàn)上面的方法就可以會(huì)出一個(gè)地圖了,但是沒(méi)有點(diǎn)擊事件,接下來(lái)實(shí)現(xiàn)點(diǎn)擊事件代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
@Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { //點(diǎn)擊的時(shí)候出發(fā) float x = event.getX(); float y = event.getY(); if (list != null ) for ( int i = 0 ; i < list.size(); i++) { //多所有的path進(jìn)行遍歷 CityPath cityPath = list.get(i); if (cityPath.isArea(x / scale, y / scale)) { //這個(gè)地方要注意了,在查找點(diǎn)是否在path區(qū)域中藥除以上面的縮放比例 mPath = cityPath.getmPath(); postInvalidate(); Toast.makeText(getContext(), cityPath.getTitle(), Toast.LENGTH_SHORT).show(); break ; } } } return super .onTouchEvent(event); } |
出發(fā)事件實(shí)現(xiàn)中主要的核心是判斷點(diǎn)是否在path區(qū)域內(nèi)實(shí)現(xiàn)代碼如下:
1
2
3
4
5
6
7
8
|
public boolean isArea( float x, float y){ RectF r= new RectF(); //計(jì)算控制點(diǎn)的邊界 mPath.computeBounds(r, true ); //設(shè)置區(qū)域路徑和剪輯描述的區(qū)域 re.setPath(mPath, new Region(( int )r.left,( int )r.top,( int )r.right,( int )r.bottom)); return re.contains(( int )x, ( int )y); } |
上面的代碼就可以實(shí)現(xiàn)不規(guī)則區(qū)域的點(diǎn)擊了,接下來(lái)主要文件就是如何保證通過(guò)解析的svg文件可以再不同手機(jī)上的顯示適配,我這里實(shí)現(xiàn)的方法是將每個(gè)path的最小外嵌矩形的大小都統(tǒng)計(jì)出來(lái),然后進(jìn)行整合獲取所有path所在區(qū)域的最小值,然后和控件的大小進(jìn)行比較算出縮放比代碼如下:
1
2
3
4
5
6
7
8
9
10
|
//處理path的邊界 //計(jì)算控制點(diǎn)的邊界 mCityPath.getmPath().computeBounds(mRectF, true ); mViewAttr.colSize(mRectF); public void colSize(RectF mRectF) { left = left == null ? mRectF.left : Math.min(mRectF.left, left); top = top == null ? mRectF.top : Math.min(mRectF.top, top); right = right == null ? mRectF.right : Math.max(mRectF.right, right); bottom = bottom == null ? mRectF.bottom : Math.max(mRectF.bottom, bottom); } |
適配完成之后就大功告成,下面是代碼的地址,如有改進(jìn)的地方歡迎提出
下載:代碼地址
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。
原文鏈接:https://blog.csdn.net/zjd934784273/article/details/72841295