android 读取 caf格式,Android 矢量图:加载本地SVG文件并生成Path路径

SVG文件本就是XML格式,因此可以直接进行XML解析,大家的方案都是使用工具(Android Studio 或者在线解析)将SVG转换为Android可识别的Drawable资源文件,但这样就没法去根据需要实时修改了,因此只能从SVG中的path标签入手。

一般SVG文件使用记事本打开后是这些内容:

其中path标签的内容就是我们需要的数据,我们使用 DocumentBuilder 和 XPath 来解析此XML,从而得到path对象。

File file = new File("/storage/emulated/0/Tencent/QQfile_recv/more.svg");

try {

DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();

Document document = builder.parse(file);

String xpathExpression = "//@*"; // 选择所有节点

XPathFactory xpf = XPathFactory.newInstance();

XPath xpath = xpf.newXPath();

XPathExpression expression = xpath.compile(xpathExpression);

// 得到整个xml的每个节点

NodeList svgPaths = (NodeList) expression.evaluate(document, XPathConstants.NODESET);

ArrayList pathList = new ArrayList<>();

for (int i = 0; i < svgPaths.getLength(); i++) {

// 对应path标签中的d节点

if (svgPaths.item(i).getNodeName().equals("d")) {

Data data = new Data();

data.mPath = PathParser.createPathFromPathData(svgPaths.item(i).getTextContent());

// 此d节点前面应该是fill节点,fill节点是此路径绘制的颜色

if (i > 0 && svgPaths.item(i - 1).getNodeName().equals("fill")) {

data.mFillColor = svgPaths.item(i - 1).getTextContent();

} else if (i > 0){

// d节点的前一个不是fill节点,可能是其他节点,此时往上查找,直到找到fill节点或者再次

// 遇到d节点(证明没有fill节点,默认为黑色)为止

for (int j = i -1; j >= 0 ; j--) {

if (svgPaths.item(j).getNodeName().equals("fill")) {

data.mFillColor = svgPaths.item(j).getTextContent();

break;

} else if (svgPaths.item(j).getNodeName().equals("d")) {

// 如果找到了上一个path中的d标签都没有找到fill标签,则代表此path没有fill,为黑色

data.mFillColor = "#000000";

break;

}

}

}

pathList.add(data);

}

}

} catch (ParserConfigurationException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

} catch (XPathExpressionException e) {

e.printStackTrace();

} catch (SAXException e) {

e.printStackTrace();

}

}

class Data {

String mFillColor;

Path mPath;

}

当然你也可以自己解析d标签的内容,m代表移动,对应path中的moveTo,l代表画线等具体可以查询path的相关方法,但Android自己便可以从Drawable下的XML解析成VectorDrawable,那官方应该有相关的解析方法,全局搜索有关path的信息,果然找到了一个PathParser类。

关于PathParser,这个类原本是在android.support.graphics.drawable下的类,无法访问到,因此直接拷贝出来,使用createPathFromPathData方法便能将d标签下的数据转换为path对象。

通过以上步骤,得到了一个SVG文件的所有path对象,然后根据pathList便可以将矢量图绘制出来。

这里使用一个自定义的IamgeView展示矢量图,在onDraw方法中将path绘制出来即可。

@Override

public void onDraw(Canvas canvas) {

canvas.save();

for (int i = 0; i < pathList.size(); i++) {

Paint paint = new Paint();

paint.setColor(Color.parseColor(pathList.get(i).mFillColor));

canvas.drawPath(pathList.get(i).mPath, paint);

}

canvas.restore();

}

如此便将矢量图绘制到了自定义的IamgeView上,当然也可以直接新建Canvas便可将矢量图按需求进行绘制。

也可以通过此方式将两个或者几个矢量图叠加在一起,每一张SVG最终都生成一个pathList,矢量图的叠加其实也就是path的叠加。

这里对这些path进行一些简单的操作,比如放大,和平移,当然旋转也可以,只要是Matrix拥有的效果均能实现

查看Path这个类,发现有个一addPath(Path src, Matrix matrix)方法,这就完美了,直接可以传入Matrix,再也不用手动计算值了

这里,我重写了ImageView的onTouchEvent方法,当点击时,将SVG图片放大1.1倍,代码如下所示:

@Override

public boolean onTouchEvent(MotionEvent ev) {

final int action = ev.getAction();

switch (action & MotionEvent.ACTION_MASK) {

case MotionEvent.ACTION_DOWN: {

Matrix matrix = new Matrix();

matrix.postScale(1.1f,1.1f);

// matrix.postTranslate(5f,5f);

for (int i = 0; i < pathList.size(); i++) {

Path path = new Path();

path.addPath(pathList.get(i).mPath, matrix);

pathList.get(i).mPath = path;

}

break;

}

}

return true;

}

演示效果如下图:

1fdbcbf3b821

加载本地SVG图片并放大.gif

欢迎大家交流指正😁

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值