Android Studio中自定义模板

Paste_Image.png
Paste_Image.png

上图均为模板的使用方法。

一、目录:

1.先拿AS原本的例子来分析一个自定义模板需要什么必须的文件,分析文件的作用。
2.记录一下遇到的问题及解决方法。

二、好了现在按上述步骤开始分析。

1.进入AS自带的自定义模板目录。

自定义模板位于AS安装目录下的\plugins\android\lib\templates\activities

Paste_Image.png

进入EmptyActivity目录(因为这个自定义模板是最简单的,包含了自定义模板基本的需要)

Paste_Image.png

文件夹下包含了5个文件:
template.xml
recipe.xml.ftl
globals.xml.ftl
root:存放源代码的ftl文件,还有各种资源文件。
模板效果缩略图

2.template.xml

template.xml用于定义下图的外观和引入recipe.xml.ftlglobals.xml.ftl文件
效果图:

Paste_Image.png

template.xml.ftl的代码(内有注释):

<?xml version="1.0"?>
<template
    format="5"
    revision="5"
    name="Empty Activity"
    minApi="9"
    minBuildApi="14"
    description="Creates a new empty activity">//对应上图中的1

    <category value="Activity" />//该模板所处的分类,可以自己写一个分类
    <formfactor value="Mobile" />

//除了description外,一个parameter代表上图中的一行。(上图为2—7)
//id标识该parameter,可以用${id值}来引用该parameter的值,例如${activityClass};
//name是该parameter呈现到上图时的名称;
//type决定了该parameter的行为,如boolean为勾选框,string为文本输入框,pacakage为下拉框选择包;
//constraints为约束,例如class要按标准类名来命名(首字母大写),unique表明这个parameter的string必须唯一,noempty是非空;
//suggest是建议值,比如Activity Name中suggest为${layoutToActivity(layoutName)},则id为layoutName的parameter改变值时,会执行${layoutToActivity(layoutName)}该函数,返回的值就是Activity Name显示的值。注意是实时改变;
//default是parameter显示的默认值;
//help是选中该parameter时,上图8的位置显示的string。

    <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="backwardsCompatibility"
        name="Backwards Compatibility (AppCompat)"
        type="boolean"
        default="true"
        help="If false, this activity base class will be Activity instead of AppCompatActivity" />
    
    <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.xml.ftl和recipe.xml.ftl文件
    <globals file="globals.xml.ftl" />
    <execute file="recipe.xml.ftl" />

</template>
3.recipe.xml.ftl

recipe.xml.ftl文件如下,主要用于将root下的源代码ftl文件和资源文件整合到项目中,涉及一些freemarker语法,写上注释解释一下。

<?xml version="1.0"?>
<recipe>
    //include语法,跟C中的include是一个意思,就是引用这个文件
    <#include "../common/recipe_manifest.xml.ftl" />

//if语法,这里代表了假如id为generateLayout的值为true,则往if里面走
<#if generateLayout>
    <#include "../common/recipe_simple.xml.ftl" />
    //open语法,这里指打开${escapeXmlAttribute(resOut)}/layout/目录下的${layoutName}.xml文件,其中${escapeXmlAttribute(resOut)}/输出的目录就是项目中的res目录
    <open file="${escapeXmlAttribute(resOut)}/layout/${layoutName}.xml" />
</#if>
    //instantiae语法,这里是将root/src/app_package/目录下的SimpleActivity.java.ftl解析成项目中${escapeXmlAttribute(srcOut)}/${activityClass}.java,其中${escapeXmlAttribute(srcOut)}/输出的目录就是项目中的src目录
    <instantiate from="root/src/app_package/SimpleActivity.java.ftl"
                   to="${escapeXmlAttribute(srcOut)}/${activityClass}.java" />

    <open file="${escapeXmlAttribute(srcOut)}/${activityClass}.java" />
</recipe>
4.globals.xml.ftl

globals.xml.ftl文件如下,主要是声明一些全局变量。

<?xml version="1.0"?>
<globals>
    <global id="hasNoActionBar" type="boolean" value="false" />
    <global id="parentActivityClass" value="" />
    <global id="simpleLayoutName" value="${layoutName}" />
    <global id="excludeMenu" type="boolean" value="true" />
    <global id="generateActivityTitle" type="boolean" value="false" />
    <#include "../common/common_globals.xml.ftl" />
</globals>

三、记录一下自定义模板时遇到的问题。

1.场景是:模板需要新建一个Activity和Adapter,接着Activity和Adapter不处于同一个目录。

首先想到的解决方法是:
在template.xml中新建一个parameter,constraint写成package(亲测这个好像不起作用,只有id为packageName才能让constraint起作用),id改成adapterPackage,接着在receipe.xml.ftl中引用。

Paste_Image.png

这样问题来了,

receipe.xml.ftl中${escapeXmlAttribute(srcOut)}/已经可以将packageName解析成相应的目录,

Paste_Image.png

其中的srcOut在common文件夹中common_globals.xml.ftl已经定义好<global id="srcOut" value="${srcDir}/${slashedPackageName(packageName)}" />

Paste_Image.png
那么我们的adapterpackageName该怎么使用呢?

方法(1)在自己定义模板的目录下globals.xml.ftl定义一个srcOut2,value为srcOut的value,其中将packageName改成adapterpackageName,即

Paste_Image.png

但是测试结果是生成的目录不是项目中的目录,而是额外生成一个新目录。

方法(2)将template.xml.ftl中的${escapeXmlAttribute(srcOut)}/更改成${manifestOut}/java/${slashedPackageName(adapterpackageName)}/

Paste_Image.png

测试这种方法可以到达adapterpackageName的目录!问题解决。

2.场景是:在template.xml生成的界面中,输入ActivityName的时候,ActivityLayoutName也会自动发生相应的变化。那么我想实现输入ActivityName的时候,也会让AdapterName跟着联动,假设我输入ChatActivity时,Adapter也变成ChatAdapter。

方法:可以先增加一个parameter,用来存放两个Name中公共的部分

Paste_Image.png

接着修改activity和adapter对应的parameter中suggest。

Paste_Image.png

Paste_Image.png

这样问题解决了!。

3.场景是输入adapterName的时候,希望在layout的name中也联动,格式为(item_)+(小写的adapterName)。

方法:修改adapterlayoutName的suggest值

Paste_Image.png

ps:这个其中的${extractLetters()}方法是在fragmentlist的自定义模板中看到的,所以还是要多看AS自带的模板,多参考。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,319评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,801评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,567评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,156评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,019评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,090评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,500评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,192评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,474评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,566评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,338评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,212评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,572评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,890评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,169评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,478评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,661评论 2 335

推荐阅读更多精彩内容