Order files

This commit is contained in:
Andros Fenollosa
2016-11-12 12:27:08 +01:00
parent 73cec1f153
commit 892d89c7f1
1814 changed files with 85 additions and 80 deletions

View File

@@ -0,0 +1,14 @@
<?xml version="1.0"?>
<globals>
<global id="appCompat" type="boolean" value="${(minApiLevel lt 14)?string}" />
<global id="Support" value="${(minApiLevel lt 14)?string('Support','')}" />
<global id="projectOut" value="." />
<global id="manifestOut" value="${manifestDir}" />
<global id="srcOut" value="${srcDir}/${slashedPackageName(packageName)}" />
<global id="resOut" value="${resDir}" />
<global id="CollectionName" value="${extractLetters(objectKind)}List" />
<global id="collection_name" value="${extractLetters(objectKind?lower_case)}_list" />
<global id="DetailName" value="${extractLetters(objectKind)}Detail" />
<global id="detail_name" value="${extractLetters(objectKind?lower_case)}_detail" />
<global id="relativePackage" value="<#if relativePackage?has_content>${relativePackage}<#else>${packageName}</#if>" />
</globals>

View File

@@ -0,0 +1,37 @@
<?xml version="1.0"?>
<recipe>
<dependency mavenUrl="com.android.support:support-v4:19.+" />
<merge from="AndroidManifest.xml.ftl"
to="${escapeXmlAttribute(manifestOut)}/AndroidManifest.xml" />
<merge from="res/values-large/refs.xml.ftl"
to="${escapeXmlAttribute(resOut)}/values-large/refs.xml" />
<merge from="res/values-sw600dp/refs.xml.ftl"
to="${escapeXmlAttribute(resOut)}/values-sw600dp/refs.xml" />
<merge from="res/values/strings.xml.ftl"
to="${escapeXmlAttribute(resOut)}/values/strings.xml" />
<instantiate from="res/layout/activity_content_detail.xml.ftl"
to="${escapeXmlAttribute(resOut)}/layout/activity_${detail_name}.xml" />
<instantiate from="res/layout/activity_content_list.xml.ftl"
to="${escapeXmlAttribute(resOut)}/layout/activity_${collection_name}.xml" />
<instantiate from="res/layout/activity_content_twopane.xml.ftl"
to="${escapeXmlAttribute(resOut)}/layout/activity_${extractLetters(objectKind?lower_case)}_twopane.xml" />
<instantiate from="res/layout/fragment_content_detail.xml.ftl"
to="${escapeXmlAttribute(resOut)}/layout/fragment_${detail_name}.xml" />
<instantiate from="src/app_package/ContentDetailActivity.java.ftl"
to="${escapeXmlAttribute(srcOut)}/${DetailName}Activity.java" />
<instantiate from="src/app_package/ContentDetailFragment.java.ftl"
to="${escapeXmlAttribute(srcOut)}/${DetailName}Fragment.java" />
<instantiate from="src/app_package/ContentListActivity.java.ftl"
to="${escapeXmlAttribute(srcOut)}/${CollectionName}Activity.java" />
<instantiate from="src/app_package/ContentListFragment.java.ftl"
to="${escapeXmlAttribute(srcOut)}/${CollectionName}Fragment.java" />
<instantiate from="src/app_package/dummy/DummyContent.java.ftl"
to="${escapeXmlAttribute(srcOut)}/dummy/DummyContent.java" />
<open file="${escapeXmlAttribute(srcOut)}/${DetailName}Fragment.java" />
<open file="${escapeXmlAttribute(resOut)}/layout/fragment_${detail_name}.xml" />
</recipe>

View File

@@ -0,0 +1,31 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<activity android:name="${relativePackage}.${CollectionName}Activity"
<#if isNewProject>
android:label="@string/app_name"
<#else>
android:label="@string/title_${collection_name}"
</#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>
<activity android:name="${relativePackage}.${DetailName}Activity"
android:label="@string/title_${detail_name}"
<#if buildApi gte 16>android:parentActivityName="${relativePackage}.${CollectionName}Activity"</#if>>
<meta-data android:name="android.support.PARENT_ACTIVITY"
android:value="${relativePackage}.${CollectionName}Activity" />
</activity>
</application>
</manifest>

View File

@@ -0,0 +1,7 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/${detail_name}_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${relativePackage}.${DetailName}Activity"
tools:ignore="MergeRootFrame" />

View File

@@ -0,0 +1,10 @@
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/${collection_name}"
android:name="${packageName}.${CollectionName}Fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
tools:context="${relativePackage}.${CollectionName}Activity"
tools:layout="@android:layout/list_content" />

View File

@@ -0,0 +1,38 @@
<LinearLayout 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"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:baselineAligned="false"
android:divider="?android:attr/dividerHorizontal"
android:orientation="horizontal"
android:showDividers="middle"
tools:context="${relativePackage}.${CollectionName}Activity">
<!--
This layout is a two-pane layout for the ${objectKindPlural}
master/detail flow. See res/values-large/refs.xml and
res/values-sw600dp/refs.xml for an example of layout aliases
that replace the single-pane version of the layout with
this two-pane version.
For more on layout aliases, see:
http://developer.android.com/training/multiscreen/screensizes.html#TaskUseAliasFilters
-->
<fragment
android:id="@+id/${collection_name}"
android:name="${packageName}.${CollectionName}Fragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
tools:layout="@android:layout/list_content" />
<FrameLayout
android:id="@+id/${detail_name}_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3" />
</LinearLayout>

View File

@@ -0,0 +1,9 @@
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/${detail_name}"
style="?android:attr/textAppearanceLarge"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
android:textIsSelectable="true"
tools:context="${relativePackage}.${DetailName}Fragment" />

View File

@@ -0,0 +1,10 @@
<resources>
<!--
Layout alias to replace the single-pane version of the layout with a
two-pane version on Large screens.
For more on layout aliases, see:
http://developer.android.com/training/multiscreen/screensizes.html#TaskUseAliasFilters
-->
<item type="layout" name="activity_${collection_name}">@layout/activity_${extractLetters(objectKind?lower_case)}_twopane</item>
</resources>

View File

@@ -0,0 +1,11 @@
<resources>
<!--
Layout alias to replace the single-pane version of the layout with a
two-pane version on screens with a smallest width (smallest dimension)
of at least 600 density-independent pixels (dips).
For more on layout aliases, see:
http://developer.android.com/training/multiscreen/screensizes.html#TaskUseAliasFilters
-->
<item type="layout" name="activity_${collection_name}">@layout/activity_${extractLetters(objectKind?lower_case)}_twopane</item>
</resources>

View File

@@ -0,0 +1,6 @@
<resources>
<#if !isNewProject>
<string name="title_${collection_name}">${escapeXmlString(objectKindPlural)}</string>
</#if>
<string name="title_${detail_name}">${escapeXmlString(objectKind)} Detail</string>
</resources>

View File

@@ -0,0 +1,78 @@
package ${packageName};
import android.content.Intent;
import android.os.Bundle;
import <#if appCompat>android.support.v7.app.ActionBarActivity<#else>android.app.Activity</#if>;
<#if minApiLevel lt 16>import android.support.v4.app.NavUtils;</#if>
import android.view.MenuItem;
<#if applicationPackage??>import ${applicationPackage}.R;</#if>
/**
* An activity representing a single ${objectKind} detail screen. This
* activity is only used on handset devices. On tablet-size devices,
* item details are presented side-by-side with a list of items
* in a {@link ${CollectionName}Activity}.
* <p>
* This activity is mostly just a 'shell' activity containing nothing
* more than a {@link ${DetailName}Fragment}.
*/
public class ${DetailName}Activity extends ${appCompat?string('ActionBar','')}Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_${detail_name});
// Show the Up button in the action bar.
get${Support}ActionBar().setDisplayHomeAsUpEnabled(true);
// savedInstanceState is non-null when there is fragment state
// saved from previous configurations of this activity
// (e.g. when rotating the screen from portrait to landscape).
// In this case, the fragment will automatically be re-added
// to its container so we don't need to manually add it.
// For more information, see the Fragments API guide at:
//
// http://developer.android.com/guide/components/fragments.html
//
if (savedInstanceState == null) {
// Create the detail fragment and add it to the activity
// using a fragment transaction.
Bundle arguments = new Bundle();
arguments.putString(${DetailName}Fragment.ARG_ITEM_ID,
getIntent().getStringExtra(${DetailName}Fragment.ARG_ITEM_ID));
${DetailName}Fragment fragment = new ${DetailName}Fragment();
fragment.setArguments(arguments);
get${Support}FragmentManager().beginTransaction()
.add(R.id.${detail_name}_container, fragment)
.commit();
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
<#if minApiLevel lt 16>
// This ID represents the Home or Up button. In the case of this
// activity, the Up button is shown. Use NavUtils to allow users
// to navigate up one level in the application structure. For
// more details, see the Navigation pattern on Android Design:
//
// http://developer.android.com/design/patterns/navigation.html#up-vs-back
//
NavUtils.navigateUpTo(this, new Intent(this, ${CollectionName}Activity.class));
<#else>
// This ID represents the Home or Up button. In the case of this
// activity, the Up button is shown. For
// more details, see the Navigation pattern on Android Design:
//
// http://developer.android.com/design/patterns/navigation.html#up-vs-back
//
navigateUpTo(new Intent(this, ${CollectionName}Activity.class));
</#if>
return true;
}
return super.onOptionsItemSelected(item);
}
}

View File

@@ -0,0 +1,62 @@
package ${packageName};
import android.os.Bundle;
import android.<#if appCompat>support.v4.</#if>app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
<#if applicationPackage??>import ${applicationPackage}.R;</#if>
import ${packageName}.dummy.DummyContent;
/**
* A fragment representing a single ${objectKind} detail screen.
* This fragment is either contained in a {@link ${CollectionName}Activity}
* in two-pane mode (on tablets) or a {@link ${DetailName}Activity}
* on handsets.
*/
public class ${DetailName}Fragment extends Fragment {
/**
* The fragment argument representing the item ID that this fragment
* represents.
*/
public static final String ARG_ITEM_ID = "item_id";
/**
* The dummy content this fragment is presenting.
*/
private DummyContent.DummyItem mItem;
/**
* Mandatory empty constructor for the fragment manager to instantiate the
* fragment (e.g. upon screen orientation changes).
*/
public ${DetailName}Fragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments().containsKey(ARG_ITEM_ID)) {
// Load the dummy content specified by the fragment
// arguments. In a real-world scenario, use a Loader
// to load content from a content provider.
mItem = DummyContent.ITEM_MAP.get(getArguments().getString(ARG_ITEM_ID));
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_${detail_name}, container, false);
// Show the dummy content as text in a TextView.
if (mItem != null) {
((TextView) rootView.findViewById(R.id.${detail_name})).setText(mItem.content);
}
return rootView;
}
}

View File

@@ -0,0 +1,106 @@
package ${packageName};
import android.content.Intent;
import android.os.Bundle;
import <#if appCompat>android.support.v4.app.FragmentActivity<#else>android.app.Activity</#if>;
<#if (parentActivityClass != "" && minApiLevel lt 16)>import android.support.v4.app.NavUtils;</#if>
<#if parentActivityClass != "">import android.view.MenuItem;</#if>
<#if applicationPackage??>import ${applicationPackage}.R;</#if>
/**
* An activity representing a list of ${objectKindPlural}. This activity
* has different presentations for handset and tablet-size devices. On
* handsets, the activity presents a list of items, which when touched,
* lead to a {@link ${DetailName}Activity} representing
* item details. On tablets, the activity presents the list of items and
* item details side-by-side using two vertical panes.
* <p>
* The activity makes heavy use of fragments. The list of items is a
* {@link ${CollectionName}Fragment} and the item details
* (if present) is a {@link ${DetailName}Fragment}.
* <p>
* This activity also implements the required
* {@link ${CollectionName}Fragment.Callbacks} interface
* to listen for item selections.
*/
public class ${CollectionName}Activity extends ${(appCompat)?string('Fragment','')}Activity
implements ${CollectionName}Fragment.Callbacks {
/**
* Whether or not the activity is in two-pane mode, i.e. running on a tablet
* device.
*/
private boolean mTwoPane;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_${collection_name});
<#if parentActivityClass != "">
// Show the Up button in the action bar.
get${Support}ActionBar().setDisplayHomeAsUpEnabled(true);
</#if>
if (findViewById(R.id.${detail_name}_container) != null) {
// The detail container view will be present only in the
// large-screen layouts (res/values-large and
// res/values-sw600dp). If this view is present, then the
// activity should be in two-pane mode.
mTwoPane = true;
// In two-pane mode, list items should be given the
// 'activated' state when touched.
((${CollectionName}Fragment) get${Support}FragmentManager()
.findFragmentById(R.id.${collection_name}))
.setActivateOnItemClick(true);
}
// TODO: If exposing deep links into your app, handle intents here.
}
<#if parentActivityClass != "">
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
// This ID represents the Home or Up button. In the case of this
// activity, the Up button is shown. Use NavUtils to allow users
// to navigate up one level in the application structure. For
// more details, see the Navigation pattern on Android Design:
//
// http://developer.android.com/design/patterns/navigation.html#up-vs-back
//
${(minApiLevel lt 16)?string('NavUtils.','')}navigateUpFromSameTask(this);
return true;
}
return super.onOptionsItemSelected(item);
}
</#if>
/**
* Callback method from {@link ${CollectionName}Fragment.Callbacks}
* indicating that the item with the given ID was selected.
*/
@Override
public void onItemSelected(String id) {
if (mTwoPane) {
// In two-pane mode, show the detail view in this activity by
// adding or replacing the detail fragment using a
// fragment transaction.
Bundle arguments = new Bundle();
arguments.putString(${DetailName}Fragment.ARG_ITEM_ID, id);
${DetailName}Fragment fragment = new ${DetailName}Fragment();
fragment.setArguments(arguments);
get${Support}FragmentManager().beginTransaction()
.replace(R.id.${detail_name}_container, fragment)
.commit();
} else {
// In single-pane mode, simply start the detail activity
// for the selected item ID.
Intent detailIntent = new Intent(this, ${DetailName}Activity.class);
detailIntent.putExtra(${DetailName}Fragment.ARG_ITEM_ID, id);
startActivity(detailIntent);
}
}
}

View File

@@ -0,0 +1,152 @@
package ${packageName};
import android.app.Activity;
import android.os.Bundle;
import android.<#if Support?has_content>support.v4.</#if>app.ListFragment;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
<#if applicationPackage??>import ${applicationPackage}.R;</#if>
import ${packageName}.dummy.DummyContent;
/**
* A list fragment representing a list of ${objectKindPlural}. This fragment
* also supports tablet devices by allowing list items to be given an
* 'activated' state upon selection. This helps indicate which item is
* currently being viewed in a {@link ${DetailName}Fragment}.
* <p>
* Activities containing this fragment MUST implement the {@link Callbacks}
* interface.
*/
public class ${CollectionName}Fragment extends ListFragment {
/**
* The serialization (saved instance state) Bundle key representing the
* activated item position. Only used on tablets.
*/
private static final String STATE_ACTIVATED_POSITION = "activated_position";
/**
* The fragment's current callback object, which is notified of list item
* clicks.
*/
private Callbacks mCallbacks = sDummyCallbacks;
/**
* The current activated item position. Only used on tablets.
*/
private int mActivatedPosition = ListView.INVALID_POSITION;
/**
* A callback interface that all activities containing this fragment must
* implement. This mechanism allows activities to be notified of item
* selections.
*/
public interface Callbacks {
/**
* Callback for when an item has been selected.
*/
public void onItemSelected(String id);
}
/**
* A dummy implementation of the {@link Callbacks} interface that does
* nothing. Used only when this fragment is not attached to an activity.
*/
private static Callbacks sDummyCallbacks = new Callbacks() {
@Override
public void onItemSelected(String id) {
}
};
/**
* Mandatory empty constructor for the fragment manager to instantiate the
* fragment (e.g. upon screen orientation changes).
*/
public ${CollectionName}Fragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// TODO: replace with a real list adapter.
setListAdapter(new ArrayAdapter<DummyContent.DummyItem>(
getActivity(),
android.R.layout.simple_list_item_activated_1,
android.R.id.text1,
DummyContent.ITEMS));
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// Restore the previously serialized activated item position.
if (savedInstanceState != null
&& savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) {
setActivatedPosition(savedInstanceState.getInt(STATE_ACTIVATED_POSITION));
}
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// Activities containing this fragment must implement its callbacks.
if (!(activity instanceof Callbacks)) {
throw new IllegalStateException("Activity must implement fragment's callbacks.");
}
mCallbacks = (Callbacks) activity;
}
@Override
public void onDetach() {
super.onDetach();
// Reset the active callbacks interface to the dummy implementation.
mCallbacks = sDummyCallbacks;
}
@Override
public void onListItemClick(ListView listView, View view, int position, long id) {
super.onListItemClick(listView, view, position, id);
// Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
mCallbacks.onItemSelected(DummyContent.ITEMS.get(position).id);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mActivatedPosition != ListView.INVALID_POSITION) {
// Serialize and persist the activated item position.
outState.putInt(STATE_ACTIVATED_POSITION, mActivatedPosition);
}
}
/**
* Turns on activate-on-click mode. When this mode is on, list items will be
* given the 'activated' state when touched.
*/
public void setActivateOnItemClick(boolean activateOnItemClick) {
// When setting CHOICE_MODE_SINGLE, ListView will automatically
// give items the 'activated' state when touched.
getListView().setChoiceMode(activateOnItemClick
? ListView.CHOICE_MODE_SINGLE
: ListView.CHOICE_MODE_NONE);
}
private void setActivatedPosition(int position) {
if (position == ListView.INVALID_POSITION) {
getListView().setItemChecked(mActivatedPosition, false);
} else {
getListView().setItemChecked(position, true);
}
mActivatedPosition = position;
}
}

View File

@@ -0,0 +1,55 @@
package ${packageName}.dummy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Helper class for providing sample content for user interfaces created by
* Android template wizards.
* <p>
* TODO: Replace all uses of this class before publishing your app.
*/
public class DummyContent {
/**
* An array of sample (dummy) items.
*/
public static List<DummyItem> ITEMS = new ArrayList<DummyItem>();
/**
* A map of sample (dummy) items, by ID.
*/
public static Map<String, DummyItem> ITEM_MAP = new HashMap<String, DummyItem>();
static {
// Add 3 sample items.
addItem(new DummyItem("1", "Item 1"));
addItem(new DummyItem("2", "Item 2"));
addItem(new DummyItem("3", "Item 3"));
}
private static void addItem(DummyItem item) {
ITEMS.add(item);
ITEM_MAP.put(item.id, item);
}
/**
* A dummy item representing a piece of content.
*/
public static class DummyItem {
public String id;
public String content;
public DummyItem(String id, String content) {
this.id = id;
this.content = content;
}
@Override
public String toString() {
return content;
}
}
}

View File

@@ -0,0 +1,68 @@
<?xml version="1.0"?>
<template
format="4"
revision="5"
name="Master/Detail Flow"
minApi="4"
description="Creates a new master/detail flow, allowing users to view a collection of objects as well as details for each object. This flow is presented using two columns on tablet-size screens and one column on handsets and smaller screens. This template creates two activities, a master fragment, and a detail fragment."
category="Activity">
<dependency name="android-support-v4" revision="8" />
<category value="Activity" />
<formfactor value="Mobile" />
<thumbs>
<thumb>template_master_detail.png</thumb>
</thumbs>
<parameter
id="objectKind"
name="Object Kind"
type="string"
constraints="nonempty"
default="Item"
help="Other examples are 'Person', 'Book', etc." />
<parameter
id="objectKindPlural"
name="Object Kind Plural"
type="string"
constraints="nonempty"
default="Items"
help="Other examples are 'People', 'Books', etc." />
<parameter
id="activityTitle"
name="Title"
type="string"
constraints="nonempty"
suggest="${objectKindPlural}"
default="Items" />
<parameter
id="isLauncher"
name="Launcher Activity"
type="boolean"
default="false"
help="If true, the primary activity in the flow 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" />
<globals file="globals.xml.ftl" />
<execute file="recipe.xml.ftl" />
</template>

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB