本篇文章为大家展示了怎么在Android中通过自定义控件实现不规则区域点击事件,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。
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;
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:// 文档开始事件,可以进行数据初始化处理
break;
case XmlPullParser.START_TAG:// 开始元素事件
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:// 结束元素事件
name = parser.getName();
if ("path".equals(name)) {//这个地方主要处理屏幕适配问题,后面后详细讲解
mCityPath.initPath();
//处理path的边界
//计算控制点的边界
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文件之后就是绘制图像代码如下:
@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);//这个地方要用concat方法不能用这个方法
// 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代表的是选中区域的path,如果不为空则一点击选中区域了
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();
}
实现上面的方法就可以会出一个地图了,但是没有点击事件,接下来实现点击事件代码如下:
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {//点击的时候出发
float x = event.getX();
float y = event.getY();
if (list != null)
for (int i = 0; i < list.size(); i++) {//多所有的path进行遍历
CityPath cityPath = list.get(i);
if (cityPath.isArea(x / scale, y / scale)) {//这个地方要注意了,在查找点是否在path区域中药除以上面的缩放比例
mPath = cityPath.getmPath();
postInvalidate();
Toast.makeText(getContext(), cityPath.getTitle(), Toast.LENGTH_SHORT).show();
break;
}
}
}
return super.onTouchEvent(event);
}
出发事件实现中主要的核心是判断点是否在path区域内实现代码如下:
public boolean isArea(float x,float y){
RectF r=new RectF();
//计算控制点的边界
mPath.computeBounds(r, true);
//设置区域路径和剪辑描述的区域
re.setPath(mPath, new Region((int)r.left,(int)r.top,(int)r.right,(int)r.bottom));
return re.contains((int)x, (int)y);
}
上面的代码就可以实现不规则区域的点击了,接下来主要文件就是如何保证通过解析的svg文件可以再不同手机上的显示适配,我这里实现的方法是将每个path的最小外嵌矩形的大小都统计出来,然后进行整合获取所有path所在区域的最小值,然后和控件的大小进行比较算出缩放比代码如下:
//处理path的边界
//计算控制点的边界
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);
}
Android是一种基于Linux内核的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由美国Google公司和开放手机联盟领导及开发。
上述内容就是怎么在Android中通过自定义控件实现不规则区域点击事件,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注亿速云行业资讯频道。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。