美文网首页
Android Studio中自定义模板

Android Studio中自定义模板

作者: EdisonJQ | 来源:发表于2017-04-07 11:43 被阅读1579次
    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自带的模板,多参考。

    相关文章

      网友评论

          本文标题:Android Studio中自定义模板

          本文链接:https://www.haomeiwen.com/subject/dfqqattx.html