在我们创建Android工程,新建Activity时,Android Studio都会创建一些模板文件,比如创建Activity 可以选择BlankActivity,EmptyActivity,LoginActivity等等,可以帮我们轻松的构建一个基础的Activity(包含Activity文件,Activity对应的Xml文件,在AndroidManifest文件中注册Activity等),这时我们就可以轻松的跑一个helloWorld工程了。
相信大家一直都在用,有没有机会创建一个属于自己的模板呢?答案是肯定的,android Studio 内置的模板不能满足所有人的需求,因为不满足,所以才会有很好的方案出来,开始的动机很简单,每次创建Fragment的时候调用都会报错,因为版本兼容原因,我要用的是v4包里面的Fragment,而创建的Fragment默认导入的是系统的包,每次都要手动改,真心伤不起,不知道大家有没有遇到过这样的问题,一个偶然的机会在github上看到一位大神帮我解决了这个问题,其实也不算解决问题,只是帮我打开了思路,就是在android Studio 的安装目录\Android Studio\plugins\android\lib\templates下看到了所有模板,都是以文件的形式存在的,于是我决定写一个属于我自己的模板。
下面教大家定制属于自己的模板,下面以“BlankActivity”为例讲解:
1、首先,找到安装目录\Android Studio\plugins\android\lib\templates\activities,找到BlankActivity
新建一个eclipse空的工程,将BlankActivity复制到工程中,为了高亮显示ftl文件,可以安freemaker 插件
文件名 | 介绍 |
---|---|
activity_simple.xml.ftl | activity布局文件模板 |
main.xml.ftl | 导航菜单模板 |
dimens.xml.ftl | dimens.xml模板 |
strings.xml.ftl | strings.xml模板 |
SimpleActivity.java.ftl | activity模板 |
AndroidManifest.java.ftl | AndroidManifest.java模板 |
globals.xml | 全局参数设置 |
recipe.xml.ftl | 根据模板生成对应的文件 |
template.xml | 一些配置信息和参数 |
template_blank_activity.png | 缩略图 |
下面我针对上述几个文件分别讲解
template_blank_activity.png就没有什么好说的啦,只是一张图片,有兴趣的话可以换一张自己喜欢的
template.xml 看下源码
<?xml version="1.0"?>
<template
format="3"
revision="4"
name="Blank Activity" //模板的名称,最好和文件夹相同
minApi="7"
minBuildApi="14"
description="Creates a new blank activity with an action bar.">//这里是描述,可以修改成自己的描述
<category value="Activity" /> //你会在新建文件 Activity文件夹下找到你的MyActivity
<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="layoutName"
name="Layout Name"
type="string"
constraints="layout|unique|nonempty"
suggest="${activityToLayout(activityClass)}"
default="activity_main"
help="The name of the layout to create for the activity" />
<parameter
id="activityTitle"
name="Title"
type="string"
constraints="nonempty"
default="MainActivity"
suggest="${activityClass}"
help="The name of the activity. For launcher activities, the application title." />
<parameter
id="menuName"
name="Menu Resource Name"
type="string"
constraints="layout|unique|nonempty"
suggest="menu_${classToResource(activityClass)}"
default="menu_main"
help="The name of the resource file to create for the menu items" />
<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="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" />
<!-- 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>
globals.xml 定义全局变量,如manifestOut,srcOut,ResOut,Recipe.xml用到
<?xml version="1.0"?>
<globals>
<global id="manifestOut" value="${manifestDir}" />
<#if hasDependency('com.android.support:appcompat-v7')>
<global id="appCompat" type="boolean" value="true" />
<global id="superClass" type="string" value="<#if buildApi gte 22>AppCompat<#else>ActionBar</#if>Activity"/>
<global id="superClassFqcn" type="string" value="android.support.v7.app.<#if buildApi gte 22>AppCompat<#else>ActionBar</#if>Activity"/>
<#else>
<global id="appCompat" type="boolean" value="false" />
<global id="superClass" type="string" value="Activity"/>
<global id="superClassFqcn" type="string" value="android.app.Activity"/>
</#if>
<global id="srcOut" value="${srcDir}/${slashedPackageName(packageName)}" />
<global id="resOut" value="${resDir}" />
<global id="relativePackage" value="<#if relativePackage?has_content>${relativePackage}<#else>${packageName}</#if>" />
</globals>
这里简单介绍下,Android Studio 使用的是freeMaker模板引擎,globals.xml中使用了简单freeMaker条件表达式if else语法很简单也容易理解,想要更深入的理解可以在百度搜索freemaker相关的教程。
recipe.xml 根据模板生成文件
<?xml version="1.0"?>
<recipe>
//将Activity注册到Manifest文件
<merge from="AndroidManifest.xml.ftl"
to="${escapeXmlAttribute(manifestOut)}/AndroidManifest.xml" />
//根据main.xml.ftl创建菜单布局文件
<instantiate from="res/menu/main.xml.ftl"
to="${escapeXmlAttribute(resOut)}/menu/${menuName}.xml" />
//插入activity名称到String.xml文件
<merge from="res/values/strings.xml.ftl"
to="${escapeXmlAttribute(resOut)}/values/strings.xml" />
<merge from="res/values/dimens.xml.ftl"
to="${escapeXmlAttribute(resOut)}/values/dimens.xml" />
<merge from="res/values-w820dp/dimens.xml"
to="${escapeXmlAttribute(resOut)}/values-w820dp/dimens.xml" />
//根据activity_simple.xml.ftl创建布局文件
<instantiate from="res/layout/activity_simple.xml.ftl"
to="${escapeXmlAttribute(resOut)}/layout/${layoutName}.xml" />
//根据SimpleActivity.java.ftl创建Activity
<instantiate from="src/app_package/SimpleActivity.java.ftl"
to="${escapeXmlAttribute(srcOut)}/${activityClass}.java" />
//打开activity文件
<open file="${escapeXmlAttribute(srcOut)}/${activityClass}.java" />
//打开布局文件
<open file="${escapeXmlAttribute(resOut)}/layout/${layoutName}.xml" />
</recipe>
root文件夹中包含了各种模板文件,recipe.xml.ftl文件中有用到,到这里相信大家已经知道了大概的流程,接下来我们要开始写自己的模板了
SimpleActivity.java.ftl 其中${}包裹的就是template或者globals中声明的变量或者系统变量
package ${packageName};
import ${superClassFqcn};
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
<#if applicationPackage??>
import ${applicationPackage}.R;
</#if>
public class ${activityClass} extends ${superClass} {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.${layoutName});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.${menuName}, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
其他文件就不一一展示了,都差不多
到这里相信大家已经了解了基本的流程,接下来就是定制属于自己的模板MyActivity,为了节省时间,我会在BlankActivity的基础上进行修改
提示:尽量不要在自己的电脑新建文件进行编辑,如要增加一个新的模板文件,复制原有的进行修改即可(自己建的文件在Android Studio 中编译不通过,具体原因也不是很清楚)
接下来我要对BlankActivity进行如下修改(根据我的个人习惯)
1、删掉Activity中一直没用到的函数onCreateOptionsMenu和onOptionsItemSelected。
2、删掉menu.xml,很少用
3、修改默认的布局,我不需要那些padding
4、我希望我的Activity都是竖屏的,label熟悉也不需要
修改之后的SimpleActivity.java.ftl是这样的
package ${packageName};
import ${superClassFqcn};
import android.os.Bundle;
<#if applicationPackage??>
import ${applicationPackage}.R;
</#if>
public class ${activityClass} extends ${superClass} {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.${layoutName});
}
}
直接删,去掉多余的import
直接删除main.xml.ftl 并删除 recipe.xml.ftl 关联的代码
activity_simple.xml.ftl 修改后
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${relativePackage}.${activityClass}">
<TextView
android:text="@string/hello_world"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
AndroidManifest.xml.ftl修改如下
<manifest xmlns:android="http://schemas.android.com/apk/res/android" >
<application>
<activity android:name="${relativePackage}.${activityClass}"
<#if isNewProject>
android:label="@string/app_name"
<#else>
android:screenOrientation="portrait" //竖屏代码
</#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>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</#if>
</activity>
</application>
</manifest>
编辑过程中因为没有智能的编辑器
最后一步,将MyActivity丢掉activitys目录下,重启AS就可以用了
效果图:
资源下载 MyActivity