一款快速生成安卓shape的插件--NoCodeShape
一、NoCodeShape介绍
NoCodeShape是一个能可视化界面操作生成Android中Shape.xml的Android Studio插件。对于新手能更好的去接受Android中相对应的属性,对于资深程序员则能简化操作,快速生成shape.xml。
二、NoCodeShape使用方法
1. 下载和安装
同一般的Android Studio插件下载一样,可以直接Preferences->Plugins
搜索 NoCodeShape
搜索出来结果直接安装再重启即可。
也可以去jetbrains插件管理的官网下载各个版本的插件 https://plugins.jetbrains.com/plugin/13325-nocodeshape/versions
然后Preferences->Plugins
再Install plugins from disk从本地安装
2. 如何使用
在新建一个shape.xml文件后,右键选择NoCodeShape或者直接按快捷键Common+U
然后选择自己想要的属性,随着点击事件的进行会生成相关xml代码,并在Android Studio右边有对应的shape形状的展示。如果对应shape.xml有相关属性,NoCodeShape也会生成对应shape.xml属性的操作界面,非常方便。
示例:
三、实现原理
实现原理总体来说并不复杂,主要是界面相关操作逻辑比较繁琐。
对于新生成的一个shape.xml来说只需要弹出一个新的操作界面,用户只需要点击对应模块的属性即可。项目使用了单例模式+Bulider建造者模式
去管理各个Shape属性,分别生成 Shape、Solid、Corners、Stroke、Gradient
的单例,其内部拥有一个Builder用来去承各类型的具体属性。
通过界面的操作,对其内部的Builder
进行数据的填充,最后在完成各类操作后,将各类型中的Builder中的所有属性提取出并生成一份完整的xml字符串并将其粘贴到Android Studio的操作界面上。
实现主要分为两大类:
1. 拼接生成xml字符串
字符串拼接算是其中最复杂的部分,一是各shape的类型拥有较多数据,其中一些属性有逻辑存在性,二是生成最终Android Studio的xml字符串的时候格式存在比较多的处理。对于各类属性都继承于BaseXml
,其内部拥有一个静态内部Builder
类,以相对简单的Solid类来举例,如下所示:
public class Solid extends BaseXml { private static Builder builder; private static Solid instance = null; public static Solid getInstance() { if (instance == null) { builder = new Builder(); instance = new Solid(); } return instance; } public static class Builder extends BaseBuilder { String color; String colorValue; public void setColor(String color) { this.colorValue = color; this.color = getAttrWithOutUnitStr("color", color); } @Override public String getBuilderString() { return StringUtils.getString(color); } @Override public void clearData() { StringUtils.clearObjectData(this); } @Override public void analysisAttribute(Attributes attributes) { Solid.getInstance().setChecked(true); setColor(attributes.getValue("android:color")); } }
其类继承于抽象类BaseXml,代码如下所示:
public abstract class BaseXml { private boolean isChecked = false; public String getCloser() { return " />"; } public String getStartTag() { return ""; } public String generateXmlString() { return ""; } protected String getLineFeedString() { return "\n"; } public boolean isChecked() { return isChecked; } public BaseXml setChecked(boolean checked) { isChecked = checked; return this; } }
抽象类提取出来在字符串拼接阶段,各类型常用的基本操作,例如:返回“<solid”这类的开始标签," />"结束标签等
其内部BaseXml
拥有对应类拥有的所有属性的常用操作,其继承与抽象类BaseBuilder
,代码如下所示
public abstract class BaseBuilder { public abstract String getBuilderString(); public abstract void clearData(); public abstract void analysisAttribute(Attributes attributes); protected final String getAttrWithUnitStr(String attributeType, String value) { String unit; if (TextUtils.isEmpty(value)) { return ""; } if (value.contains("px") || value.contains("dp")) { unit = ""; } else { unit = DefaultData.UNIT; } return "android:" + attributeType + "=\"" + value + unit + "\""; } protected final String getAttrWithOutUnitStr(String attributeType, String value) { if (TextUtils.isEmpty(value)) { return ""; } return "android:" + attributeType + "=\"" + value + "\""; } protected final String getValueOutUnit(String value) { if (TextUtils.isEmpty(value)) { return value; } return value.replace("dp", "").replace("px", ""); } }
BaseBuilder内部封装了一些属性的常用操作,例如生成:android:color="#FFFFFF"
这样的字符串,获取是否带有单位的字串等。 并提供三个抽象方法:
public abstract String getBuilderString(); //获取Builder中所有属性拼接好的字符串 public abstract void clearData(); //清空Builder内部属性值 public abstract void analysisAttribute(Attributes attributes); //分析xml数据中的值,这个在第二大点“将原有shape.xml字符串转化为对应操作界面”中将会讲到
以上是基本数据的构造,在最后在控件交互的地方会调用CommonAction
类的refreshAndWriteData
:
abstract class CommonAction { JComponent component; NoShapeDialog noShapeDialog; void refreshAndWriteData() { NoCodeShapeAction.callWriteData(); } }
最后会调用基本的Action中的writeData()
方法,其具体逻辑为
/** * 数据写入xml文件 */ private static void writeData() { final Document document = FileDocumentManager.getInstance().getDocument(file); if (document == null) { try { throw new Exception("Document对象为空"); } catch (Exception e) { e.printStackTrace(); } return; } new WriteCommandAction.Simple(project) { @Override protected void run() { document.setText(XMLString.getInstance().generateXmlString()); //formatCode(); } }.execute(); }
利用XMLString.getInstance().generateXmlString()
获取各操作类型的所有属性将其拼接为一份完整的shape.xml文件的字段,最后调用插件系统的相关命令将字符串粘贴在系统对应的输入框中。
2. 将原有shape.xml字符串转化为对应操作界面
上面已经讲述类如何拼接生成xml字符串并将其粘贴到Android Studio界面上,此外NoCodeShape不仅支持新生成的shape.xml,同样也支持对旧shape.xml进行修改的能力。与第一步相比较主要多了一步读取Android Studio xml文档并将其转化为对应操作界面的过程。其主要是在操作界面初始化之前执行了如下方法:
private void initSax() { String text = FileDocumentManager.getInstance().getDocument(file).getText(); ShapeSaxHandler handler = new ShapeSaxHandler(); try { handler.createViewList(text); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
利用ShapeSaxHandler去解析xml里面的元素,参考了FindViewByMe的解析原理。
具体操作逻辑如下:
public void createViewList(String string) throws ParserConfigurationException, SAXException, IOException { InputStream xmlStream = new ByteArrayInputStream(string.getBytes("UTF-8")); SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser(); parser.parse(xmlStream, this); } @Override public void startDocument() throws SAXException { if (shapePartList == null) { shapePartList = new ArrayList<ShapePart>(); } } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { switch (qName) { case "shape": Shape.getInstance().getBuilder().analysisAttribute(attributes); break; case "stroke": Stroke.getInstance().getBuilder().analysisAttribute(attributes); break; case "solid": Solid.getInstance().getBuilder().analysisAttribute(attributes); break; case "gradient": Gradient.getInstance().getBuilder().analysisAttribute(attributes); break; case "corners": Corners.getInstance().getBuilder().analysisAttribute(attributes); break; default: break; }
逻辑其实很清楚,主要对startTag的判断,然后通过调用 public abstract void analysisAttribute(Attributes attributes);
的方法对相应的 类型的Buidler进行一个赋值操作。
以Stroke为例:
@Override public void analysisAttribute(Attributes attributes) { Stroke.getInstance().setChecked(true); setColor(attributes.getValue("android:color")); setDashGap(attributes.getValue("android:dashGap")); setWidth(attributes.getValue("android:width")); setDashWidth(attributes.getValue("android:dashWidth")); }
主要是获取到其中的属性,并对初始化的界面进行一些操作(例如选中或者赋值相关操作)。
四、总结
这个插件算是自己第一次做一个相对较实用的插件,都是利用工作的空闲事件进行编写,前前后后进行了将近一个月,其中收获颇多,但也踩过了各种各样的坑。在开发过程中由于相关文档较少,通过阅读官方文档还是有点小吃力,不过一步步还是走了下来,自己也得到了成长。其中坑也都添平了,但由于一些基础技术的欠缺,比如对Java GUI界面编程不太熟悉,导致开发过程中有很大一段时间都在跟界面作对,因此后面有机会将去深入了解Java的界面编程,争取能够将页面交互能够做到更好。
另外由于自身开发精力的原因,不能将插件做到完美,目前插件中还有如下几个问题:
1、Gradient中对应相关逻辑还需要再优化
2、还未支持Size跟Pading(从自身所处环境考虑用得较少,所以暂未支持)
3、对于颜色选择器默认打开后不支持对本地颜色字符串处理
4、存在大量的界面操作逻辑代码,需要优化
最后,希望大家能在使用过程中提出相关的意见或建议,也欢迎能一起加入到开发中,从而能将该插件做得更加完美。
项目地址:
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
更强的 JsonPath 兼容性及性能测试
更强的 JsonPath 兼容性及性能测试 最近给自己的json框架snack3添加了json path支持。搞好之后,找了两个市面上流行框架比较性测试,以助自己改进框架的性能和兼容性。 测了一圈之后,发现snack3兼容性良好,性能更是最好的。晚上要喝点小酒庆祝一下!!! 免责声明:我也是个java新手,可能测试得方式不对而造成不科学的结果,可以留言指出来。以下测试数值只对我的电脑有效(配置:Macbook pro 13 2018款 i7+16G+512G)。 Snack3 借签了 Javascript 所有变量由 var 申明,及 Xml dom 一切都是 Node 的设计。其下一切数据都以ONode表示,ONode也即 One node 之意。 强调文档树的操控和构建能力 做为中间媒体,方便不同格式互转 高性能Json path查询(兼容性和性能很赞) 支持序列化、反序列化 本案测试用的三个框架及版本: com.alibaba:fastjson:1.2.29 com.jayway.jsonpath:json-path:2.2.0 org.noear:snack3:3.1.5.3 ...
- 下一篇
ITOps为什么要转向云端?
如今,企业IT的正在发生翻天覆地的变化,无论是Splunk收购SignalFx,还是软件制造商PagerDuty的IPO事件,所有迹象都在表明——基于SaaS模式的ITOM时代正在崛起。 过去,大多数企业的IT项目都遵守了同一个流程,即先咨询,然后进行设计,最后再进行架构部署。一个项目完成的时间,少说也得一年半载。但是现在,如果你还按照这种流程和速度交付项目,你会发现等6个月项目结束时,用户需求早已过时,一切又回到了项目初始的状态。 所以说,一个完整的IT架构,或者说优秀的IT解决方案,应该像哺育一个孩子一样,要关注他的“成长”过程。每一个解决方案在设计之初都是完美的,但是要充分考虑动态调整因素。一些满足SLA服务可用性的标准,会随着企业业务的变化而变化。 当然,拥有好的系统架构,有好的运维体系,是大前提。就像我们“人”一样,要想让身体行动自如,必须由大脑发出指令,控制神经系统,然后整个身体还要有自我修复的一个机制,才能让整个系统正常运转。只不过,传统方式方法是,主要围绕好的IT基础架构和好的IT运维管理(ITOM)解决方案来设计;未来的ITOM解决方案,不只关注架构之初的设计,还要关...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- SpringBoot2全家桶,快速入门学习开发网站教程
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- CentOS关闭SELinux安全模块
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- CentOS7设置SWAP分区,小内存服务器的救世主
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- CentOS7安装Docker,走上虚拟化容器引擎之路