android studio的自定義模板詳解

DUUHos 8年前發布 | 28K 次閱讀 Android Studio開發工具 Android Studio

前言

最近看到有關技術博客,發現了關于androidstudio的模板的有關文章,表示感興趣。

包括文中的引用部分。

關于自定義模板

在新建Activity的時候都有許多的模板供我們選擇,大牛可以自定義模板,減少開發時候的重復工作。

比如這樣:

圖片來自鴻洋的csdn博客

其實模板不僅限于activity 包括圖片自由 布局文件 fragment service 以及一個類都可以制作成模板。

這里只想看下Activity模板:

模板制作學習

分為三個步驟:

  1. 分析系統模板

  2. 改寫系統模板

  3. 自己創造模板

分析和改寫系統模板

Activity的模板地址在AS的 plugins\android\lib\templates\activities 目錄下:

比如我的電腦在

C:\Program Files\Android\Android Studio\plugins\android\lib\templates\activities

Login界面用的比較多,就從他開始吧。

點開文件夾,看到以下目錄:

模板LoginActivity.png

下面來一一分析這些文件:

template.xml

這個是模板配置文件,打開可以看到:

<?xml version="1.0"?>
<template
    format="5"
    revision="6"
    name="Login Activity"
    description="Creates a new login activity, allowing users to optionally sign in with Google+ or enter an email address and password to log in to or register with your application."
    requireAppTheme="true"
    minApi="8"
    minBuildApi="14">

<dependency name="android-support-v4" revision="8" />

<category value="Activity" />
<formfactor value="Mobile" />

<parameter
    id="activityClass"
    name="Activity Name"
    type="string"
    constraints="class|unique|nonempty"
    default="LoginActivity"
    help="The name of the activity class to create" />

<parameter
    id="layoutName"
    name="Layout Name"
    type="string"
    constraints="layout|unique|nonempty"
    suggest="${activityToLayout(activityClass)}"
    default="activity_login"
    help="The name of the layout to create for the activity" />

<parameter
    id="activityTitle"
    name="Title"
    type="string"
    constraints="nonempty"
    default="Sign in"
    help="The name of the activity." />

<parameter
    id="parentActivityClass"
    name="Hierarchical Parent"
    type="string"
    constraints="activity|exists|empty"
    default=""
    help="The hierarchical parent activity, used to provide a default implementation for the 'Up' button" />

<parameter
    id="packageName"
    name="Package name"
    type="string"
    constraints="package"
    default="com.mycompany.myapp" />

<thumbs>
    <thumb>template_login_activity.png</thumb>
</thumbs>

<globals file="globals.xml.ftl" />
<execute file="recipe.xml.ftl" />

</template></code></pre>

  1. 最外面的template標簽寫的是基本的配置:包括模板名,描述,是否請求系統主題等等。我們可以將其修改為中文。
    <template
     format="5"
     revision="6"
     name="登陸界面"
     description="創建一個新的登陸界面"
     requireAppTheme="true"
     minApi="8"
     minBuildApi="14">
  2. parameter標簽
    參數,也就是要在創建的時候自己設置的東西。每一個 parameter標簽對應一個參數。這些參數會顯示在創建頁面上。也修改為中文。

    . id :唯一標識,最終通過該屬性的值,獲取用戶輸入值(文本框內容,是否選中)

    . name:界面上的類似label的提示語

    . type : 輸入值類型

    . constraints:填寫值的約束

    . suggest:建議值,比如填寫ActivityName的時候,會給出一個布局文件的建議值。

    . default:默認值

    . help:底部顯示的提升語

<parameter
        id="activityClass"
        name="活動類名"
        type="string"
        constraints="class|unique|nonempty"
        default="LoginActivity"
        help="填寫所創建的活動類的名稱" />

<parameter
    id="layoutName"
    name="布局文件名"
    type="string"
    constraints="layout|unique|nonempty"
    suggest="${activityToLayout(activityClass)}"
    default="activity_login"
    help="填寫所創建的布局文件的名稱" />

<parameter
    id="activityTitle"
    name="標題欄標題"
    type="string"
    constraints="nonempty"
    default="Sign in"
    help="The name of the activity." />

<parameter
    id="parentActivityClass"
    name="父活動類"
    type="string"
    constraints="activity|exists|empty"
    default=""
    help="配置父活動類,用于返回上一級按鈕" />

<parameter
    id="packageName"
    name="包名"
    type="string"
    constraints="package"
    default="com.mycompany.myapp" /></code></pre> 

3.thumbs

里面放置了樣例圖,可以嘗試更換。

4.最后指定了兩個引用文件

<globals file="globals.xml.ftl" />
 <execute file="recipe.xml.ftl" />

可以測試一下修改的效果:

my.gif

globals.xml.ftl和recipe.xml.ftl

在這之前先了解一下ftl結尾的文件是什么:

freemarker的文件一般以后綴ftl.

freemarker確實是不錯的模版語言引擎,尤其是處理對象圖很方便,處理xml也很方便,還支持xpath

FreeMarker 是一個模版引擎,一個基于文本的模板輸出工具(生成任意的HTML表單代碼)。它是一個Java package,面向Java程序員的class library。它本身并不是針對最終用戶的應用,而是允許程序員將其嵌入到他們的產品中。

FreeMarker被設計用來生成HTML Web頁面,特別是基于MVC(Model View Controller)模式的應用程序。使用 MVC 模式作為動態的WEB頁面的想法,是為了分隔頁面設計者 (HTML 設計者) 和程序員。.每個人做自己擅長的那一部分。設計者可以不通過程序員的改變或修改代碼來改變網頁的樣子,因為應用邏輯(Java程序)和頁面設計(FreeMarker 模版)是分開的。模板不會被復雜繁瑣的程序框架所破壞。即使當一個項目的程序員和HIMTL頁面的制作者是同一個人時,這種分隔也是很有用,因為這樣有助于保持應用的清晰并易于維護。

不知道大家寫過網頁沒有,不管是jsp還是asp還是asp.net

都會有這種在標簽語言里面插入編程語言的方式,大概類似。

關于ftl的語法:

組成部分

一、整體結構

1、注釋:<#--注釋內容-->,不會輸出。

2、文本:直接輸出。

3、interpolation:由 ${var} 或 #{var} 限定,由計算值代替輸出。

4、FTL標記

二、指令:

freemarker指令有兩種:

1、預定義指令:引用方式為<#指令名稱>

2、用戶定義指令:引用方式為<@指令名稱>,引用用戶定義指令時須將#換為@。

注意:如果使用不存在的指令,FreeMarker不會使用模板輸出,而是產生一個錯誤消息。

freemarker指令由FTL標記來引用,FTL標記和HTML標記類似,名字前加#來加 以區分。如HTML標記的形式為

則FTL標記的形式是<#list>< /#list>(此處h1標記和list指令沒有任何功能上的對應關系,只是做為說明使用一下)。

有三種FTL標記:

1)、開始標記:<#指令名稱>

2)、結束標記:</#指令名稱>

3)、空標記:<#指令名稱/>

注意:

1) FTL會忽略標記之中的空格,但是,<#和指令 與 </#和指令 之間不能有空格。

2) FTL標記不能夠交叉,必須合理嵌套。每個開始標記對應一個結束標記,層層嵌套。 如:

<#list>

  • ${數據}

    <#if 變量>

    game over!

    </#if>

</#list>

注意事項:

1)、FTL對大小寫敏感。 所以使用的標記及interpolation要注意大小寫。name與NAME就是不同的對象。<#list>是正確的標記,而<#List>則不是。

2)、interpolation只能在文本部分使用,不能位于FTL標記內。如<#if ${var}>是錯誤的,正確的方法是:<#if var>,而且此處var必須為布爾值。

3)、FTL標記不能位于另一個FTL標記內部,注釋例外。注釋可以位于標記及interpolation內部。

其實只要知道if即可以了,這里只用if來判斷。

globals.xml.ftl

定義了全局變量,并引用了一個內置的通用globals.xml.ftl

<?xml version="1.0"?>
<globals>
    <global id="hasNoActionBar" type="boolean" value="false" />
    <global id="isLauncher" type="boolean" value="${isNewProject?string}" />
    <global id="includePermissionCheck" type="boolean" value="${(targetApi gte 23)?string}" />
    <global id="GenericStringArgument" type="string" value="<#if buildApi lt 19>String</#if>" />
    <#include "../common/common_globals.xml.ftl" />
</globals>

recipe.xml.ftl

指定資源文件的路徑并相應的生成到我們的項目目錄去:

<recipe>
   <#if appCompat && !(hasDependency('com.android.support:appcompat-v7'))>
       <dependency mavenUrl="com.android.support:appcompat-v7:${buildApi}.+" />
    </#if>

    <#if (buildApi gte 22) && appCompat && !(hasDependency('com.android.support:design'))>
        <dependency mavenUrl="com.android.support:design:${buildApi}.+" />
    </#if>

    <merge from="root/AndroidManifest.xml.ftl"
             to="${escapeXmlAttribute(manifestOut)}/AndroidManifest.xml" />

    <merge from="root/res/values/dimens.xml"
             to="${escapeXmlAttribute(resOut)}/values/dimens.xml" />

    <merge from="root/res/values/strings.xml.ftl"
             to="${escapeXmlAttribute(resOut)}/values/strings.xml" />

    <instantiate from="root/res/layout/activity_login.xml.ftl"
                   to="${escapeXmlAttribute(resOut)}/layout/${layoutName}.xml" />

    <instantiate from="root/src/app_package/LoginActivity.java.ftl"
                   to="${escapeXmlAttribute(srcOut)}/${activityClass}.java" />

    <open file="${escapeXmlAttribute(srcOut)}/${activityClass}.java" />

</recipe>

. copy :從root中copy文件到我們的目標目錄,比如我們的模板Activity需要使用一些圖標,那么可能就需要使用copy標簽將這些圖標拷貝到我們的項目對應文件夾。

. merge : 合并的意思,比如將我們使用到的strings.xml合并到我們的項目的stirngs.xml中

. instantiate : 和copy類似,但是可以看到上例試將ftl->java文件的,也就是說中間會通過一個步驟,將ftl中的變量都換成對應的值,那么完整的流程是ftl->freemarker process -> java。

. open:在代碼生成后,打開指定的文件,比如我們新建一個Activity后,默認就會將該Activity打開。

那么整體的關系類似下圖:

這里只是指定了生成的路徑的文件名,但是如何生成呢,這就要根據前面創建的選項來設置生成的目標文件。

root文件夾

里面都是加了ftl的java文件和XML文件,所以我們用if來判斷生成的方式。

兩個步驟:

取值--->判斷-->生成

xml文件中:

配置文件:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" >

    <!-- To auto-complete the email text field in the login form with the user's emails -->
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.READ_PROFILE" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />

    <application>
        <activity android:name=".${activityClass}"
            <#if isNewProject>
            android:label="@string/app_name"
            <#else>
            android:label="@string/title_${simpleName}"
            </#if>
            <#if hasNoActionBar>
            android:theme="@style/${themeNameNoActionBar}"
            </#if>
            <#if buildApi gte 16 && parentActivityClass != "">android:parentActivityName="${parentActivityClass}"</#if>>
            <#if parentActivityClass != "">
            <meta-data android:name="android.support.PARENT_ACTIVITY"
                android:value="${parentActivityClass}" />
            </#if>
            <#if isLauncher && !(isLibraryProject!false)>
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            </#if>
        </activity>
    </application>
</manifest>

獲取值,包括設定值和全局變量:

  1. 設定值:activityClass獲取,${activityClass}
    全局變量:isNewProject,hasNoActionBar

if判斷

<#if isNewProject>
android:label="@string/app_name"
<#else>
android:label="@string/title_${simpleName}"
</#if>

java文件中

代碼太長不貼
也是類似的方式:
比如包名引入 package ${packageName};
判斷:

<#if parentActivityClass != "">
setupActionBar();
</#if>

最后系統根據這些東西來生成最終的文件:

流程大致可用下圖說明:

自己創造模板

分析改寫已經完成了,下面開始創造

寫個自己的登錄界面

不用完全從頭開始。我們就拿LoginActivity模板來寫。

 

來自:http://www.jianshu.com/p/c76facb61d69

 

 本文由用戶 DUUHos 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!