Merge "Improvements for CardEmulation/CardReader sample" into klp-dev
diff --git a/common/src/java/com/example/android/common/view/SlidingTabLayout.java b/common/src/java/com/example/android/common/view/SlidingTabLayout.java
new file mode 100644
index 0000000..20049e3
--- /dev/null
+++ b/common/src/java/com/example/android/common/view/SlidingTabLayout.java
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.common.view;
+
+import android.content.Context;
+import android.graphics.Typeface;
+import android.os.Build;
+import android.support.v4.view.PagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.HorizontalScrollView;
+import android.widget.TextView;
+
+/**
+ * To be used with ViewPager to provide a tab indicator component which give constant feedback as to
+ * the user's scroll progress.
+ * <p>
+ * To use the component, simply add it to your view hierarchy. Then in your
+ * {@link android.app.Activity} or {@link android.support.v4.app.Fragment} call
+ * {@link #setViewPager(ViewPager)} providing it the ViewPager this layout is being used for.
+ * <p>
+ * The colors can be customized in two ways. The first and simplest is to provide an array of colors
+ * via {@link #setSelectedIndicatorColors(int...)} and {@link #setDividerColors(int...)}. The
+ * alternative is via the {@link TabColorizer} interface which provides you complete control over
+ * which color is used for any individual position.
+ * <p>
+ * The views used as tabs can be customized by calling {@link #setCustomTabView(int, int)},
+ * providing the layout ID of your custom layout.
+ */
+public class SlidingTabLayout extends HorizontalScrollView {
+
+ /**
+ * Allows complete control over the colors drawn in the tab layout. Set with
+ * {@link #setCustomTabColorizer(TabColorizer)}.
+ */
+ public interface TabColorizer {
+
+ /**
+ * @return return the color of the indicator used when {@code position} is selected.
+ */
+ int getIndicatorColor(int position);
+
+ /**
+ * @return return the color of the divider drawn to the right of {@code position}.
+ */
+ int getDividerColor(int position);
+
+ }
+
+ private static final int TITLE_OFFSET_DIPS = 24;
+ private static final int TAB_VIEW_PADDING_DIPS = 16;
+ private static final int TAB_VIEW_TEXT_SIZE_SP = 12;
+
+ private int mTitleOffset;
+
+ private int mTabViewLayoutId;
+ private int mTabViewTextViewId;
+
+ private ViewPager mViewPager;
+ private ViewPager.OnPageChangeListener mViewPagerPageChangeListener;
+
+ private final SlidingTabStrip mTabStrip;
+
+ public SlidingTabLayout(Context context) {
+ this(context, null);
+ }
+
+ public SlidingTabLayout(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public SlidingTabLayout(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ // Disable the Scroll Bar
+ setHorizontalScrollBarEnabled(false);
+ // Make sure that the Tab Strips fills this View
+ setFillViewport(true);
+
+ mTitleOffset = (int) (TITLE_OFFSET_DIPS * getResources().getDisplayMetrics().density);
+
+ mTabStrip = new SlidingTabStrip(context);
+ addView(mTabStrip, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+ }
+
+ /**
+ * Set the custom {@link TabColorizer} to be used.
+ *
+ * If you only require simple custmisation then you can use
+ * {@link #setSelectedIndicatorColors(int...)} and {@link #setDividerColors(int...)} to achieve
+ * similar effects.
+ */
+ public void setCustomTabColorizer(TabColorizer tabColorizer) {
+ mTabStrip.setCustomTabColorizer(tabColorizer);
+ }
+
+ /**
+ * Sets the colors to be used for indicating the selected tab. These colors are treated as a
+ * circular array. Providing one color will mean that all tabs are indicated with the same color.
+ */
+ public void setSelectedIndicatorColors(int... colors) {
+ mTabStrip.setSelectedIndicatorColors(colors);
+ }
+
+ /**
+ * Sets the colors to be used for tab dividers. These colors are treated as a circular array.
+ * Providing one color will mean that all tabs are indicated with the same color.
+ */
+ public void setDividerColors(int... colors) {
+ mTabStrip.setDividerColors(colors);
+ }
+
+ /**
+ * Set the {@link ViewPager.OnPageChangeListener}. When using {@link SlidingTabLayout} you are
+ * required to set any {@link ViewPager.OnPageChangeListener} through this method. This is so
+ * that the layout can update it's scroll position correctly.
+ *
+ * @see ViewPager#setOnPageChangeListener(ViewPager.OnPageChangeListener)
+ */
+ public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) {
+ mViewPagerPageChangeListener = listener;
+ }
+
+ /**
+ * Set the custom layout to be inflated for the tab views.
+ *
+ * @param layoutResId Layout id to be inflated
+ * @param textViewId id of the {@link TextView} in the inflated view
+ */
+ public void setCustomTabView(int layoutResId, int textViewId) {
+ mTabViewLayoutId = layoutResId;
+ mTabViewTextViewId = textViewId;
+ }
+
+ /**
+ * Sets the associated view pager. Note that the assumption here is that the pager content
+ * (number of tabs and tab titles) does not change after this call has been made.
+ */
+ public void setViewPager(ViewPager viewPager) {
+ mTabStrip.removeAllViews();
+
+ mViewPager = viewPager;
+ if (viewPager != null) {
+ viewPager.setOnPageChangeListener(new InternalViewPagerListener());
+ populateTabStrip();
+ }
+ }
+
+ /**
+ * Create a default view to be used for tabs. This is called if a custom tab view is not set via
+ * {@link #setCustomTabView(int, int)}.
+ */
+ protected TextView createDefaultTabView(Context context) {
+ TextView textView = new TextView(context);
+ textView.setGravity(Gravity.CENTER);
+ textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, TAB_VIEW_TEXT_SIZE_SP);
+ textView.setTypeface(Typeface.DEFAULT_BOLD);
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ // If we're running on Honeycomb or newer, then we can use the Theme's
+ // selectableItemBackground to ensure that the View has a pressed state
+ TypedValue outValue = new TypedValue();
+ getContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground,
+ outValue, true);
+ textView.setBackgroundResource(outValue.resourceId);
+ }
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
+ // If we're running on ICS or newer, enable all-caps to match the Action Bar tab style
+ textView.setAllCaps(true);
+ }
+
+ int padding = (int) (TAB_VIEW_PADDING_DIPS * getResources().getDisplayMetrics().density);
+ textView.setPadding(padding, padding, padding, padding);
+
+ return textView;
+ }
+
+ private void populateTabStrip() {
+ final PagerAdapter adapter = mViewPager.getAdapter();
+ final View.OnClickListener tabClickListener = new TabClickListener();
+
+ for (int i = 0; i < adapter.getCount(); i++) {
+ View tabView = null;
+ TextView tabTitleView = null;
+
+ if (mTabViewLayoutId != 0) {
+ // If there is a custom tab view layout id set, try and inflate it
+ tabView = LayoutInflater.from(getContext()).inflate(mTabViewLayoutId, mTabStrip,
+ false);
+ tabTitleView = (TextView) tabView.findViewById(mTabViewTextViewId);
+ }
+
+ if (tabView == null) {
+ tabView = createDefaultTabView(getContext());
+ }
+
+ if (tabTitleView == null && TextView.class.isInstance(tabView)) {
+ tabTitleView = (TextView) tabView;
+ }
+
+ tabTitleView.setText(adapter.getPageTitle(i));
+ tabView.setOnClickListener(tabClickListener);
+
+ mTabStrip.addView(tabView);
+ }
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+
+ if (mViewPager != null) {
+ scrollToTab(mViewPager.getCurrentItem(), 0);
+ }
+ }
+
+ private void scrollToTab(int tabIndex, int positionOffset) {
+ final int tabStripChildCount = mTabStrip.getChildCount();
+ if (tabStripChildCount == 0 || tabIndex < 0 || tabIndex >= tabStripChildCount) {
+ return;
+ }
+
+ View selectedChild = mTabStrip.getChildAt(tabIndex);
+ if (selectedChild != null) {
+ int targetScrollX = selectedChild.getLeft() + positionOffset;
+
+ if (tabIndex > 0 || positionOffset > 0) {
+ // If we're not at the first child and are mid-scroll, make sure we obey the offset
+ targetScrollX -= mTitleOffset;
+ }
+
+ scrollTo(targetScrollX, 0);
+ }
+ }
+
+ private class InternalViewPagerListener implements ViewPager.OnPageChangeListener {
+ private int mScrollState;
+
+ @Override
+ public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+ int tabStripChildCount = mTabStrip.getChildCount();
+ if ((tabStripChildCount == 0) || (position < 0) || (position >= tabStripChildCount)) {
+ return;
+ }
+
+ mTabStrip.onViewPagerPageChanged(position, positionOffset);
+
+ View selectedTitle = mTabStrip.getChildAt(position);
+ int extraOffset = (selectedTitle != null)
+ ? (int) (positionOffset * selectedTitle.getWidth())
+ : 0;
+ scrollToTab(position, extraOffset);
+
+ if (mViewPagerPageChangeListener != null) {
+ mViewPagerPageChangeListener.onPageScrolled(position, positionOffset,
+ positionOffsetPixels);
+ }
+ }
+
+ @Override
+ public void onPageScrollStateChanged(int state) {
+ mScrollState = state;
+
+ if (mViewPagerPageChangeListener != null) {
+ mViewPagerPageChangeListener.onPageScrollStateChanged(state);
+ }
+ }
+
+ @Override
+ public void onPageSelected(int position) {
+ if (mScrollState == ViewPager.SCROLL_STATE_IDLE) {
+ mTabStrip.onViewPagerPageChanged(position, 0f);
+ scrollToTab(position, 0);
+ }
+
+ if (mViewPagerPageChangeListener != null) {
+ mViewPagerPageChangeListener.onPageSelected(position);
+ }
+ }
+
+ }
+
+ private class TabClickListener implements View.OnClickListener {
+ @Override
+ public void onClick(View v) {
+ for (int i = 0; i < mTabStrip.getChildCount(); i++) {
+ if (v == mTabStrip.getChildAt(i)) {
+ mViewPager.setCurrentItem(i);
+ return;
+ }
+ }
+ }
+ }
+
+}
diff --git a/common/src/java/com/example/android/common/view/SlidingTabStrip.java b/common/src/java/com/example/android/common/view/SlidingTabStrip.java
new file mode 100644
index 0000000..d5bbbae
--- /dev/null
+++ b/common/src/java/com/example/android/common/view/SlidingTabStrip.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.common.view;
+
+import android.R;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.View;
+import android.widget.LinearLayout;
+
+class SlidingTabStrip extends LinearLayout {
+
+ private static final int DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS = 2;
+ private static final byte DEFAULT_BOTTOM_BORDER_COLOR_ALPHA = 0x26;
+ private static final int SELECTED_INDICATOR_THICKNESS_DIPS = 8;
+ private static final int DEFAULT_SELECTED_INDICATOR_COLOR = 0xFF33B5E5;
+
+ private static final int DEFAULT_DIVIDER_THICKNESS_DIPS = 1;
+ private static final byte DEFAULT_DIVIDER_COLOR_ALPHA = 0x20;
+ private static final float DEFAULT_DIVIDER_HEIGHT = 0.5f;
+
+ private final int mBottomBorderThickness;
+ private final Paint mBottomBorderPaint;
+
+ private final int mSelectedIndicatorThickness;
+ private final Paint mSelectedIndicatorPaint;
+
+ private final int mDefaultBottomBorderColor;
+
+ private final Paint mDividerPaint;
+ private final float mDividerHeight;
+
+ private int mSelectedPosition;
+ private float mSelectionOffset;
+
+ private SlidingTabLayout.TabColorizer mCustomTabColorizer;
+ private final SimpleTabColorizer mDefaultTabColorizer;
+
+ SlidingTabStrip(Context context) {
+ this(context, null);
+ }
+
+ SlidingTabStrip(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setWillNotDraw(false);
+
+ final float density = getResources().getDisplayMetrics().density;
+
+ TypedValue outValue = new TypedValue();
+ context.getTheme().resolveAttribute(R.attr.colorForeground, outValue, true);
+ final int themeForegroundColor = outValue.data;
+
+ mDefaultBottomBorderColor = setColorAlpha(themeForegroundColor,
+ DEFAULT_BOTTOM_BORDER_COLOR_ALPHA);
+
+ mDefaultTabColorizer = new SimpleTabColorizer();
+ mDefaultTabColorizer.setIndicatorColors(DEFAULT_SELECTED_INDICATOR_COLOR);
+ mDefaultTabColorizer.setDividerColors(setColorAlpha(themeForegroundColor,
+ DEFAULT_DIVIDER_COLOR_ALPHA));
+
+ mBottomBorderThickness = (int) (DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS * density);
+ mBottomBorderPaint = new Paint();
+ mBottomBorderPaint.setColor(mDefaultBottomBorderColor);
+
+ mSelectedIndicatorThickness = (int) (SELECTED_INDICATOR_THICKNESS_DIPS * density);
+ mSelectedIndicatorPaint = new Paint();
+
+ mDividerHeight = DEFAULT_DIVIDER_HEIGHT;
+ mDividerPaint = new Paint();
+ mDividerPaint.setStrokeWidth((int) (DEFAULT_DIVIDER_THICKNESS_DIPS * density));
+ }
+
+ void setCustomTabColorizer(SlidingTabLayout.TabColorizer customTabColorizer) {
+ mCustomTabColorizer = customTabColorizer;
+ invalidate();
+ }
+
+ void setSelectedIndicatorColors(int... colors) {
+ // Make sure that the custom colorizer is removed
+ mCustomTabColorizer = null;
+ mDefaultTabColorizer.setIndicatorColors(colors);
+ invalidate();
+ }
+
+ void setDividerColors(int... colors) {
+ // Make sure that the custom colorizer is removed
+ mCustomTabColorizer = null;
+ mDefaultTabColorizer.setDividerColors(colors);
+ invalidate();
+ }
+
+ void onViewPagerPageChanged(int position, float positionOffset) {
+ mSelectedPosition = position;
+ mSelectionOffset = positionOffset;
+ invalidate();
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ final int height = getHeight();
+ final int childCount = getChildCount();
+ final int dividerHeightPx = (int) (Math.min(Math.max(0f, mDividerHeight), 1f) * height);
+ final SlidingTabLayout.TabColorizer tabColorizer = mCustomTabColorizer != null
+ ? mCustomTabColorizer
+ : mDefaultTabColorizer;
+
+ // Thick colored underline below the current selection
+ if (childCount > 0) {
+ View selectedTitle = getChildAt(mSelectedPosition);
+ int left = selectedTitle.getLeft();
+ int right = selectedTitle.getRight();
+ int color = tabColorizer.getIndicatorColor(mSelectedPosition);
+
+ if (mSelectionOffset > 0f && mSelectedPosition < (getChildCount() - 1)) {
+ int nextColor = tabColorizer.getIndicatorColor(mSelectedPosition + 1);
+ if (color != nextColor) {
+ color = blendColors(nextColor, color, mSelectionOffset);
+ }
+
+ // Draw the selection partway between the tabs
+ View nextTitle = getChildAt(mSelectedPosition + 1);
+ left = (int) (mSelectionOffset * nextTitle.getLeft() +
+ (1.0f - mSelectionOffset) * left);
+ right = (int) (mSelectionOffset * nextTitle.getRight() +
+ (1.0f - mSelectionOffset) * right);
+ }
+
+ mSelectedIndicatorPaint.setColor(color);
+
+ canvas.drawRect(left, height - mSelectedIndicatorThickness, right,
+ height, mSelectedIndicatorPaint);
+ }
+
+ // Thin underline along the entire bottom edge
+ canvas.drawRect(0, height - mBottomBorderThickness, getWidth(), height, mBottomBorderPaint);
+
+ // Vertical separators between the titles
+ int separatorTop = (height - dividerHeightPx) / 2;
+ for (int i = 0; i < childCount - 1; i++) {
+ View child = getChildAt(i);
+ mDividerPaint.setColor(tabColorizer.getDividerColor(i));
+ canvas.drawLine(child.getRight(), separatorTop, child.getRight(),
+ separatorTop + dividerHeightPx, mDividerPaint);
+ }
+ }
+
+ /**
+ * Set the alpha value of the {@code color} to be the given {@code alpha} value.
+ */
+ private static int setColorAlpha(int color, byte alpha) {
+ return Color.argb(alpha, Color.red(color), Color.green(color), Color.blue(color));
+ }
+
+ /**
+ * Blend {@code color1} and {@code color2} using the given ratio.
+ *
+ * @param ratio of which to blend. 1.0 will return {@code color1}, 0.5 will give an even blend,
+ * 0.0 will return {@code color2}.
+ */
+ private static int blendColors(int color1, int color2, float ratio) {
+ final float inverseRation = 1f - ratio;
+ float r = (Color.red(color1) * ratio) + (Color.red(color2) * inverseRation);
+ float g = (Color.green(color1) * ratio) + (Color.green(color2) * inverseRation);
+ float b = (Color.blue(color1) * ratio) + (Color.blue(color2) * inverseRation);
+ return Color.rgb((int) r, (int) g, (int) b);
+ }
+
+ private static class SimpleTabColorizer implements SlidingTabLayout.TabColorizer {
+ private int[] mIndicatorColors;
+ private int[] mDividerColors;
+
+ @Override
+ public final int getIndicatorColor(int position) {
+ return mIndicatorColors[position % mIndicatorColors.length];
+ }
+
+ @Override
+ public final int getDividerColor(int position) {
+ return mDividerColors[position % mDividerColors.length];
+ }
+
+ void setIndicatorColors(int... colors) {
+ mIndicatorColors = colors;
+ }
+
+ void setDividerColors(int... colors) {
+ mDividerColors = colors;
+ }
+ }
+}
\ No newline at end of file
diff --git a/sensors/BatchStepSensor/BatchStepSensorSample/README-CardStream.txt b/sensors/BatchStepSensor/BatchStepSensorSample/README-CardStream.txt
new file mode 100644
index 0000000..957ccd6
--- /dev/null
+++ b/sensors/BatchStepSensor/BatchStepSensorSample/README-CardStream.txt
@@ -0,0 +1,82 @@
+<#--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+Steps to implement CardStream template:
+-in template-params.xml.ftl:
+ -add the following templates
+ <template src="base"/>
+ <template src="CardStream"/>
+ -add the following line to common imports
+ <common src="activities"/>
+ <common src="logger"/>
+
+-Add a Fragment to handle behavior. In your MainActivity.java class, it will reference a Fragment
+ called (yourProjectName)Fragment.java. Create that file in your project, using the "main" source
+ folder instead of "common" or "templates".
+ For instance, if your package name is com.example.foo, create the file
+ src/main/java/com/example/foo/FooFragment.java
+
+-Now it's time to deal with cards. Implement a method like this in your Fragment to access the CardStream:
+private CardStreamFragment getCardStream() {
+ if (mCards == null) {
+ mCards = ((CardStream) getActivity()).getCardStream();
+ }
+ return mCards;
+}
+
+
+-Create a instance of Card.Builder with a tag String that *must* be unique among all cards.
+
+ Card.Builder builder = new Card.Builder(UNIQUE_TAG_STRING);
+
+-Set the properties for your card in the builder. Some properties (title, description, progress type) can also
+be changed later.
+
+ builder.setTitle(String title)
+
+-Cards can also have more than one action that is shown as a button at the bottom of the card.
+All actions *must* be defined through the builder. They can be hidden or shown later again, but they must be defined
+in the builder before .build() is called.
+
+-To implement an action, use Builder.addAction with a label, id, type (Neutral/Positive/Negative) and
+ a CardActionCallback.
+ Actions can be distinguished by their id to avoid the use of a large number of unnamed callback instances.
+ For convenience, the tag of the card the action belongs to is also returned in the callback.
+
+ builder.addAction(actionLabel1, 0, Card.ACTION_NEUTRAL, new Card.CardActionCallback() {
+ @Override
+ public void onClick(int cardActionId, String tag) {
+ ...
+ }
+ });
+
+
+-After finishing setup process, call Buidler.build() to return a new instance of a Card.
+
+ final Card card = builder.build(activity);
+
+-Inside your MainActivity.java class, call getCardStream() to get the instance of the CardStreamFragment through
+which cards are shown on screen.
+A card needs to be added to the CardStreamFragment first before it can be shown.
+Cards are identified by their unique tag.
+
+ Card myCard = ...
+ getCardStreamFragment().addCard(myCard);
+ getCardStreamFragment().show(myCard.getTag());
+ getCardStreamFragment().hide("MyCardTag");
+ getCardStreamFragment().show("MyCardTag",false); // can't be dismissed by user
+
+
diff --git a/sensors/BatchStepSensor/BatchStepSensorSample/src/main/AndroidManifest.xml b/sensors/BatchStepSensor/BatchStepSensorSample/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..2c4e4f2
--- /dev/null
+++ b/sensors/BatchStepSensor/BatchStepSensorSample/src/main/AndroidManifest.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.batchstepsensor"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <!-- This sample requires at least Android KitKat for sensor batching support -->
+ <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="19" />
+
+ <!-- Require the step counter and step detector sensors.
+ See the method BatchStepSensorFragment#isKitkatWithStepSensor() for a programmatic check if
+ support is optional and the application supports a case where these sensors are not available.
+ -->
+ <uses-feature android:name="android.hardware.sensor.stepcounter" />
+ <uses-feature android:name="android.hardware.sensor.stepdetector" />
+
+
+ <application android:allowBackup="true"
+ android:label="@string/app_name"
+ android:icon="@drawable/ic_launcher"
+ android:theme="@style/AppTheme">
+
+ <activity android:name=".MainActivity"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+
+</manifest>
diff --git a/sensors/BatchStepSensor/BatchStepSensorSample/src/main/java/com/example/android/batchstepsensor/BatchStepSensorFragment.java b/sensors/BatchStepSensor/BatchStepSensorSample/src/main/java/com/example/android/batchstepsensor/BatchStepSensorFragment.java
new file mode 100644
index 0000000..aab0fc3
--- /dev/null
+++ b/sensors/BatchStepSensor/BatchStepSensorSample/src/main/java/com/example/android/batchstepsensor/BatchStepSensorFragment.java
@@ -0,0 +1,588 @@
+/*
+* Copyright 2014 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.example.android.batchstepsensor;
+
+import android.app.Activity;
+import android.content.pm.PackageManager;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+
+import com.example.android.common.logger.Log;
+
+public class BatchStepSensorFragment extends Fragment implements OnCardClickListener {
+
+ public static final String TAG = "StepSensorSample";
+ // Cards
+ private CardStreamFragment mCards = null;
+
+ // Card tags
+ public static final String CARD_INTRO = "intro";
+ public static final String CARD_REGISTER_DETECTOR = "register_detector";
+ public static final String CARD_REGISTER_COUNTER = "register_counter";
+ public static final String CARD_BATCHING_DESCRIPTION = "register_batching_description";
+ public static final String CARD_COUNTING = "counting";
+ public static final String CARD_EXPLANATION = "explanation";
+ public static final String CARD_NOBATCHSUPPORT = "error";
+
+ // Actions from REGISTER cards
+ public static final int ACTION_REGISTER_DETECT_NOBATCHING = 10;
+ public static final int ACTION_REGISTER_DETECT_BATCHING_5s = 11;
+ public static final int ACTION_REGISTER_DETECT_BATCHING_10s = 12;
+ public static final int ACTION_REGISTER_COUNT_NOBATCHING = 21;
+ public static final int ACTION_REGISTER_COUNT_BATCHING_5s = 22;
+ public static final int ACTION_REGISTER_COUNT_BATCHING_10s = 23;
+ // Action from COUNTING card
+ public static final int ACTION_UNREGISTER = 1;
+ // Actions from description cards
+ private static final int ACTION_BATCHING_DESCRIPTION_DISMISS = 2;
+ private static final int ACTION_EXPLANATION_DISMISS = 3;
+
+ // State of application, used to register for sensors when app is restored
+ public static final int STATE_OTHER = 0;
+ public static final int STATE_COUNTER = 1;
+ public static final int STATE_DETECTOR = 2;
+
+ // Bundle tags used to store data when restoring application state
+ private static final String BUNDLE_STATE = "state";
+ private static final String BUNDLE_LATENCY = "latency";
+ private static final String BUNDLE_STEPS = "steps";
+
+ // max batch latency is specified in microseconds
+ private static final int BATCH_LATENCY_0 = 0; // no batching
+ private static final int BATCH_LATENCY_10s = 10000000;
+ private static final int BATCH_LATENCY_5s = 5000000;
+
+ /*
+ For illustration we keep track of the last few events and show their delay from when the
+ event occurred until it was received by the event listener.
+ These variables keep track of the list of timestamps and the number of events.
+ */
+ // Number of events to keep in queue and display on card
+ private static final int EVENT_QUEUE_LENGTH = 10;
+ // List of timestamps when sensor events occurred
+ private float[] mEventDelays = new float[EVENT_QUEUE_LENGTH];
+
+ // number of events in event list
+ private int mEventLength = 0;
+ // pointer to next entry in sensor event list
+ private int mEventData = 0;
+
+ // Steps counted in current session
+ private int mSteps = 0;
+ // Value of the step counter sensor when the listener was registered.
+ // (Total steps are calculated from this value.)
+ private int mCounterSteps = 0;
+ // Steps counted by the step counter previously. Used to keep counter consistent across rotation
+ // changes
+ private int mPreviousCounterSteps = 0;
+ // State of the app (STATE_OTHER, STATE_COUNTER or STATE_DETECTOR)
+ private int mState = STATE_OTHER;
+ // When a listener is registered, the batch sensor delay in microseconds
+ private int mMaxDelay = 0;
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ CardStreamFragment stream = getCardStream();
+ if (stream.getVisibleCardCount() < 1) {
+ // No cards are visible, started for the first time
+ // Prepare all cards and show the intro card.
+ initialiseCards();
+ showIntroCard();
+ // Show the registration card if the hardware is supported, show an error otherwise
+ if (isKitkatWithStepSensor()) {
+ showRegisterCard();
+ } else {
+ showErrorCard();
+ }
+ }
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ // BEGIN_INCLUDE(onpause)
+ // Unregister the listener when the application is paused
+ unregisterListeners();
+ // END_INCLUDE(onpause)
+ }
+
+ /**
+ * Returns true if this device is supported. It needs to be running Android KitKat (4.4) or
+ * higher and has a step counter and step detector sensor.
+ * This check is useful when an app provides an alternative implementation or different
+ * functionality if the step sensors are not available or this code runs on a platform version
+ * below Android KitKat. If this functionality is required, then the minSDK parameter should
+ * be specified appropriately in the AndroidManifest.
+ *
+ * @return True iff the device can run this sample
+ */
+ private boolean isKitkatWithStepSensor() {
+ // BEGIN_INCLUDE(iskitkatsensor)
+ // Require at least Android KitKat
+ int currentApiVersion = android.os.Build.VERSION.SDK_INT;
+ // Check that the device supports the step counter and detector sensors
+ PackageManager packageManager = getActivity().getPackageManager();
+ return currentApiVersion >= android.os.Build.VERSION_CODES.KITKAT
+ && packageManager.hasSystemFeature(PackageManager.FEATURE_SENSOR_STEP_COUNTER)
+ && packageManager.hasSystemFeature(PackageManager.FEATURE_SENSOR_STEP_DETECTOR);
+ // END_INCLUDE(iskitkatsensor)
+ }
+
+ /**
+ * Handles a click on a card action.
+ * Registers a SensorEventListener (see {@link #registerEventListener(int, int)}) with the
+ * selected delay, dismisses cards and unregisters the listener
+ * (see {@link #unregisterListeners()}).
+ * Actions are defined when a card is created.
+ *
+ * @param cardActionId
+ * @param cardTag
+ */
+ @Override
+ public void onCardClick(int cardActionId, String cardTag) {
+
+ switch (cardActionId) {
+ // BEGIN_INCLUDE(onclick)
+ // Register Step Counter card
+ case ACTION_REGISTER_COUNT_NOBATCHING:
+ registerEventListener(BATCH_LATENCY_0, Sensor.TYPE_STEP_COUNTER);
+ break;
+ case ACTION_REGISTER_COUNT_BATCHING_5s:
+ registerEventListener(BATCH_LATENCY_5s, Sensor.TYPE_STEP_COUNTER);
+ break;
+ case ACTION_REGISTER_COUNT_BATCHING_10s:
+ registerEventListener(BATCH_LATENCY_10s, Sensor.TYPE_STEP_COUNTER);
+ break;
+
+ // Register Step Detector card
+ case ACTION_REGISTER_DETECT_NOBATCHING:
+ registerEventListener(BATCH_LATENCY_0, Sensor.TYPE_STEP_DETECTOR);
+ break;
+ case ACTION_REGISTER_DETECT_BATCHING_5s:
+ registerEventListener(BATCH_LATENCY_5s, Sensor.TYPE_STEP_DETECTOR);
+ break;
+ case ACTION_REGISTER_DETECT_BATCHING_10s:
+ registerEventListener(BATCH_LATENCY_10s, Sensor.TYPE_STEP_DETECTOR);
+ break;
+
+ // Unregister card
+ case ACTION_UNREGISTER:
+ showRegisterCard();
+ unregisterListeners();
+ // reset the application state when explicitly unregistered
+ mState = STATE_OTHER;
+ break;
+ // END_INCLUDE(onclick)
+ // Explanation cards
+ case ACTION_BATCHING_DESCRIPTION_DISMISS:
+ // permanently remove the batch description card, it will not be shown again
+ getCardStream().removeCard(CARD_BATCHING_DESCRIPTION);
+ break;
+ case ACTION_EXPLANATION_DISMISS:
+ // permanently remove the explanation card, it will not be shown again
+ getCardStream().removeCard(CARD_EXPLANATION);
+ }
+
+ // For register cards, display the counting card
+ if (cardTag.equals(CARD_REGISTER_COUNTER) || cardTag.equals(CARD_REGISTER_DETECTOR)) {
+ showCountingCards();
+ }
+ }
+
+ /**
+ * Register a {@link android.hardware.SensorEventListener} for the sensor and max batch delay.
+ * The maximum batch delay specifies the maximum duration in microseconds for which subsequent
+ * sensor events can be temporarily stored by the sensor before they are delivered to the
+ * registered SensorEventListener. A larger delay allows the system to handle sensor events more
+ * efficiently, allowing the system to switch to a lower power state while the sensor is
+ * capturing events. Once the max delay is reached, all stored events are delivered to the
+ * registered listener. Note that this value only specifies the maximum delay, the listener may
+ * receive events quicker. A delay of 0 disables batch mode and registers the listener in
+ * continuous mode.
+ * The optimium batch delay depends on the application. For example, a delay of 5 seconds or
+ * higher may be appropriate for an application that does not update the UI in real time.
+ *
+ * @param maxdelay
+ * @param sensorType
+ */
+ private void registerEventListener(int maxdelay, int sensorType) {
+ // BEGIN_INCLUDE(register)
+
+ // Keep track of state so that the correct sensor type and batch delay can be set up when
+ // the app is restored (for example on screen rotation).
+ mMaxDelay = maxdelay;
+ if (sensorType == Sensor.TYPE_STEP_COUNTER) {
+ mState = STATE_COUNTER;
+ /*
+ Reset the initial step counter value, the first event received by the event listener is
+ stored in mCounterSteps and used to calculate the total number of steps taken.
+ */
+ mCounterSteps = 0;
+ Log.i(TAG, "Event listener for step counter sensor registered with a max delay of "
+ + mMaxDelay);
+ } else {
+ mState = STATE_DETECTOR;
+ Log.i(TAG, "Event listener for step detector sensor registered with a max delay of "
+ + mMaxDelay);
+ }
+
+ // Get the default sensor for the sensor type from the SenorManager
+ SensorManager sensorManager =
+ (SensorManager) getActivity().getSystemService(Activity.SENSOR_SERVICE);
+ // sensorType is either Sensor.TYPE_STEP_COUNTER or Sensor.TYPE_STEP_DETECTOR
+ Sensor sensor = sensorManager.getDefaultSensor(sensorType);
+
+ // Register the listener for this sensor in batch mode.
+ // If the max delay is 0, events will be delivered in continuous mode without batching.
+ final boolean batchMode = sensorManager.registerListener(
+ mListener, sensor, SensorManager.SENSOR_DELAY_NORMAL, maxdelay);
+
+ if (!batchMode) {
+ // Batch mode could not be enabled, show a warning message and switch to continuous mode
+ getCardStream().getCard(CARD_NOBATCHSUPPORT)
+ .setDescription(getString(R.string.warning_nobatching));
+ getCardStream().showCard(CARD_NOBATCHSUPPORT);
+ Log.w(TAG, "Could not register sensor listener in batch mode, " +
+ "falling back to continuous mode.");
+ }
+
+ if (maxdelay > 0 && batchMode) {
+ // Batch mode was enabled successfully, show a description card
+ getCardStream().showCard(CARD_BATCHING_DESCRIPTION);
+ }
+
+ // Show the explanation card
+ getCardStream().showCard(CARD_EXPLANATION);
+
+ // END_INCLUDE(register)
+
+ }
+
+ /**
+ * Unregisters the sensor listener if it is registered.
+ */
+ private void unregisterListeners() {
+ // BEGIN_INCLUDE(unregister)
+ SensorManager sensorManager =
+ (SensorManager) getActivity().getSystemService(Activity.SENSOR_SERVICE);
+ sensorManager.unregisterListener(mListener);
+ Log.i(TAG, "Sensor listener unregistered.");
+
+ // END_INCLUDE(unregister)
+ }
+
+ /**
+ * Resets the step counter by clearing all counting variables and lists.
+ */
+ private void resetCounter() {
+ // BEGIN_INCLUDE(reset)
+ mSteps = 0;
+ mCounterSteps = 0;
+ mEventLength = 0;
+ mEventDelays = new float[EVENT_QUEUE_LENGTH];
+ mPreviousCounterSteps = 0;
+ // END_INCLUDE(reset)
+ }
+
+
+ /**
+ * Listener that handles step sensor events for step detector and step counter sensors.
+ */
+ private final SensorEventListener mListener = new SensorEventListener() {
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ // BEGIN_INCLUDE(sensorevent)
+ // store the delay of this event
+ recordDelay(event);
+ final String delayString = getDelayString();
+
+ if (event.sensor.getType() == Sensor.TYPE_STEP_DETECTOR) {
+ // A step detector event is received for each step.
+ // This means we need to count steps ourselves
+
+ mSteps += event.values.length;
+
+ // Update the card with the latest step count
+ getCardStream().getCard(CARD_COUNTING)
+ .setTitle(getString(R.string.counting_title, mSteps))
+ .setDescription(getString(R.string.counting_description,
+ getString(R.string.sensor_detector), mMaxDelay, delayString));
+
+ Log.i(TAG,
+ "New step detected by STEP_DETECTOR sensor. Total step count: " + mSteps);
+
+ } else if (event.sensor.getType() == Sensor.TYPE_STEP_COUNTER) {
+
+ /*
+ A step counter event contains the total number of steps since the listener
+ was first registered. We need to keep track of this initial value to calculate the
+ number of steps taken, as the first value a listener receives is undefined.
+ */
+ if (mCounterSteps < 1) {
+ // initial value
+ mCounterSteps = (int) event.values[0];
+ }
+
+ // Calculate steps taken based on first counter value received.
+ mSteps = (int) event.values[0] - mCounterSteps;
+
+ // Add the number of steps previously taken, otherwise the counter would start at 0.
+ // This is needed to keep the counter consistent across rotation changes.
+ mSteps = mSteps + mPreviousCounterSteps;
+
+ // Update the card with the latest step count
+ getCardStream().getCard(CARD_COUNTING)
+ .setTitle(getString(R.string.counting_title, mSteps))
+ .setDescription(getString(R.string.counting_description,
+ getString(R.string.sensor_counter), mMaxDelay, delayString));
+ Log.i(TAG, "New step detected by STEP_COUNTER sensor. Total step count: " + mSteps);
+ // END_INCLUDE(sensorevent)
+ }
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+
+ }
+ };
+
+ /**
+ * Records the delay for the event.
+ *
+ * @param event
+ */
+ private void recordDelay(SensorEvent event) {
+ // Calculate the delay from when event was recorded until it was received here in ms
+ // Event timestamp is recorded in us accuracy, but ms accuracy is sufficient here
+ mEventDelays[mEventData] = System.currentTimeMillis() - (event.timestamp / 1000000L);
+
+ // Increment length counter
+ mEventLength = Math.min(EVENT_QUEUE_LENGTH, mEventLength + 1);
+ // Move pointer to the next (oldest) location
+ mEventData = (mEventData + 1) % EVENT_QUEUE_LENGTH;
+ }
+
+ private final StringBuffer mDelayStringBuffer = new StringBuffer();
+
+ /**
+ * Returns a string describing the sensor delays recorded in
+ * {@link #recordDelay(android.hardware.SensorEvent)}.
+ *
+ * @return
+ */
+ private String getDelayString() {
+ // Empty the StringBuffer
+ mDelayStringBuffer.setLength(0);
+
+ // Loop over all recorded delays and append them to the buffer as a decimal
+ for (int i = 0; i < mEventLength; i++) {
+ if (i > 0) {
+ mDelayStringBuffer.append(", ");
+ }
+ final int index = (mEventData + i) % EVENT_QUEUE_LENGTH;
+ final float delay = mEventDelays[index] / 1000f; // convert delay from ms into s
+ mDelayStringBuffer.append(String.format("%1.1f", delay));
+ }
+
+ return mDelayStringBuffer.toString();
+ }
+
+ /**
+ * Records the state of the application into the {@link android.os.Bundle}.
+ *
+ * @param outState
+ */
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ // BEGIN_INCLUDE(saveinstance)
+ super.onSaveInstanceState(outState);
+ // Store all variables required to restore the state of the application
+ outState.putInt(BUNDLE_LATENCY, mMaxDelay);
+ outState.putInt(BUNDLE_STATE, mState);
+ outState.putInt(BUNDLE_STEPS, mSteps);
+ // END_INCLUDE(saveinstance)
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ // BEGIN_INCLUDE(restore)
+ // Fragment is being restored, reinitialise its state with data from the bundle
+ if (savedInstanceState != null) {
+ resetCounter();
+ mSteps = savedInstanceState.getInt(BUNDLE_STEPS);
+ mState = savedInstanceState.getInt(BUNDLE_STATE);
+ mMaxDelay = savedInstanceState.getInt(BUNDLE_LATENCY);
+
+ // Register listeners again if in detector or counter states with restored delay
+ if (mState == STATE_DETECTOR) {
+ registerEventListener(mMaxDelay, Sensor.TYPE_STEP_DETECTOR);
+ } else if (mState == STATE_COUNTER) {
+ // store the previous number of steps to keep step counter count consistent
+ mPreviousCounterSteps = mSteps;
+ registerEventListener(mMaxDelay, Sensor.TYPE_STEP_COUNTER);
+ }
+ }
+ // END_INCLUDE(restore)
+ }
+
+ /**
+ * Hides the registration cards, reset the counter and show the step counting card.
+ */
+ private void showCountingCards() {
+ // Hide the registration cards
+ getCardStream().hideCard(CARD_REGISTER_DETECTOR);
+ getCardStream().hideCard(CARD_REGISTER_COUNTER);
+
+ // Show the explanation card if it has not been dismissed
+ getCardStream().showCard(CARD_EXPLANATION);
+
+ // Reset the step counter, then show the step counting card
+ resetCounter();
+
+ // Set the inital text for the step counting card before a step is recorded
+ String sensor = "-";
+ if (mState == STATE_COUNTER) {
+ sensor = getString(R.string.sensor_counter);
+ } else if (mState == STATE_DETECTOR) {
+ sensor = getString(R.string.sensor_detector);
+ }
+ // Set initial text
+ getCardStream().getCard(CARD_COUNTING)
+ .setTitle(getString(R.string.counting_title, 0))
+ .setDescription(getString(R.string.counting_description, sensor, mMaxDelay, "-"));
+
+ // Show the counting card and make it undismissable
+ getCardStream().showCard(CARD_COUNTING, false);
+
+ }
+
+ /**
+ * Show the introduction card
+ */
+ private void showIntroCard() {
+ Card c = new Card.Builder(this, CARD_INTRO)
+ .setTitle(getString(R.string.intro_title))
+ .setDescription(getString(R.string.intro_message))
+ .build(getActivity());
+ getCardStream().addCard(c, true);
+ }
+
+ /**
+ * Show two registration cards, one for the step detector and counter sensors.
+ */
+ private void showRegisterCard() {
+ // Hide the counting and explanation cards
+ getCardStream().hideCard(CARD_BATCHING_DESCRIPTION);
+ getCardStream().hideCard(CARD_EXPLANATION);
+ getCardStream().hideCard(CARD_COUNTING);
+
+ // Show two undismissable registration cards, one for each step sensor
+ getCardStream().showCard(CARD_REGISTER_DETECTOR, false);
+ getCardStream().showCard(CARD_REGISTER_COUNTER, false);
+ }
+
+ /**
+ * Show the error card.
+ */
+ private void showErrorCard() {
+ getCardStream().showCard(CARD_NOBATCHSUPPORT, false);
+ }
+
+ /**
+ * Initialise Cards.
+ */
+ private void initialiseCards() {
+ // Step counting
+ Card c = new Card.Builder(this, CARD_COUNTING)
+ .setTitle("Steps")
+ .setDescription("")
+ .addAction("Unregister Listener", ACTION_UNREGISTER, Card.ACTION_NEGATIVE)
+ .build(getActivity());
+ getCardStream().addCard(c);
+
+ // Register step detector listener
+ c = new Card.Builder(this, CARD_REGISTER_DETECTOR)
+ .setTitle(getString(R.string.register_detector_title))
+ .setDescription(getString(R.string.register_detector_description))
+ .addAction(getString(R.string.register_0),
+ ACTION_REGISTER_DETECT_NOBATCHING, Card.ACTION_NEUTRAL)
+ .addAction(getString(R.string.register_5),
+ ACTION_REGISTER_DETECT_BATCHING_5s, Card.ACTION_NEUTRAL)
+ .addAction(getString(R.string.register_10),
+ ACTION_REGISTER_DETECT_BATCHING_10s, Card.ACTION_NEUTRAL)
+ .build(getActivity());
+ getCardStream().addCard(c);
+
+ // Register step counter listener
+ c = new Card.Builder(this, CARD_REGISTER_COUNTER)
+ .setTitle(getString(R.string.register_counter_title))
+ .setDescription(getString(R.string.register_counter_description))
+ .addAction(getString(R.string.register_0),
+ ACTION_REGISTER_COUNT_NOBATCHING, Card.ACTION_NEUTRAL)
+ .addAction(getString(R.string.register_5),
+ ACTION_REGISTER_COUNT_BATCHING_5s, Card.ACTION_NEUTRAL)
+ .addAction(getString(R.string.register_10),
+ ACTION_REGISTER_COUNT_BATCHING_10s, Card.ACTION_NEUTRAL)
+ .build(getActivity());
+ getCardStream().addCard(c);
+
+
+ // Batching description
+ c = new Card.Builder(this, CARD_BATCHING_DESCRIPTION)
+ .setTitle(getString(R.string.batching_queue_title))
+ .setDescription(getString(R.string.batching_queue_description))
+ .addAction(getString(R.string.action_notagain),
+ ACTION_BATCHING_DESCRIPTION_DISMISS, Card.ACTION_POSITIVE)
+ .build(getActivity());
+ getCardStream().addCard(c);
+
+ // Explanation
+ c = new Card.Builder(this, CARD_EXPLANATION)
+ .setDescription(getString(R.string.explanation_description))
+ .addAction(getString(R.string.action_notagain),
+ ACTION_EXPLANATION_DISMISS, Card.ACTION_POSITIVE)
+ .build(getActivity());
+ getCardStream().addCard(c);
+
+ // Error
+ c = new Card.Builder(this, CARD_NOBATCHSUPPORT)
+ .setTitle(getString(R.string.error_title))
+ .setDescription(getString(R.string.error_nosensor))
+ .build(getActivity());
+ getCardStream().addCard(c);
+ }
+
+ /**
+ * Returns the cached CardStreamFragment used to show cards.
+ *
+ * @return
+ */
+ private CardStreamFragment getCardStream() {
+ if (mCards == null) {
+ mCards = ((CardStream) getActivity()).getCardStream();
+ }
+ return mCards;
+ }
+
+}
diff --git a/sensors/BatchStepSensor/BatchStepSensorSample/src/main/res/drawable-hdpi/ic_launcher.png b/sensors/BatchStepSensor/BatchStepSensorSample/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..564742c
--- /dev/null
+++ b/sensors/BatchStepSensor/BatchStepSensorSample/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/sensors/BatchStepSensor/BatchStepSensorSample/src/main/res/drawable-mdpi/ic_launcher.png b/sensors/BatchStepSensor/BatchStepSensorSample/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..08abe57
--- /dev/null
+++ b/sensors/BatchStepSensor/BatchStepSensorSample/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/sensors/BatchStepSensor/BatchStepSensorSample/src/main/res/drawable-xhdpi/ic_launcher.png b/sensors/BatchStepSensor/BatchStepSensorSample/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..15bafae
--- /dev/null
+++ b/sensors/BatchStepSensor/BatchStepSensorSample/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/sensors/BatchStepSensor/BatchStepSensorSample/src/main/res/drawable-xxhdpi/ic_launcher.png b/sensors/BatchStepSensor/BatchStepSensorSample/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..40bdd35
--- /dev/null
+++ b/sensors/BatchStepSensor/BatchStepSensorSample/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/sensors/BatchStepSensor/BatchStepSensorSample/src/main/res/values/strings.xml b/sensors/BatchStepSensor/BatchStepSensorSample/src/main/res/values/strings.xml
new file mode 100644
index 0000000..9c0a8ad
--- /dev/null
+++ b/sensors/BatchStepSensor/BatchStepSensorSample/src/main/res/values/strings.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+ <string name="intro_title">Introduction</string>
+
+ <string name="batching_queue_title">Background sensor batching</string>
+ <string name="batching_queue_description">Batching allows the sensor to report sensor events at
+ a specified frequency.\n\nThe system delays calls to the SensorEventListener and deliver
+ them in intervals, based on the maximum report latency specified when the listener is
+ registered. Note that this only means that the call to onSensorChanged() is delayed, the
+ total number of calls is identical as if no batching was used. Sensors only deliver events
+ while the CPU is awake. If the CPU is asleep and a batched sensor event listener is still
+ registered, the sensor will continue to collect events until it runs out of memory and
+ overwrites old values. This use case is not covered by this sample. (The sensor event queue
+ should be flushed using a scheduled background thread.) \n\nIn this sample app data is only
+ collected while the app is running and the CPU is awake. In this case the sensor will
+ deliver events before the queue fills up.
+ </string>
+
+ <string name="explanation_description">The age of a sensor event describes the delay between
+ when it was recorded by the sensor until it was delivered to the SensorEventListener.
+ </string>
+
+ <string name="register_detector_title">Register step detector sensor</string>
+ <string name="register_detector_description">Register a listener for the STEP DETECTOR
+ sensor.\n\nThis sensor delivers an event when the user takes a step. One event is received
+ per step.
+ </string>
+
+ <string name="register_counter_title">Register step counter sensor</string>
+ <string name="register_counter_description">Register a listener for the STEP COUNTER
+ sensor.\n\nThis sensor triggers events when a step is detected, but applies algorithms to
+ filter out false positives. Events from this sensor have higher latency than the step
+ detector and contain the total number of steps taken since the sensor was first registered.
+ </string>
+
+ <string name="register_0">No batching (delay=0)</string>
+ <string name="register_5">5s batching (delay=5000ms)</string>
+ <string name="register_10">10s batching (delay=10000ms)</string>
+
+ <string name="counting_title">Total Steps: %1$d</string>
+ <string name="sensor_counter">Step Counter</string>
+ <string name="sensor_detector">Step Detector</string>
+ <string name="counting_description">Sensor: %1$s\nMax sensor event delay: %2$,d \u00B5s\nAge of
+ events in s:\n%3$s
+ </string>
+
+ <string name="error_title">Error</string>
+ <string name="error_nosensor">This sample requires at least Android KitKat (4.4) and a device
+ with the step sensor.\n\nThis device does not appear to meet these requirements, as an
+ alternative you may want to consider using the gyro sensor and implement your own step
+ recognition as a fallback.
+ </string>
+ <string name="warning_nobatching">The listener has been registered, but batch mode could not be
+ enabled.\n\nIt is likely that it is not supported by this device.\n\nSensor events will be
+ delivered in continuous mode.
+ </string>
+
+ <string name="action_notagain">Do not show again</string>
+</resources>
\ No newline at end of file
diff --git a/sensors/BatchStepSensor/build.gradle b/sensors/BatchStepSensor/build.gradle
new file mode 100644
index 0000000..f9f6f65
--- /dev/null
+++ b/sensors/BatchStepSensor/build.gradle
@@ -0,0 +1,14 @@
+
+
+
+
+// BEGIN_EXCLUDE
+import com.example.android.samples.build.SampleGenPlugin
+apply plugin: SampleGenPlugin
+
+samplegen {
+ pathToBuild "../../../../build"
+ pathToSamplesCommon "../../common"
+}
+apply from: "../../../../build/build.gradle"
+// END_EXCLUDE
diff --git a/sensors/BatchStepSensor/buildSrc/build.gradle b/sensors/BatchStepSensor/buildSrc/build.gradle
new file mode 100644
index 0000000..29282af
--- /dev/null
+++ b/sensors/BatchStepSensor/buildSrc/build.gradle
@@ -0,0 +1,18 @@
+
+
+
+repositories {
+ mavenCentral()
+}
+dependencies {
+ compile 'org.freemarker:freemarker:2.3.20'
+}
+
+sourceSets {
+ main {
+ groovy {
+ srcDir new File(rootDir, "../../../../../build/buildSrc/src/main/groovy")
+ }
+ }
+}
+
diff --git a/sensors/BatchStepSensor/gradle/wrapper/gradle-wrapper.jar b/sensors/BatchStepSensor/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..8c0fb64
--- /dev/null
+++ b/sensors/BatchStepSensor/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/sensors/BatchStepSensor/gradle/wrapper/gradle-wrapper.properties b/sensors/BatchStepSensor/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..56f685a
--- /dev/null
+++ b/sensors/BatchStepSensor/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Apr 10 15:27:10 PDT 2013
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=http\://services.gradle.org/distributions/gradle-1.10-bin.zip
diff --git a/sensors/BatchStepSensor/gradlew b/sensors/BatchStepSensor/gradlew
new file mode 100755
index 0000000..91a7e26
--- /dev/null
+++ b/sensors/BatchStepSensor/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/sensors/BatchStepSensor/gradlew.bat b/sensors/BatchStepSensor/gradlew.bat
new file mode 100644
index 0000000..aec9973
--- /dev/null
+++ b/sensors/BatchStepSensor/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/sensors/BatchStepSensor/settings.gradle b/sensors/BatchStepSensor/settings.gradle
new file mode 100644
index 0000000..18ebefc
--- /dev/null
+++ b/sensors/BatchStepSensor/settings.gradle
@@ -0,0 +1,4 @@
+
+
+
+include 'BatchStepSensorSample'
diff --git a/sensors/BatchStepSensor/template-params.xml b/sensors/BatchStepSensor/template-params.xml
new file mode 100644
index 0000000..a07579d
--- /dev/null
+++ b/sensors/BatchStepSensor/template-params.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+
+
+<sample>
+ <name>BatchStepSensor</name>
+ <group>Sensors</group>
+ <package>com.example.android.batchstepsensor</package>
+
+
+
+ <!-- change minSdk if needed-->
+ <minSdk>19</minSdk>
+
+
+ <strings>
+ <intro>
+ <![CDATA[
+ This sample demonstrates the use of the two step sensors (step detector and counter) and
+ sensor batching.\n\n It shows how to register a SensorEventListener with and without
+ batching and shows how these events are received.\n\nThe Step Detector sensor fires an
+ event when a step is detected, while the step counter returns the total number of
+ steps since a listener was first registered for this sensor.
+ Both sensors only count steps while a listener is registered. This sample only covers the
+ basic case, where a listener is only registered while the app is running. Likewise,
+ batched sensors can be used in the background (when the CPU is suspended), which
+ requires manually flushing the sensor event queue before it overflows, which is not
+ covered in this sample.
+ ]]>
+ </intro>
+ </strings>
+
+ <template src="base"/>
+ <template src="CardStream"/>
+ <common src="logger"/>
+ <common src="activities"/>
+
+</sample>
diff --git a/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/.gitignore b/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/README-fragmentview.txt b/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/README-fragmentview.txt
new file mode 100644
index 0000000..ba92b3a
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/README-fragmentview.txt
@@ -0,0 +1,37 @@
+<#--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+Steps to implement FragmentView template:
+-in template-params.xml.ftl:
+ -add the following line to common imports
+ <common src="activities"/>
+
+-Add a Fragment to show behavior. In your MainActivity.java class, it will reference a Fragment
+ called (yourProjectName)Fragment.java. Create that file in your project, using the "main" source
+ folder instead of "common" or "templates".
+ For instance, if your package name is com.example.foo, create the file
+ src/main/java/com/example/foo/FooFragment.java
+
+
+-Within this fragment, make sure that the onCreate method has the line
+ "setHasOptionsMenu(true);", to enable the fragment to handle menu events.
+
+-In order to override menu events, override onOptionsItemSelected.
+
+-refer to sampleSamples/fragmentViewSample for a reference implementation of a
+project built on this template.
+
+
diff --git a/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/src/main/AndroidManifest.xml b/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..31cbfb8
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/src/main/AndroidManifest.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.slidingtabsbasic"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="19" />
+
+ <application android:allowBackup="true"
+ android:label="@string/app_name"
+ android:icon="@drawable/ic_launcher"
+ android:theme="@style/AppTheme">
+
+ <activity android:name=".MainActivity"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+
+</manifest>
diff --git a/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/src/main/java/com/example/android/slidingtabsbasic/SlidingTabsBasicFragment.java b/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/src/main/java/com/example/android/slidingtabsbasic/SlidingTabsBasicFragment.java
new file mode 100644
index 0000000..80f7b10
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/src/main/java/com/example/android/slidingtabsbasic/SlidingTabsBasicFragment.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.slidingtabsbasic;
+
+import com.example.android.common.logger.Log;
+import com.example.android.common.view.SlidingTabLayout;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.view.PagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+/**
+ * A basic sample which shows how to use {@link com.example.android.common.view.SlidingTabLayout}
+ * to display a custom {@link ViewPager} title strip which gives continuous feedback to the user
+ * when scrolling.
+ */
+public class SlidingTabsBasicFragment extends Fragment {
+
+ static final String LOG_TAG = "SlidingTabsBasicFragment";
+
+ /**
+ * A custom {@link ViewPager} title strip which looks much like Tabs present in Android v4.0 and
+ * above, but is designed to give continuous feedback to the user when scrolling.
+ */
+ private SlidingTabLayout mSlidingTabLayout;
+
+ /**
+ * A {@link ViewPager} which will be used in conjunction with the {@link SlidingTabLayout} above.
+ */
+ private ViewPager mViewPager;
+
+ /**
+ * Inflates the {@link View} which will be displayed by this {@link Fragment}, from the app's
+ * resources.
+ */
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.fragment_sample, container, false);
+ }
+
+ // BEGIN_INCLUDE (fragment_onviewcreated)
+ /**
+ * This is called after the {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)} has finished.
+ * Here we can pick out the {@link View}s we need to configure from the content view.
+ *
+ * We set the {@link ViewPager}'s adapter to be an instance of {@link SamplePagerAdapter}. The
+ * {@link SlidingTabLayout} is then given the {@link ViewPager} so that it can populate itself.
+ *
+ * @param view View created in {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}
+ */
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ // BEGIN_INCLUDE (setup_viewpager)
+ // Get the ViewPager and set it's PagerAdapter so that it can display items
+ mViewPager = (ViewPager) view.findViewById(R.id.viewpager);
+ mViewPager.setAdapter(new SamplePagerAdapter());
+ // END_INCLUDE (setup_viewpager)
+
+ // BEGIN_INCLUDE (setup_slidingtablayout)
+ // Give the SlidingTabLayout the ViewPager, this must be done AFTER the ViewPager has had
+ // it's PagerAdapter set.
+ mSlidingTabLayout = (SlidingTabLayout) view.findViewById(R.id.sliding_tabs);
+ mSlidingTabLayout.setViewPager(mViewPager);
+ // END_INCLUDE (setup_slidingtablayout)
+ }
+ // END_INCLUDE (fragment_onviewcreated)
+
+ /**
+ * The {@link android.support.v4.view.PagerAdapter} used to display pages in this sample.
+ * The individual pages are simple and just display two lines of text. The important section of
+ * this class is the {@link #getPageTitle(int)} method which controls what is displayed in the
+ * {@link SlidingTabLayout}.
+ */
+ class SamplePagerAdapter extends PagerAdapter {
+
+ /**
+ * @return the number of pages to display
+ */
+ @Override
+ public int getCount() {
+ return 10;
+ }
+
+ /**
+ * @return true if the value returned from {@link #instantiateItem(ViewGroup, int)} is the
+ * same object as the {@link View} added to the {@link ViewPager}.
+ */
+ @Override
+ public boolean isViewFromObject(View view, Object o) {
+ return o == view;
+ }
+
+ // BEGIN_INCLUDE (pageradapter_getpagetitle)
+ /**
+ * Return the title of the item at {@code position}. This is important as what this method
+ * returns is what is displayed in the {@link SlidingTabLayout}.
+ * <p>
+ * Here we construct one using the position value, but for real application the title should
+ * refer to the item's contents.
+ */
+ @Override
+ public CharSequence getPageTitle(int position) {
+ return "Item " + (position + 1);
+ }
+ // END_INCLUDE (pageradapter_getpagetitle)
+
+ /**
+ * Instantiate the {@link View} which should be displayed at {@code position}. Here we
+ * inflate a layout from the apps resources and then change the text view to signify the position.
+ */
+ @Override
+ public Object instantiateItem(ViewGroup container, int position) {
+ // Inflate a new layout from our resources
+ View view = getActivity().getLayoutInflater().inflate(R.layout.pager_item,
+ container, false);
+ // Add the newly created View to the ViewPager
+ container.addView(view);
+
+ // Retrieve a TextView from the inflated View, and update it's text
+ TextView title = (TextView) view.findViewById(R.id.item_title);
+ title.setText(String.valueOf(position + 1));
+
+ Log.i(LOG_TAG, "instantiateItem() [position: " + position + "]");
+
+ // Return the View
+ return view;
+ }
+
+ /**
+ * Destroy the item from the {@link ViewPager}. In our case this is simply removing the
+ * {@link View}.
+ */
+ @Override
+ public void destroyItem(ViewGroup container, int position, Object object) {
+ container.removeView((View) object);
+ Log.i(LOG_TAG, "destroyItem() [position: " + position + "]");
+ }
+
+ }
+}
diff --git a/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/src/main/res/drawable-hdpi/ic_launcher.png b/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..53ebb57
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/src/main/res/drawable-mdpi/ic_launcher.png b/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..33aa87a
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/src/main/res/drawable-xhdpi/ic_launcher.png b/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..6a4ba00
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/src/main/res/drawable-xxhdpi/ic_launcher.png b/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..c3744cd
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/src/main/res/layout/fragment_sample.xml b/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/src/main/res/layout/fragment_sample.xml
new file mode 100644
index 0000000..6ac3690
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/src/main/res/layout/fragment_sample.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <com.example.android.common.view.SlidingTabLayout
+ android:id="@+id/sliding_tabs"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+ <android.support.v4.view.ViewPager
+ android:id="@+id/viewpager"
+ android:layout_width="match_parent"
+ android:layout_height="0px"
+ android:layout_weight="1"
+ android:background="@android:color/white"/>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/src/main/res/layout/pager_item.xml b/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/src/main/res/layout/pager_item.xml
new file mode 100644
index 0000000..ce4413f
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/src/main/res/layout/pager_item.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:gravity="center">
+
+ <TextView
+ android:id="@+id/item_subtitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:text="Page:"/>
+
+ <TextView
+ android:id="@+id/item_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="80sp" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/tests/AndroidManifest.xml b/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/tests/AndroidManifest.xml
new file mode 100644
index 0000000..8d8fa2b
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/tests/AndroidManifest.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+
+
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<!-- package name must be unique so suffix with "tests" so package loader doesn't ignore us -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.slidingtabsbasic.tests"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <uses-sdk
+ android:minSdkVersion="4"
+ android:targetSdkVersion="19" />
+
+ <!-- We add an application tag here just so that we can indicate that
+ this package needs to link against the android.test library,
+ which is needed when building test cases. -->
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <!--
+ Specifies the instrumentation test runner used to run the tests.
+ -->
+ <instrumentation
+ android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.example.android.slidingtabsbasic"
+ android:label="Tests for com.example.android.slidingtabsbasic" />
+
+</manifest>
\ No newline at end of file
diff --git a/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/tests/src/com/example/android/slidingtabsbasic/tests/SampleTests.java b/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/tests/src/com/example/android/slidingtabsbasic/tests/SampleTests.java
new file mode 100644
index 0000000..6ab9c73
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsBasic/SlidingTabsBasicSample/tests/src/com/example/android/slidingtabsbasic/tests/SampleTests.java
@@ -0,0 +1,79 @@
+/*
+* Copyright 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+
+
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package com.example.android.slidingtabsbasic.tests;
+
+import com.example.android.slidingtabsbasic.*;
+
+import android.test.ActivityInstrumentationTestCase2;
+
+/**
+* Tests for SlidingTabsBasic sample.
+*/
+public class SampleTests extends ActivityInstrumentationTestCase2<MainActivity> {
+
+ private MainActivity mTestActivity;
+ private SlidingTabsBasicFragment mTestFragment;
+
+ public SampleTests() {
+ super(MainActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // Starts the activity under test using the default Intent with:
+ // action = {@link Intent#ACTION_MAIN}
+ // flags = {@link Intent#FLAG_ACTIVITY_NEW_TASK}
+ // All other fields are null or empty.
+ mTestActivity = getActivity();
+ mTestFragment = (SlidingTabsBasicFragment)
+ mTestActivity.getSupportFragmentManager().getFragments().get(1);
+ }
+
+ /**
+ * Test if the test fixture has been set up correctly.
+ */
+ public void testPreconditions() {
+ //Try to add a message to add context to your assertions. These messages will be shown if
+ //a tests fails and make it easy to understand why a test failed
+ assertNotNull("mTestActivity is null", mTestActivity);
+ assertNotNull("mTestFragment is null", mTestFragment);
+ }
+
+ /**
+ * Add more tests below.
+ */
+
+}
\ No newline at end of file
diff --git a/ui/views/SlidingTabs/SlidingTabsBasic/build.gradle b/ui/views/SlidingTabs/SlidingTabsBasic/build.gradle
new file mode 100644
index 0000000..cda9c5c
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsBasic/build.gradle
@@ -0,0 +1,14 @@
+
+
+
+
+// BEGIN_EXCLUDE
+import com.example.android.samples.build.SampleGenPlugin
+apply plugin: SampleGenPlugin
+
+samplegen {
+ pathToBuild "../../../../../../build"
+ pathToSamplesCommon "../../../../common"
+}
+apply from: "../../../../../../build/build.gradle"
+// END_EXCLUDE
diff --git a/ui/views/SlidingTabs/SlidingTabsBasic/buildSrc/build.gradle b/ui/views/SlidingTabs/SlidingTabsBasic/buildSrc/build.gradle
new file mode 100644
index 0000000..81f445f
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsBasic/buildSrc/build.gradle
@@ -0,0 +1,18 @@
+
+
+
+repositories {
+ mavenCentral()
+}
+dependencies {
+ compile 'org.freemarker:freemarker:2.3.20'
+}
+
+sourceSets {
+ main {
+ groovy {
+ srcDir new File(rootDir, "../../../../../../../build/buildSrc/src/main/groovy")
+ }
+ }
+}
+
diff --git a/ui/views/SlidingTabs/SlidingTabsBasic/gradle/wrapper/gradle-wrapper.jar b/ui/views/SlidingTabs/SlidingTabsBasic/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..8c0fb64
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsBasic/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/ui/views/SlidingTabs/SlidingTabsBasic/gradle/wrapper/gradle-wrapper.properties b/ui/views/SlidingTabs/SlidingTabsBasic/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..42ae065
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsBasic/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Thu Feb 06 10:46:09 GMT 2014
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=http\://services.gradle.org/distributions/gradle-1.10-all.zip
diff --git a/ui/views/SlidingTabs/SlidingTabsBasic/gradlew b/ui/views/SlidingTabs/SlidingTabsBasic/gradlew
new file mode 100755
index 0000000..91a7e26
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsBasic/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/ui/views/SlidingTabs/SlidingTabsBasic/gradlew.bat b/ui/views/SlidingTabs/SlidingTabsBasic/gradlew.bat
new file mode 100644
index 0000000..aec9973
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsBasic/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/ui/views/SlidingTabs/SlidingTabsBasic/settings.gradle b/ui/views/SlidingTabs/SlidingTabsBasic/settings.gradle
new file mode 100644
index 0000000..4accfbd
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsBasic/settings.gradle
@@ -0,0 +1,4 @@
+
+
+
+include 'SlidingTabsBasicSample'
diff --git a/ui/views/SlidingTabs/SlidingTabsBasic/template-params.xml b/ui/views/SlidingTabs/SlidingTabsBasic/template-params.xml
new file mode 100644
index 0000000..7d6c97f
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsBasic/template-params.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+
+
+<sample>
+ <name>SlidingTabsBasic</name>
+ <group>UI</group>
+ <package>com.example.android.slidingtabsbasic</package>
+
+ <!-- change minSdk if needed-->
+ <minSdk>4</minSdk>
+
+
+ <strings>
+ <intro>
+ <![CDATA[
+ A basic sample which shows how to use SlidingTabLayout to display a custom
+ ViewPager title strip which gives continuous feedback to the user when scrolling.
+ ]]>
+ </intro>
+ </strings>
+
+ <template src="base"/>
+ <template src="FragmentView"/>
+ <common src="logger"/>
+ <common src="activities"/>
+ <common src="view"/>
+
+</sample>
diff --git a/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/.gitignore b/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/README-fragmentview.txt b/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/README-fragmentview.txt
new file mode 100644
index 0000000..38d903f
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/README-fragmentview.txt
@@ -0,0 +1,37 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+Steps to implement FragmentView template:
+-in template-params.xml.ftl:
+ -add the following line to common imports
+ <common src="activities"/>
+
+-Add a Fragment to show behavior. In your MainActivity.java class, it will reference a Fragment
+ called (yourProjectName)Fragment.java. Create that file in your project, using the "main" source
+ folder instead of "common" or "templates".
+ For instance, if your package name is com.example.foo, create the file
+ src/main/java/com/example/foo/FooFragment.java
+
+
+-Within this fragment, make sure that the onCreate method has the line
+ "setHasOptionsMenu(true);", to enable the fragment to handle menu events.
+
+-In order to override menu events, override onOptionsItemSelected.
+
+-refer to sampleSamples/fragmentViewSample for a reference implementation of a
+project built on this template.
+
+
diff --git a/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/proguard-project.txt b/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/proguard-project.txt
new file mode 100644
index 0000000..0d8f171
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/proguard-project.txt
@@ -0,0 +1,20 @@
+ To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/src/main/AndroidManifest.xml b/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..d59dbaa
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/src/main/AndroidManifest.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.slidingtabscolors"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="17" />
+
+ <application android:allowBackup="true"
+ android:label="@string/app_name"
+ android:icon="@drawable/ic_launcher"
+ android:theme="@style/AppTheme">
+
+ <activity android:name=".MainActivity"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+
+</manifest>
diff --git a/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/src/main/java/com/example/android/slidingtabscolors/ContentFragment.java b/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/src/main/java/com/example/android/slidingtabscolors/ContentFragment.java
new file mode 100644
index 0000000..6dadcd2
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/src/main/java/com/example/android/slidingtabscolors/ContentFragment.java
@@ -0,0 +1,64 @@
+package com.example.android.slidingtabscolors;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+/**
+ * Simple Fragment used to display some meaningful for each page in the sample's
+ * {@link android.support.v4.view.ViewPager}.
+ */
+public class ContentFragment extends Fragment {
+
+ private static final String KEY_TITLE = "title";
+ private static final String KEY_INDICATOR_COLOR = "indicator_color";
+ private static final String KEY_DIVIDER_COLOR = "divider_color";
+
+ /**
+ * @return a new instance of {@link ContentFragment}, adding the parameters into a bundle and
+ * setting them as arguments.
+ */
+ public static ContentFragment newInstance(CharSequence title, int indicatorColor,
+ int dividerColor) {
+ Bundle bundle = new Bundle();
+ bundle.putCharSequence(KEY_TITLE, title);
+ bundle.putInt(KEY_INDICATOR_COLOR, indicatorColor);
+ bundle.putInt(KEY_DIVIDER_COLOR, dividerColor);
+
+ ContentFragment fragment = new ContentFragment();
+ fragment.setArguments(bundle);
+
+ return fragment;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.pager_item, container, false);
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+
+ Bundle args = getArguments();
+
+ if (args != null) {
+ TextView title = (TextView) view.findViewById(R.id.item_title);
+ title.setText("Title: " + args.getCharSequence(KEY_TITLE));
+
+ int indicatorColor = args.getInt(KEY_INDICATOR_COLOR);
+ TextView indicatorColorView = (TextView) view.findViewById(R.id.item_indicator_color);
+ indicatorColorView.setText("Indicator: " + Integer.toHexString(indicatorColor));
+ indicatorColorView.setTextColor(indicatorColor);
+
+ int dividerColor = args.getInt(KEY_DIVIDER_COLOR);
+ TextView dividerColorView = (TextView) view.findViewById(R.id.item_divider_color);
+ dividerColorView.setText("Divider: " + Integer.toHexString(dividerColor));
+ dividerColorView.setTextColor(dividerColor);
+ }
+ }
+}
diff --git a/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/src/main/java/com/example/android/slidingtabscolors/SlidingTabsColorsFragment.java b/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/src/main/java/com/example/android/slidingtabscolors/SlidingTabsColorsFragment.java
new file mode 100644
index 0000000..e27ad3e
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/src/main/java/com/example/android/slidingtabscolors/SlidingTabsColorsFragment.java
@@ -0,0 +1,223 @@
+package com.example.android.slidingtabscolors;
+
+import com.example.android.common.view.SlidingTabLayout;
+
+import android.graphics.Color;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentPagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A basic sample which shows how to use {@link com.example.android.common.view.SlidingTabLayout}
+ * to display a custom {@link ViewPager} title strip which gives continuous feedback to the user
+ * when scrolling.
+ */
+public class SlidingTabsColorsFragment extends Fragment {
+
+ /**
+ * This class represents a tab to be displayed by {@link ViewPager} and it's associated
+ * {@link SlidingTabLayout}.
+ */
+ static class SamplePagerItem {
+ private final CharSequence mTitle;
+ private final int mIndicatorColor;
+ private final int mDividerColor;
+
+ SamplePagerItem(CharSequence title, int indicatorColor, int dividerColor) {
+ mTitle = title;
+ mIndicatorColor = indicatorColor;
+ mDividerColor = dividerColor;
+ }
+
+ /**
+ * @return A new {@link Fragment} to be displayed by a {@link ViewPager}
+ */
+ Fragment createFragment() {
+ return ContentFragment.newInstance(mTitle, mIndicatorColor, mDividerColor);
+ }
+
+ /**
+ * @return the title which represents this tab. In this sample this is used directly by
+ * {@link android.support.v4.view.PagerAdapter#getPageTitle(int)}
+ */
+ CharSequence getTitle() {
+ return mTitle;
+ }
+
+ /**
+ * @return the color to be used for indicator on the {@link SlidingTabLayout}
+ */
+ int getIndicatorColor() {
+ return mIndicatorColor;
+ }
+
+ /**
+ * @return the color to be used for right divider on the {@link SlidingTabLayout}
+ */
+ int getDividerColor() {
+ return mDividerColor;
+ }
+ }
+
+ static final String LOG_TAG = "SlidingTabsColorsFragment";
+
+ /**
+ * A custom {@link ViewPager} title strip which looks much like Tabs present in Android v4.0 and
+ * above, but is designed to give continuous feedback to the user when scrolling.
+ */
+ private SlidingTabLayout mSlidingTabLayout;
+
+ /**
+ * A {@link ViewPager} which will be used in conjunction with the {@link SlidingTabLayout} above.
+ */
+ private ViewPager mViewPager;
+
+ /**
+ * List of {@link SamplePagerItem} which represent this sample's tabs.
+ */
+ private List<SamplePagerItem> mTabs = new ArrayList<SamplePagerItem>();
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // BEGIN_INCLUDE (populate_tabs)
+ /**
+ * Populate our tab list with tabs. Each item contains a title, indicator color and divider
+ * color, which are used by {@link SlidingTabLayout}.
+ */
+ mTabs.add(new SamplePagerItem(
+ getString(R.string.tab_stream), // Title
+ Color.BLUE, // Indicator color
+ Color.GRAY // Divider color
+ ));
+
+ mTabs.add(new SamplePagerItem(
+ getString(R.string.tab_messages), // Title
+ Color.RED, // Indicator color
+ Color.GRAY // Divider color
+ ));
+
+ mTabs.add(new SamplePagerItem(
+ getString(R.string.tab_photos), // Title
+ Color.YELLOW, // Indicator color
+ Color.GRAY // Divider color
+ ));
+
+ mTabs.add(new SamplePagerItem(
+ getString(R.string.tab_notifications), // Title
+ Color.GREEN, // Indicator color
+ Color.GRAY // Divider color
+ ));
+ // END_INCLUDE (populate_tabs)
+ }
+
+ /**
+ * Inflates the {@link View} which will be displayed by this {@link Fragment}, from the app's
+ * resources.
+ */
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.fragment_sample, container, false);
+ }
+
+ // BEGIN_INCLUDE (fragment_onviewcreated)
+ /**
+ * This is called after the {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)} has finished.
+ * Here we can pick out the {@link View}s we need to configure from the content view.
+ *
+ * We set the {@link ViewPager}'s adapter to be an instance of
+ * {@link SampleFragmentPagerAdapter}. The {@link SlidingTabLayout} is then given the
+ * {@link ViewPager} so that it can populate itself.
+ *
+ * @param view View created in {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}
+ */
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ // BEGIN_INCLUDE (setup_viewpager)
+ // Get the ViewPager and set it's PagerAdapter so that it can display items
+ mViewPager = (ViewPager) view.findViewById(R.id.viewpager);
+ mViewPager.setAdapter(new SampleFragmentPagerAdapter(getChildFragmentManager()));
+ // END_INCLUDE (setup_viewpager)
+
+ // BEGIN_INCLUDE (setup_slidingtablayout)
+ // Give the SlidingTabLayout the ViewPager, this must be done AFTER the ViewPager has had
+ // it's PagerAdapter set.
+ mSlidingTabLayout = (SlidingTabLayout) view.findViewById(R.id.sliding_tabs);
+ mSlidingTabLayout.setViewPager(mViewPager);
+
+ // BEGIN_INCLUDE (tab_colorizer)
+ // Set a TabColorizer to customize the indicator and divider colors. Here we just retrieve
+ // the tab at the position, and return it's set color
+ mSlidingTabLayout.setCustomTabColorizer(new SlidingTabLayout.TabColorizer() {
+
+ @Override
+ public int getIndicatorColor(int position) {
+ return mTabs.get(position).getIndicatorColor();
+ }
+
+ @Override
+ public int getDividerColor(int position) {
+ return mTabs.get(position).getDividerColor();
+ }
+
+ });
+ // END_INCLUDE (tab_colorizer)
+ // END_INCLUDE (setup_slidingtablayout)
+ }
+ // END_INCLUDE (fragment_onviewcreated)
+
+ /**
+ * The {@link FragmentPagerAdapter} used to display pages in this sample. The individual pages
+ * are instances of {@link ContentFragment} which just display three lines of text. Each page is
+ * created by the relevant {@link SamplePagerItem} for the requested position.
+ * <p>
+ * The important section of this class is the {@link #getPageTitle(int)} method which controls
+ * what is displayed in the {@link SlidingTabLayout}.
+ */
+ class SampleFragmentPagerAdapter extends FragmentPagerAdapter {
+
+ SampleFragmentPagerAdapter(FragmentManager fm) {
+ super(fm);
+ }
+
+ /**
+ * Return the {@link android.support.v4.app.Fragment} to be displayed at {@code position}.
+ * <p>
+ * Here we return the value returned from {@link SamplePagerItem#createFragment()}.
+ */
+ @Override
+ public Fragment getItem(int i) {
+ return mTabs.get(i).createFragment();
+ }
+
+ @Override
+ public int getCount() {
+ return mTabs.size();
+ }
+
+ // BEGIN_INCLUDE (pageradapter_getpagetitle)
+ /**
+ * Return the title of the item at {@code position}. This is important as what this method
+ * returns is what is displayed in the {@link SlidingTabLayout}.
+ * <p>
+ * Here we return the value returned from {@link SamplePagerItem#getTitle()}.
+ */
+ @Override
+ public CharSequence getPageTitle(int position) {
+ return mTabs.get(position).getTitle();
+ }
+ // END_INCLUDE (pageradapter_getpagetitle)
+
+ }
+
+}
\ No newline at end of file
diff --git a/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/src/main/res/drawable-hdpi/ic_launcher.png b/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..b1efaf4
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/src/main/res/drawable-mdpi/ic_launcher.png b/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..f5f9244
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/src/main/res/drawable-xhdpi/ic_launcher.png b/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..5d07b3f
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/src/main/res/drawable-xxhdpi/ic_launcher.png b/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..6ef21e1
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/src/main/res/layout/fragment_sample.xml b/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/src/main/res/layout/fragment_sample.xml
new file mode 100644
index 0000000..605cba7
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/src/main/res/layout/fragment_sample.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <com.example.android.common.view.SlidingTabLayout
+ android:id="@+id/sliding_tabs"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+ <android.support.v4.view.ViewPager
+ android:id="@+id/viewpager"
+ android:layout_width="match_parent"
+ android:layout_height="0px"
+ android:layout_weight="1"
+ android:background="@android:color/white" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/src/main/res/layout/pager_item.xml b/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/src/main/res/layout/pager_item.xml
new file mode 100644
index 0000000..039ceb1
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/src/main/res/layout/pager_item.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:gravity="center">
+
+ <TextView
+ android:id="@+id/item_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceLarge" />
+
+ <TextView
+ android:id="@+id/item_indicator_color"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceLarge" />
+
+ <TextView
+ android:id="@+id/item_divider_color"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceLarge" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/src/main/res/values/strings.xml b/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/src/main/res/values/strings.xml
new file mode 100644
index 0000000..e1b0846
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/src/main/res/values/strings.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="tab_stream">Stream</string>
+ <string name="tab_messages">Messages</string>
+ <string name="tab_notifications">Notifications</string>
+ <string name="tab_photos">Photos</string>
+
+</resources>
\ No newline at end of file
diff --git a/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/tests/AndroidManifest.xml b/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/tests/AndroidManifest.xml
new file mode 100644
index 0000000..beedf00
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/tests/AndroidManifest.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+
+
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<!-- package name must be unique so suffix with "tests" so package loader doesn't ignore us -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.slidingtabscolors.tests"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <uses-sdk
+ android:minSdkVersion="18"
+ android:targetSdkVersion="19" />
+
+ <!-- We add an application tag here just so that we can indicate that
+ this package needs to link against the android.test library,
+ which is needed when building test cases. -->
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <!--
+ Specifies the instrumentation test runner used to run the tests.
+ -->
+ <instrumentation
+ android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.example.android.slidingtabscolors"
+ android:label="Tests for com.example.android.slidingtabscolors" />
+
+</manifest>
\ No newline at end of file
diff --git a/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/tests/src/com/example/android/slidingtabscolors/tests/SampleTests.java b/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/tests/src/com/example/android/slidingtabscolors/tests/SampleTests.java
new file mode 100644
index 0000000..caab5d8
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsColors/SlidingTabsColorsSample/tests/src/com/example/android/slidingtabscolors/tests/SampleTests.java
@@ -0,0 +1,79 @@
+/*
+* Copyright 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+
+
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package com.example.android.slidingtabscolors.tests;
+
+import com.example.android.slidingtabscolors.*;
+
+import android.test.ActivityInstrumentationTestCase2;
+
+/**
+* Tests for SlidingTabsColors sample.
+*/
+public class SampleTests extends ActivityInstrumentationTestCase2<MainActivity> {
+
+ private MainActivity mTestActivity;
+ private SlidingTabsColorsFragment mTestFragment;
+
+ public SampleTests() {
+ super(MainActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // Starts the activity under test using the default Intent with:
+ // action = {@link Intent#ACTION_MAIN}
+ // flags = {@link Intent#FLAG_ACTIVITY_NEW_TASK}
+ // All other fields are null or empty.
+ mTestActivity = getActivity();
+ mTestFragment = (SlidingTabsColorsFragment)
+ mTestActivity.getSupportFragmentManager().getFragments().get(1);
+ }
+
+ /**
+ * Test if the test fixture has been set up correctly.
+ */
+ public void testPreconditions() {
+ //Try to add a message to add context to your assertions. These messages will be shown if
+ //a tests fails and make it easy to understand why a test failed
+ assertNotNull("mTestActivity is null", mTestActivity);
+ assertNotNull("mTestFragment is null", mTestFragment);
+ }
+
+ /**
+ * Add more tests below.
+ */
+
+}
\ No newline at end of file
diff --git a/ui/views/SlidingTabs/SlidingTabsColors/build.gradle b/ui/views/SlidingTabs/SlidingTabsColors/build.gradle
new file mode 100644
index 0000000..cda9c5c
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsColors/build.gradle
@@ -0,0 +1,14 @@
+
+
+
+
+// BEGIN_EXCLUDE
+import com.example.android.samples.build.SampleGenPlugin
+apply plugin: SampleGenPlugin
+
+samplegen {
+ pathToBuild "../../../../../../build"
+ pathToSamplesCommon "../../../../common"
+}
+apply from: "../../../../../../build/build.gradle"
+// END_EXCLUDE
diff --git a/ui/views/SlidingTabs/SlidingTabsColors/buildSrc/build.gradle b/ui/views/SlidingTabs/SlidingTabsColors/buildSrc/build.gradle
new file mode 100644
index 0000000..81f445f
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsColors/buildSrc/build.gradle
@@ -0,0 +1,18 @@
+
+
+
+repositories {
+ mavenCentral()
+}
+dependencies {
+ compile 'org.freemarker:freemarker:2.3.20'
+}
+
+sourceSets {
+ main {
+ groovy {
+ srcDir new File(rootDir, "../../../../../../../build/buildSrc/src/main/groovy")
+ }
+ }
+}
+
diff --git a/ui/views/SlidingTabs/SlidingTabsColors/gradle/wrapper/gradle-wrapper.jar b/ui/views/SlidingTabs/SlidingTabsColors/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..8c0fb64
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsColors/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/ui/views/SlidingTabs/SlidingTabsColors/gradle/wrapper/gradle-wrapper.properties b/ui/views/SlidingTabs/SlidingTabsColors/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..861eddc
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsColors/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Apr 10 15:27:10 PDT 2013
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=http\://services.gradle.org/distributions/gradle-1.8-bin.zip
diff --git a/ui/views/SlidingTabs/SlidingTabsColors/gradlew b/ui/views/SlidingTabs/SlidingTabsColors/gradlew
new file mode 100755
index 0000000..91a7e26
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsColors/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/ui/views/SlidingTabs/SlidingTabsColors/gradlew.bat b/ui/views/SlidingTabs/SlidingTabsColors/gradlew.bat
new file mode 100644
index 0000000..aec9973
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsColors/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/ui/views/SlidingTabs/SlidingTabsColors/settings.gradle b/ui/views/SlidingTabs/SlidingTabsColors/settings.gradle
new file mode 100644
index 0000000..3c5586a
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsColors/settings.gradle
@@ -0,0 +1,4 @@
+
+
+
+include 'SlidingTabsColorsSample'
diff --git a/ui/views/SlidingTabs/SlidingTabsColors/template-params.xml b/ui/views/SlidingTabs/SlidingTabsColors/template-params.xml
new file mode 100644
index 0000000..091af61
--- /dev/null
+++ b/ui/views/SlidingTabs/SlidingTabsColors/template-params.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+
+
+<sample>
+ <name>SlidingTabsColors</name>
+ <group>NoGroup</group>
+ <package>com.example.android.slidingtabscolors</package>
+
+
+ <!-- change minSdk if needed-->
+ <minSdk>4</minSdk>
+
+
+ <strings>
+ <intro>
+ <![CDATA[
+ A more advanced sample which shows how to use SlidingTabLayout to display a custom
+ ViewPager title strip, with custom coloring for each tab.
+ ]]>
+ </intro>
+ </strings>
+
+ <template src="base"/>
+ <template src="FragmentView"/>
+ <common src="logger"/>
+ <common src="activities"/>
+ <common src="view"/>
+
+</sample>