目录地址
首先了解模板的文件结构,先看一个自带的模板“Empty Activity”,目录地址是plugins/android/lib/templates/
,里面就有我们需要的模板。
目录结构
在目录下我们可以依次看到如下文件:
- globals.xml.ftl
- recipe.xml.ftl
- template.xml
- template_blank_activity.png
- root/src/app_package/SimpleActivity.java.ftl
template.xml
这个模板主要是整个模板的定义,从模板名称到模板分类再到模板参数都在这里定义。
<?xml version="1.0"?>
<template
format="5"
revision="5"
name="Empty Activity"
minApi="7"
minBuildApi="14"
description="Creates a new empty activity">
<category value="Activity" />
<formfactor value="Mobile" />
<parameter
id="activityClass"
name="Activity Name"
type="string"
constraints="class|unique|nonempty"
suggest="${layoutToActivity(layoutName)}"
default="MainActivity"
help="The name of the activity class to create" />
<parameter
id="generateLayout"
name="Generate Layout File"
type="boolean"
default="true"
help="If true, a layout file will be generated" />
<parameter
id="layoutName"
name="Layout Name"
type="string"
constraints="layout|unique|nonempty"
suggest="${activityToLayout(activityClass)}"
default="activity_main"
visibility="generateLayout"
help="The name of the layout to create for the activity" />
<parameter
id="isLauncher"
name="Launcher Activity"
type="boolean"
default="false"
help="If true, this activity will have a CATEGORY_LAUNCHER intent filter, making it visible in the launcher" />
<parameter
id="packageName"
name="Package name"
type="string"
constraints="package"
default="com.mycompany.myapp" />
<!-- 128x128 thumbnails relative to template.xml -->
<thumbs>
<!-- default thumbnail is required -->
<thumb>template_blank_activity.png</thumb>
</thumbs>
<globals file="globals.xml.ftl" />
<execute file="recipe.xml.ftl" />
</template>
- template 标签,整个 xml 的根节点,其中 name属性为模板名称,description属性为模板的描述。
- category标签,定义了模板所属的分类,即图四中的分类列表中的分类,分类名一样的模板会被归纳到同一目录下。
- parameter 标签,定义了模板输入弹窗中的输入参数,每个 parameter 为一行。其中:
- id 属性为参数唯一标识,我们可以在代码中通过 id来使用该参数。
- name 属性为参数名称,显示在输入控件的前面或后面。
- type属性为参数类型,根据该属性和constraints属性的值综合比较后参数会被渲染成不同的输入形式,比如 string 类型会显示输入框,而 boolean类型会显示一个选择框。
- constraints属性为输入约束,常见的有class,代表类名;layout代表布局名;package 代表包路径; unique则是不能与现有的重复;nonemptye表示不能为空。
- suggest 和 default标签,前者是建议名称,后者是默认名称,前者优先级高于后者。
- help属性是参数输入提示,当该参数获取焦点后,对应的帮助信息会显示在对话框上。
- thumbs标签定义了该目标的缩略图,这也就是template_blank_activity.png文件的作用了。
- globals标签指定了 global 文件,具体用途下文会具体说明。
- execute标签,跟字面上的意思一样,执行 recipe.xml.ftl文件的内容,将模板文件生成具体的可用文件。
globals.xml.ftl
<?xml version="1.0"?>
<globals>
<global id="hasNoActionBar" type="boolean" value="false" />
<#include "../common/common_globals.xml.ftl" />
</globals>
可以根据id的值访问到该值,定义的一些全局的变量
recipe.xml.ftl
<recipe>
<#include "../common/recipe_manifest.xml.ftl" />
<#if generateLayout>
<#include "../common/recipe_simple.xml.ftl" />
<open file="${escapeXmlAttribute(resOut)}/layout/${layoutName}.xml" />
</#if>
<instantiate from="root/src/app_package/SimpleActivity.java.ftl"
to="${escapeXmlAttribute(srcOut)}/${activityClass}.java" />
<open file="${escapeXmlAttribute(srcOut)}/${activityClass}.java" />
</recipe>
定义了模板转换命令,将SimpleActivity.java.ftl
转化为 SimpleActivity.java
。
- merge : 合并的意思,比如将我们使用到的strings.xml合并到我们的项目的stirngs.xml中
- instantiate : 和copy类似,但是可以看到上例试将ftl->java文件的,也就是说中间会通过一个步骤,将ftl中的变量都换成对应的值,那么完整的流程是ftl->freemarker process -> java。
- open:在代码生成后,打开指定的文件,比如我们新建一个Activity后,默认就会将该Activity打开。
SimpleActivity.java.ftl
package ${packageName};
import ${superClassFqcn};
import android.os.Bundle;
public class ${activityClass} extends ${superClass} {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
<#if generateLayout>
setContentView(R.layout.${layoutName});
</#if>
}
}
上面就是模板设计用到的类,总结一下:
- template 中parameter标签,主要用于提供参数
- global.xml.ftl 主要用于提供参数
- recipe.xml.ftl 主要用于生成我们实际需要的代码,资源文件等;例如,利用参数+MainActivity.java.ftl -> MainActivity.java;其实就是利用参数将ftl中的变量进行替换。
示例
- 在.ftl文件里把.java文件中,可变的部分都换成了${变量名}的方式
- 之后在recipe.xml.ftl定义依赖
- 比较繁琐的话 尽量直接从原有的上面改
参考代码:源码
参考:
大幅提高 Android 开发效率之 Android 项目模板化 (上)
Android Studio自定义模板 写页面竟然可以如此轻松