Compatible Android

This commit is contained in:
Andros Fenollosa
2016-11-03 00:05:36 +01:00
parent 7cb6af1390
commit 8ec8327e5e
1793 changed files with 440698 additions and 7 deletions

View File

@ -0,0 +1,12 @@
<?xml version="1.0"?>
<globals>
<global id="manifestOut" value="${manifestDir}" />
<global id="appCompat" type="boolean" value="${(minApiLevel lt 14)?string}" />
<!-- e.g. getSupportActionBar vs. getActionBar -->
<global id="Support" value="${(minApiLevel lt 14)?string('Support','')}" />
<global id="hasViewPager" type="boolean" value="${(features == 'pager' || features == 'tabs')?string}" />
<global id="srcOut" value="${srcDir}/${slashedPackageName(packageName)}" />
<global id="resOut" value="${resDir}" />
<global id="menuName" value="${classToResource(activityClass)}" />
<global id="relativePackage" value="<#if relativePackage?has_content>${relativePackage}<#else>${packageName}</#if>" />
</globals>

View File

@ -0,0 +1,47 @@
<?xml version="1.0"?>
<recipe>
<#if appCompat><dependency mavenUrl="com.android.support:appcompat-v7:19.+"/></#if>
<#if !appCompat && hasViewPager><dependency mavenUrl="com.android.support:support-v13:19.+"/></#if>
<merge from="AndroidManifest.xml.ftl"
to="${escapeXmlAttribute(manifestOut)}/AndroidManifest.xml" />
<instantiate from="res/menu/main.xml.ftl"
to="${escapeXmlAttribute(resOut)}/menu/${menuName}.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" />
<!-- Decide what kind of layout(s) to add -->
<#if hasViewPager>
<instantiate from="res/layout/activity_pager.xml.ftl"
to="${escapeXmlAttribute(resOut)}/layout/${layoutName}.xml" />
<#else>
<instantiate from="res/layout/activity_fragment_container.xml.ftl"
to="${escapeXmlAttribute(resOut)}/layout/${layoutName}.xml" />
</#if>
<instantiate from="res/layout/fragment_simple.xml.ftl"
to="${escapeXmlAttribute(resOut)}/layout/${fragmentLayoutName}.xml" />
<!-- Decide which activity code to add -->
<#if features == "tabs" || features == "pager">
<instantiate from="src/app_package/TabsAndPagerActivity.java.ftl"
to="${escapeXmlAttribute(srcOut)}/${activityClass}.java" />
<#elseif features == "spinner">
<instantiate from="src/app_package/DropdownActivity.java.ftl"
to="${escapeXmlAttribute(srcOut)}/${activityClass}.java" />
</#if>
<open file="${escapeXmlAttribute(srcOut)}/${activityClass}.java" />
<open file="${escapeXmlAttribute(resOut)}/layout/${fragmentLayoutName}.xml" />
</recipe>

View File

@ -0,0 +1,24 @@
<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:label="@string/title_${activityToLayout(activityClass)}"
</#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>

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/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${relativePackage}.${activityClass}"
tools:ignore="MergeRootFrame" />

View File

@ -0,0 +1,6 @@
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${relativePackage}.${activityClass}" />

View File

@ -0,0 +1,16 @@
<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"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context="${relativePackage}.${activityClass}$PlaceholderFragment">
<TextView
<#if hasViewPager>android:id="@+id/section_label"<#else>android:text="@string/hello_world"</#if>
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>

View File

@ -0,0 +1,9 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"<#if appCompat>
xmlns:app="http://schemas.android.com/apk/res-auto"</#if>
xmlns:tools="http://schemas.android.com/tools"
tools:context="${relativePackage}.${activityClass}" >
<item android:id="@+id/action_settings"
android:title="@string/action_settings"
android:orderInCategory="100"
${(appCompat)?string('app','android')}:showAsAction="never" />
</menu>

View File

@ -0,0 +1,6 @@
<resources>
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
(such as screen margins) for screens with more than 820dp of available width. This
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
<dimen name="activity_horizontal_margin">64dp</dimen>
</resources>

View File

@ -0,0 +1,5 @@
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
</resources>

View File

@ -0,0 +1,14 @@
<resources>
<#if !isNewProject>
<string name="title_${activityToLayout(activityClass)}">${escapeXmlString(activityTitle)}</string>
</#if>
<string name="title_section1">Section 1</string>
<string name="title_section2">Section 2</string>
<string name="title_section3">Section 3</string>
<string name="hello_world">Hello world!</string>
<string name="action_settings">Settings</string>
</resources>

View File

@ -0,0 +1,86 @@
package ${packageName};
import <#if appCompat>android.support.v7.app.ActionBarActivity<#else>android.app.Activity</#if>;
import android.<#if appCompat>support.v7.</#if>app.ActionBar;
import android.<#if appCompat>support.v4.</#if>app.Fragment;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
<#if applicationPackage??>import ${applicationPackage}.R;</#if>
public class ${activityClass} extends ${(appCompat)?string('ActionBar','')}Activity implements ActionBar.OnNavigationListener {
/**
* The serialization (saved instance state) Bundle key representing the
* current dropdown position.
*/
private static final String STATE_SELECTED_NAVIGATION_ITEM = "selected_navigation_item";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.${layoutName});
// Set up the action bar to show a dropdown list.
final ActionBar actionBar = get${Support}ActionBar();
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
<#if parentActivityClass != "">
// Show the Up button in the action bar.
actionBar.setDisplayHomeAsUpEnabled(true);
</#if>
// Set up the dropdown list navigation in the action bar.
actionBar.setListNavigationCallbacks(
// Specify a SpinnerAdapter to populate the dropdown list.
new ArrayAdapter<String>(
actionBar.getThemedContext(),
android.R.layout.simple_list_item_1,
android.R.id.text1,
new String[] {
getString(R.string.title_section1),
getString(R.string.title_section2),
getString(R.string.title_section3),
}),
this);
}
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
// Restore the previously serialized current dropdown position.
if (savedInstanceState.containsKey(STATE_SELECTED_NAVIGATION_ITEM)) {
get${Support}ActionBar().setSelectedNavigationItem(
savedInstanceState.getInt(STATE_SELECTED_NAVIGATION_ITEM));
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
// Serialize the current dropdown position.
outState.putInt(STATE_SELECTED_NAVIGATION_ITEM,
get${Support}ActionBar().getSelectedNavigationIndex());
}
<#include "include_options_menu.java.ftl">
@Override
public boolean onNavigationItemSelected(int position, long id) {
// When the given dropdown item is selected, show its contents in the
// container view.
get${Support}FragmentManager().beginTransaction()
.replace(R.id.container, PlaceholderFragment.newInstance(position + 1))
.commit();
return true;
}
<#include "include_fragment.java.ftl">
}

View File

@ -0,0 +1,139 @@
package ${packageName};
import java.util.Locale;
import <#if appCompat>android.support.v7.app.ActionBarActivity<#else>android.app.Activity</#if>;
import android.<#if appCompat>support.v7.</#if>app.ActionBar;
import android.<#if appCompat>support.v4.</#if>app.Fragment;
import android.<#if appCompat>support.v4.</#if>app.FragmentManager;
import android.<#if appCompat>support.v4.</#if>app.FragmentTransaction;
import android.support.${(appCompat)?string('v4','v13')}.app.FragmentPagerAdapter;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
<#if applicationPackage??>import ${applicationPackage}.R;</#if>
public class ${activityClass} extends ${(appCompat)?string('ActionBar','')}Activity<#if features == 'tabs'> implements ActionBar.TabListener</#if> {
/**
* The {@link android.support.v4.view.PagerAdapter} that will provide
* fragments for each of the sections. We use a
* {@link FragmentPagerAdapter} derivative, which will keep every
* loaded fragment in memory. If this becomes too memory intensive, it
* may be best to switch to a
* {@link android.support.${(appCompat)?string('v4','v13')}.app.FragmentStatePagerAdapter}.
*/
SectionsPagerAdapter mSectionsPagerAdapter;
/**
* The {@link ViewPager} that will host the section contents.
*/
ViewPager mViewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.${layoutName});
<#if features == 'tabs'>
// Set up the action bar.
final ActionBar actionBar = get${Support}ActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);</#if>
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(get${Support}FragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
<#if features == 'tabs'>
// When swiping between different sections, select the corresponding
// tab. We can also use ActionBar.Tab#select() to do this if we have
// a reference to the Tab.
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
@Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
// For each of the sections in the app, add a tab to the action bar.
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
// Create a tab with text corresponding to the page title defined by
// the adapter. Also specify this Activity object, which implements
// the TabListener interface, as the callback (listener) for when
// this tab is selected.
actionBar.addTab(
actionBar.newTab()
.setText(mSectionsPagerAdapter.getPageTitle(i))
.setTabListener(this));
}
</#if>
}
<#include "include_options_menu.java.ftl">
<#if features == 'tabs'>@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
mViewPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
@Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}</#if>
/**
* A {@link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
return PlaceholderFragment.newInstance(position + 1);
}
@Override
public int getCount() {
// Show 3 total pages.
return 3;
}
@Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
switch (position) {
case 0:
return getString(R.string.title_section1).toUpperCase(l);
case 1:
return getString(R.string.title_section2).toUpperCase(l);
case 2:
return getString(R.string.title_section3).toUpperCase(l);
}
return null;
}
}
<#include "include_fragment.java.ftl">
}

View File

@ -0,0 +1,36 @@
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
private static final String ARG_SECTION_NUMBER = "section_number";
/**
* Returns a new instance of this fragment for the given section
* number.
*/
public static PlaceholderFragment newInstance(int sectionNumber) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.${fragmentLayoutName}, container, false);
<#if hasSections?has_content>
TextView textView = (TextView) rootView.findViewById(R.id.section_label);
textView.setText(Integer.toString(getArguments().getInt(ARG_SECTION_NUMBER)));
</#if>
return rootView;
}
}

View File

@ -0,0 +1,19 @@
@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();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}

View File

@ -0,0 +1,95 @@
<?xml version="1.0"?>
<template
format="3"
revision="4"
name="Tabbed Activity"
minApi="7"
minBuildApi="14"
description="Creates a new blank activity, with an action bar and navigational elements such as tabs or horizontal swipe.">
<category value="Activity" />
<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="fragmentLayoutName"
name="Fragment Layout Name"
type="string"
constraints="layout|unique|nonempty"
suggest="fragment_${classToResource(activityClass)}"
default="fragment_main"
help="The name of the layout to create for the activity's content fragment" />
<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="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="features"
name="Navigation Style"
type="enum"
default="pager"
help="Additional features to include, such as a fragment, swipe views, or a navigation drawer" >
<option id="pager">Swipe Views (ViewPager)</option>
<option id="tabs">Action Bar Tabs (with ViewPager)</option>
<option id="spinner">Action Bar Spinner</option>
</parameter>
<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_pager.png</thumb>
<!-- attributes act as selectors based on chosen parameters -->
<thumb features="tabs">template_blank_activity_tabs.png</thumb>
<thumb features="pager">template_blank_activity_pager.png</thumb>
<thumb features="spinner">template_blank_activity_dropdown.png</thumb>
</thumbs>
<globals file="globals.xml.ftl" />
<execute file="recipe.xml.ftl" />
</template>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB