am 6e21ec3f: am 9811d58e: Merge "Add the "Abort message:" line to the preserved stack output."
* commit '6e21ec3fc9df759c1dd61408247847547f3501da':
Add the "Abort message:" line to the preserved stack output.
diff --git a/build/Android.mk b/build/Android.mk
index f8578d2..117e3e0 100644
--- a/build/Android.mk
+++ b/build/Android.mk
@@ -139,11 +139,14 @@
endef
ANDROID_SUPPORT_LIBRARIES := \
+ android-support-annotations \
android-support-v4 \
android-support-v7-gridlayout \
android-support-v7-appcompat \
android-support-v7-mediarouter \
- android-support-v13
+ android-support-v7-recyclerview \
+ android-support-v13 \
+ android-support-v17-leanback
$(foreach lib, $(ANDROID_SUPPORT_LIBRARIES), $(eval $(call _package_sdk_library,$(lib))))
diff --git a/build/sdk.atree b/build/sdk.atree
index 91442be..dbc8a0c 100644
--- a/build/sdk.atree
+++ b/build/sdk.atree
@@ -170,8 +170,7 @@
docs/features.txt platforms/${PLATFORM_NAME}/data/features.txt
# fonts for layoutlib.
-frameworks/base/data/fonts platforms/${PLATFORM_NAME}/data/fonts
-external/noto-fonts platforms/${PLATFORM_NAME}/data/fonts
+${FONT_OUT} platforms/${PLATFORM_NAME}/data/fonts
# NOTICE files are copied by build/core/Makefile from sdk.git
development/sdk/sdk_files_NOTICE.txt platforms/${PLATFORM_NAME}/templates/NOTICE.txt
@@ -264,10 +263,13 @@
developers/build/prebuilts/gradle/DisplayingBitmaps samples/${PLATFORM_NAME}/ui/DisplayingBitmaps
developers/build/prebuilts/gradle/BasicTransition samples/${PLATFORM_NAME}/ui/BasicTransition
developers/build/prebuilts/gradle/AdapterTransition samples/${PLATFORM_NAME}/ui/AdapterTransition
+developers/build/prebuilts/gradle/CustomTransition samples/${PLATFORM_NAME}/ui/CustomTransition
+developers/build/prebuilts/gradle/FragmentTransition samples/${PLATFORM_NAME}/ui/FragmentTransition
+developers/build/prebuilts/gradle/SwipeRefreshLayoutBasic samples/${PLATFORM_NAME}/ui/SwipeRefreshLayoutBasic
+developers/build/prebuilts/gradle/SwipeRefreshListFragment samples/${PLATFORM_NAME}/ui/SwipeRefreshListFragment
+developers/build/prebuilts/gradle/SwipeRefreshMultipleViews samples/${PLATFORM_NAME}/ui/SwipeRefreshMultipleViews
developers/build/prebuilts/gradle/MediaRouter samples/${PLATFORM_NAME}/media/MediaRouter
-
-
# Old sample tree
development/samples/AccelerometerPlay samples/${PLATFORM_NAME}/legacy/AccelerometerPlay
development/samples/ActionBarCompat samples/${PLATFORM_NAME}/legacy/ActionBarCompat
@@ -337,6 +339,8 @@
development/sdk/support_README.txt extras/android/support/README.txt
development/sdk/sdk_files_NOTICE.txt extras/android/support/NOTICE.txt
+${OUT_DIR}/target/common/obj/PACKAGING/android-support-annotations_intermediates/android-support-annotations.jar extras/android/support/annotations/android-support-annotations.jar
+
${OUT_DIR}/target/common/obj/PACKAGING/android-support-v4_intermediates/android-support-v4.jar extras/android/support/v4/android-support-v4.jar
frameworks/support/v4 extras/android/support/v4/src
development/samples/Support4Demos extras/android/support/samples/Support4Demos
@@ -380,5 +384,6 @@
# Tests Component
##############################################################################
framework/layoutlib-tests.jar tests/libtests/layoutlib-tests.jar
-system/app/EmulatorSmokeTests.apk tests/emulator-test-apps/EmulatorSmokeTests.apk
+system/app/ConnectivityTest.apk tests/emulator-test-apps/ConnectivityTest.apk
+system/app/GpsLocationTest.apk tests/emulator-test-apps/GpsLocationTest.apk
diff --git a/ide/eclipse/.classpath b/ide/eclipse/.classpath
index dda0606..af99325 100644
--- a/ide/eclipse/.classpath
+++ b/ide/eclipse/.classpath
@@ -65,7 +65,12 @@
<classpathentry kind="src" path="frameworks/base/packages/SystemUI/src"/>
<classpathentry kind="src" path="frameworks/base/policy/src"/>
<classpathentry kind="src" path="frameworks/base/sax/java"/>
- <classpathentry kind="src" path="frameworks/base/services/java"/>
+ <classpathentry kind="src" path="frameworks/base/services/core/java"/>
+ <classpathentry kind="src" path="frameworks/base/services/accessibility/java"/>
+ <classpathentry kind="src" path="frameworks/base/services/print/java"/>
+ <classpathentry kind="src" path="frameworks/base/services/backup/java"/>
+ <classpathentry kind="src" path="frameworks/base/services/devicepolicy/java"/>
+ <classpathentry kind="src" path="frameworks/base/services/appwidget/java"/>
<classpathentry kind="src" path="frameworks/base/telephony/java"/>
<classpathentry kind="src" path="frameworks/base/test-runner/src"/>
<classpathentry kind="src" path="frameworks/base/wifi/java"/>
diff --git a/samples/BluetoothChat/AndroidManifest.xml b/samples/BluetoothChat/AndroidManifest.xml
index 895e633..4726670 100644
--- a/samples/BluetoothChat/AndroidManifest.xml
+++ b/samples/BluetoothChat/AndroidManifest.xml
@@ -17,7 +17,7 @@
package="com.example.android.BluetoothChat"
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk minSdkVersion="6" />
+ <uses-sdk android:minSdkVersion="11" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" />
diff --git a/samples/Support7Demos/Android.mk b/samples/Support7Demos/Android.mk
index 0e43e3d..ca8310f 100644
--- a/samples/Support7Demos/Android.mk
+++ b/samples/Support7Demos/Android.mk
@@ -26,7 +26,8 @@
android-support-v4 \
android-support-v7-appcompat \
android-support-v7-gridlayout \
- android-support-v7-mediarouter
+ android-support-v7-mediarouter \
+ android-support-v7-recyclerview
LOCAL_RESOURCE_DIR = \
$(LOCAL_PATH)/res \
frameworks/support/v7/appcompat/res \
diff --git a/samples/Support7Demos/AndroidManifest.xml b/samples/Support7Demos/AndroidManifest.xml
index 4735433..6f9b237 100644
--- a/samples/Support7Demos/AndroidManifest.xml
+++ b/samples/Support7Demos/AndroidManifest.xml
@@ -38,6 +38,7 @@
android:compatibleWidthLimitDp="480" />
<application android:label="@string/activity_sample_code"
+ android:supportsRtl="true"
android:icon="@drawable/app_sample_code"
android:hardwareAccelerated="true">
@@ -172,5 +173,33 @@
</intent-filter>
</activity>
+ <!-- RecyclerView samples -->
+ <activity android:name=".widget.RecyclerViewActivity"
+ android:label="@string/recycler_view"
+ android:theme="@style/Theme.AppCompat">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="com.example.android.supportv7.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".widget.AnimatedRecyclerView"
+ android:label="@string/animated_recycler_view"
+ android:theme="@style/Theme.AppCompat">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="com.example.android.supportv7.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".widget.LinearLayoutManagerActivity"
+ android:label="@string/linear_layout_manager"
+ android:theme="@style/Theme.AppCompat">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="com.example.android.supportv7.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
</application>
</manifest>
diff --git a/samples/Support7Demos/res/layout/activity_linear_layout_manager.xml b/samples/Support7Demos/res/layout/activity_linear_layout_manager.xml
new file mode 100644
index 0000000..d671c73
--- /dev/null
+++ b/samples/Support7Demos/res/layout/activity_linear_layout_manager.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+ <EditText
+ android:id="@+id/scroll_offset"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:inputType="numberSigned"
+ android:hint="offset"/>
+ <Spinner
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/spinner"/>
+ <CheckBox
+ android:id="@+id/enable_smooth_scroll"
+ android:text="smooth scroll"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+ </LinearLayout>
+
+ <android.support.v7.widget.RecyclerView
+ android:layout_width="fill_parent"
+ android:layout_height="60dp"
+ android:scrollbars="horizontal"
+ android:id="@+id/config_recycler_view"/>
+ <android.support.v7.widget.RecyclerView
+ android:background="#ff0099cc"
+ android:scrollbarStyle="insideOverlay"
+ android:scrollbars="horizontal|vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:id="@+id/recycler_view"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/samples/Support7Demos/res/layout/animated_recycler_view.xml b/samples/Support7Demos/res/layout/animated_recycler_view.xml
new file mode 100644
index 0000000..188a154
--- /dev/null
+++ b/samples/Support7Demos/res/layout/animated_recycler_view.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <CheckBox
+ android:id="@+id/enableAnimations"
+ android:checked="true"
+ android:text="@string/enableAnimations"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <Button
+ android:id="@+id/deleteButton"
+ android:layout_weight=".5"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:onClick="deleteItem"
+ android:text="@string/delete_item"/>
+
+ <Button
+ android:layout_weight=".5"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:onClick="addItem"
+ android:text="@string/add_item"/>
+
+ <Button
+ android:layout_weight=".5"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:onClick="addDeleteItem"
+ android:text="@string/add_delete_item"/>
+
+ <Button
+ android:layout_weight=".5"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:onClick="deleteAddItem"
+ android:text="@string/delete_add_item"/>
+
+ <Button
+ android:layout_weight=".5"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:onClick="d1a2d3"
+ android:text="@string/d1a2d3"/>
+
+ </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/samples/Support7Demos/res/layout/selectable_item.xml b/samples/Support7Demos/res/layout/selectable_item.xml
new file mode 100644
index 0000000..65a23cc
--- /dev/null
+++ b/samples/Support7Demos/res/layout/selectable_item.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <CheckBox
+ android:id="@+id/selected"
+ android:onClick="checkboxClicked"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+
+ <TextView
+ android:id="@+id/text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/samples/Support7Demos/res/values/strings.xml b/samples/Support7Demos/res/values/strings.xml
index 1b13623..7e4e03c 100644
--- a/samples/Support7Demos/res/values/strings.xml
+++ b/samples/Support7Demos/res/values/strings.xml
@@ -95,4 +95,18 @@
<string name="sample_media_route_activity_local">Local Playback</string>
<string name="sample_media_route_activity_presentation">Local Playback on Presentation Display</string>
+ <string name="recycler_view">RecyclerView/RecyclerViewActivity</string>
+ <string name="animated_recycler_view">RecyclerView/AnimatedRecyclerView</string>
+ <string name="linear_layout_manager">Linear Layout Manager</string>
+ <string name="checkbox_orientation">Horz.</string>
+ <string name="checkbox_reverse">Rev.</string>
+ <string name="checkbox_layout_dir">Layout Dir</string>
+ <string name="checkbox_stack_from_end">Stack From End</string>
+ <string name="enableAnimations">Animate Changes</string>
+ <string name="add_item">Add</string>
+ <string name="delete_item">Delete</string>
+ <string name="add_delete_item">A+D</string>
+ <string name="delete_add_item">D+A</string>
+ <string name="d1a2d3">d1a2d3</string>
+
</resources>
diff --git a/samples/Support7Demos/src/com/example/android/supportv7/Cheeses.java b/samples/Support7Demos/src/com/example/android/supportv7/Cheeses.java
new file mode 100644
index 0000000..a66b1d6
--- /dev/null
+++ b/samples/Support7Demos/src/com/example/android/supportv7/Cheeses.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2011 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.supportv7;
+
+public class Cheeses {
+
+ public static final String[] sCheeseStrings = {
+ "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi",
+ "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale",
+ "Aisy Cendre", "Allgauer Emmentaler", "Alverca", "Ambert", "American Cheese",
+ "Ami du Chambertin", "Anejo Enchilado", "Anneau du Vic-Bilh", "Anthoriro", "Appenzell",
+ "Aragon", "Ardi Gasna", "Ardrahan", "Armenian String", "Aromes au Gene de Marc",
+ "Asadero", "Asiago", "Aubisque Pyrenees", "Autun", "Avaxtskyr", "Baby Swiss",
+ "Babybel", "Baguette Laonnaise", "Bakers", "Baladi", "Balaton", "Bandal", "Banon",
+ "Barry's Bay Cheddar", "Basing", "Basket Cheese", "Bath Cheese", "Bavarian Bergkase",
+ "Baylough", "Beaufort", "Beauvoorde", "Beenleigh Blue", "Beer Cheese", "Bel Paese",
+ "Bergader", "Bergere Bleue", "Berkswell", "Beyaz Peynir", "Bierkase", "Bishop Kennedy",
+ "Blarney", "Bleu d'Auvergne", "Bleu de Gex", "Bleu de Laqueuille",
+ "Bleu de Septmoncel", "Bleu Des Causses", "Blue", "Blue Castello", "Blue Rathgore",
+ "Blue Vein (Australian)", "Blue Vein Cheeses", "Bocconcini", "Bocconcini (Australian)",
+ "Boeren Leidenkaas", "Bonchester", "Bosworth", "Bougon", "Boule Du Roves",
+ "Boulette d'Avesnes", "Boursault", "Boursin", "Bouyssou", "Bra", "Braudostur",
+ "Breakfast Cheese", "Brebis du Lavort", "Brebis du Lochois", "Brebis du Puyfaucon",
+ "Bresse Bleu", "Brick", "Brie", "Brie de Meaux", "Brie de Melun", "Brillat-Savarin",
+ "Brin", "Brin d' Amour", "Brin d'Amour", "Brinza (Burduf Brinza)",
+ "Briquette de Brebis", "Briquette du Forez", "Broccio", "Broccio Demi-Affine",
+ "Brousse du Rove", "Bruder Basil", "Brusselae Kaas (Fromage de Bruxelles)", "Bryndza",
+ "Buchette d'Anjou", "Buffalo", "Burgos", "Butte", "Butterkase", "Button (Innes)",
+ "Buxton Blue", "Cabecou", "Caboc", "Cabrales", "Cachaille", "Caciocavallo", "Caciotta",
+ "Caerphilly", "Cairnsmore", "Calenzana", "Cambazola", "Camembert de Normandie",
+ "Canadian Cheddar", "Canestrato", "Cantal", "Caprice des Dieux", "Capricorn Goat",
+ "Capriole Banon", "Carre de l'Est", "Casciotta di Urbino", "Cashel Blue", "Castellano",
+ "Castelleno", "Castelmagno", "Castelo Branco", "Castigliano", "Cathelain",
+ "Celtic Promise", "Cendre d'Olivet", "Cerney", "Chabichou", "Chabichou du Poitou",
+ "Chabis de Gatine", "Chaource", "Charolais", "Chaumes", "Cheddar",
+ "Cheddar Clothbound", "Cheshire", "Chevres", "Chevrotin des Aravis", "Chontaleno",
+ "Civray", "Coeur de Camembert au Calvados", "Coeur de Chevre", "Colby", "Cold Pack",
+ "Comte", "Coolea", "Cooleney", "Coquetdale", "Corleggy", "Cornish Pepper",
+ "Cotherstone", "Cotija", "Cottage Cheese", "Cottage Cheese (Australian)",
+ "Cougar Gold", "Coulommiers", "Coverdale", "Crayeux de Roncq", "Cream Cheese",
+ "Cream Havarti", "Crema Agria", "Crema Mexicana", "Creme Fraiche", "Crescenza",
+ "Croghan", "Crottin de Chavignol", "Crottin du Chavignol", "Crowdie", "Crowley",
+ "Cuajada", "Curd", "Cure Nantais", "Curworthy", "Cwmtawe Pecorino",
+ "Cypress Grove Chevre", "Danablu (Danish Blue)", "Danbo", "Danish Fontina",
+ "Daralagjazsky", "Dauphin", "Delice des Fiouves", "Denhany Dorset Drum", "Derby",
+ "Dessertnyj Belyj", "Devon Blue", "Devon Garland", "Dolcelatte", "Doolin",
+ "Doppelrhamstufel", "Dorset Blue Vinney", "Double Gloucester", "Double Worcester",
+ "Dreux a la Feuille", "Dry Jack", "Duddleswell", "Dunbarra", "Dunlop", "Dunsyre Blue",
+ "Duroblando", "Durrus", "Dutch Mimolette (Commissiekaas)", "Edam", "Edelpilz",
+ "Emental Grand Cru", "Emlett", "Emmental", "Epoisses de Bourgogne", "Esbareich",
+ "Esrom", "Etorki", "Evansdale Farmhouse Brie", "Evora De L'Alentejo", "Exmoor Blue",
+ "Explorateur", "Feta", "Feta (Australian)", "Figue", "Filetta", "Fin-de-Siecle",
+ "Finlandia Swiss", "Finn", "Fiore Sardo", "Fleur du Maquis", "Flor de Guia",
+ "Flower Marie", "Folded", "Folded cheese with mint", "Fondant de Brebis",
+ "Fontainebleau", "Fontal", "Fontina Val d'Aosta", "Formaggio di capra", "Fougerus",
+ "Four Herb Gouda", "Fourme d' Ambert", "Fourme de Haute Loire", "Fourme de Montbrison",
+ "Fresh Jack", "Fresh Mozzarella", "Fresh Ricotta", "Fresh Truffles", "Fribourgeois",
+ "Friesekaas", "Friesian", "Friesla", "Frinault", "Fromage a Raclette", "Fromage Corse",
+ "Fromage de Montagne de Savoie", "Fromage Frais", "Fruit Cream Cheese",
+ "Frying Cheese", "Fynbo", "Gabriel", "Galette du Paludier", "Galette Lyonnaise",
+ "Galloway Goat's Milk Gems", "Gammelost", "Gaperon a l'Ail", "Garrotxa", "Gastanberra",
+ "Geitost", "Gippsland Blue", "Gjetost", "Gloucester", "Golden Cross", "Gorgonzola",
+ "Gornyaltajski", "Gospel Green", "Gouda", "Goutu", "Gowrie", "Grabetto", "Graddost",
+ "Grafton Village Cheddar", "Grana", "Grana Padano", "Grand Vatel",
+ "Grataron d' Areches", "Gratte-Paille", "Graviera", "Greuilh", "Greve",
+ "Gris de Lille", "Gruyere", "Gubbeen", "Guerbigny", "Halloumi",
+ "Halloumy (Australian)", "Haloumi-Style Cheese", "Harbourne Blue", "Havarti",
+ "Heidi Gruyere", "Hereford Hop", "Herrgardsost", "Herriot Farmhouse", "Herve",
+ "Hipi Iti", "Hubbardston Blue Cow", "Hushallsost", "Iberico", "Idaho Goatster",
+ "Idiazabal", "Il Boschetto al Tartufo", "Ile d'Yeu", "Isle of Mull", "Jarlsberg",
+ "Jermi Tortes", "Jibneh Arabieh", "Jindi Brie", "Jubilee Blue", "Juustoleipa",
+ "Kadchgall", "Kaseri", "Kashta", "Kefalotyri", "Kenafa", "Kernhem", "Kervella Affine",
+ "Kikorangi", "King Island Cape Wickham Brie", "King River Gold", "Klosterkaese",
+ "Knockalara", "Kugelkase", "L'Aveyronnais", "L'Ecir de l'Aubrac", "La Taupiniere",
+ "La Vache Qui Rit", "Laguiole", "Lairobell", "Lajta", "Lanark Blue", "Lancashire",
+ "Langres", "Lappi", "Laruns", "Lavistown", "Le Brin", "Le Fium Orbo", "Le Lacandou",
+ "Le Roule", "Leafield", "Lebbene", "Leerdammer", "Leicester", "Leyden", "Limburger",
+ "Lincolnshire Poacher", "Lingot Saint Bousquet d'Orb", "Liptauer", "Little Rydings",
+ "Livarot", "Llanboidy", "Llanglofan Farmhouse", "Loch Arthur Farmhouse",
+ "Loddiswell Avondale", "Longhorn", "Lou Palou", "Lou Pevre", "Lyonnais", "Maasdam",
+ "Macconais", "Mahoe Aged Gouda", "Mahon", "Malvern", "Mamirolle", "Manchego",
+ "Manouri", "Manur", "Marble Cheddar", "Marbled Cheeses", "Maredsous", "Margotin",
+ "Maribo", "Maroilles", "Mascares", "Mascarpone", "Mascarpone (Australian)",
+ "Mascarpone Torta", "Matocq", "Maytag Blue", "Meira", "Menallack Farmhouse",
+ "Menonita", "Meredith Blue", "Mesost", "Metton (Cancoillotte)", "Meyer Vintage Gouda",
+ "Mihalic Peynir", "Milleens", "Mimolette", "Mine-Gabhar", "Mini Baby Bells", "Mixte",
+ "Molbo", "Monastery Cheeses", "Mondseer", "Mont D'or Lyonnais", "Montasio",
+ "Monterey Jack", "Monterey Jack Dry", "Morbier", "Morbier Cru de Montagne",
+ "Mothais a la Feuille", "Mozzarella", "Mozzarella (Australian)",
+ "Mozzarella di Bufala", "Mozzarella Fresh, in water", "Mozzarella Rolls", "Munster",
+ "Murol", "Mycella", "Myzithra", "Naboulsi", "Nantais", "Neufchatel",
+ "Neufchatel (Australian)", "Niolo", "Nokkelost", "Northumberland", "Oaxaca",
+ "Olde York", "Olivet au Foin", "Olivet Bleu", "Olivet Cendre",
+ "Orkney Extra Mature Cheddar", "Orla", "Oschtjepka", "Ossau Fermier", "Ossau-Iraty",
+ "Oszczypek", "Oxford Blue", "P'tit Berrichon", "Palet de Babligny", "Paneer", "Panela",
+ "Pannerone", "Pant ys Gawn", "Parmesan (Parmigiano)", "Parmigiano Reggiano",
+ "Pas de l'Escalette", "Passendale", "Pasteurized Processed", "Pate de Fromage",
+ "Patefine Fort", "Pave d'Affinois", "Pave d'Auge", "Pave de Chirac", "Pave du Berry",
+ "Pecorino", "Pecorino in Walnut Leaves", "Pecorino Romano", "Peekskill Pyramid",
+ "Pelardon des Cevennes", "Pelardon des Corbieres", "Penamellera", "Penbryn",
+ "Pencarreg", "Perail de Brebis", "Petit Morin", "Petit Pardou", "Petit-Suisse",
+ "Picodon de Chevre", "Picos de Europa", "Piora", "Pithtviers au Foin",
+ "Plateau de Herve", "Plymouth Cheese", "Podhalanski", "Poivre d'Ane", "Polkolbin",
+ "Pont l'Eveque", "Port Nicholson", "Port-Salut", "Postel", "Pouligny-Saint-Pierre",
+ "Pourly", "Prastost", "Pressato", "Prince-Jean", "Processed Cheddar", "Provolone",
+ "Provolone (Australian)", "Pyengana Cheddar", "Pyramide", "Quark",
+ "Quark (Australian)", "Quartirolo Lombardo", "Quatre-Vents", "Quercy Petit",
+ "Queso Blanco", "Queso Blanco con Frutas --Pina y Mango", "Queso de Murcia",
+ "Queso del Montsec", "Queso del Tietar", "Queso Fresco", "Queso Fresco (Adobera)",
+ "Queso Iberico", "Queso Jalapeno", "Queso Majorero", "Queso Media Luna",
+ "Queso Para Frier", "Queso Quesadilla", "Rabacal", "Raclette", "Ragusano", "Raschera",
+ "Reblochon", "Red Leicester", "Regal de la Dombes", "Reggianito", "Remedou",
+ "Requeson", "Richelieu", "Ricotta", "Ricotta (Australian)", "Ricotta Salata", "Ridder",
+ "Rigotte", "Rocamadour", "Rollot", "Romano", "Romans Part Dieu", "Roncal", "Roquefort",
+ "Roule", "Rouleau De Beaulieu", "Royalp Tilsit", "Rubens", "Rustinu", "Saaland Pfarr",
+ "Saanenkaese", "Saga", "Sage Derby", "Sainte Maure", "Saint-Marcellin",
+ "Saint-Nectaire", "Saint-Paulin", "Salers", "Samso", "San Simon", "Sancerre",
+ "Sap Sago", "Sardo", "Sardo Egyptian", "Sbrinz", "Scamorza", "Schabzieger", "Schloss",
+ "Selles sur Cher", "Selva", "Serat", "Seriously Strong Cheddar", "Serra da Estrela",
+ "Sharpam", "Shelburne Cheddar", "Shropshire Blue", "Siraz", "Sirene", "Smoked Gouda",
+ "Somerset Brie", "Sonoma Jack", "Sottocenare al Tartufo", "Soumaintrain",
+ "Sourire Lozerien", "Spenwood", "Sraffordshire Organic", "St. Agur Blue Cheese",
+ "Stilton", "Stinking Bishop", "String", "Sussex Slipcote", "Sveciaost", "Swaledale",
+ "Sweet Style Swiss", "Swiss", "Syrian (Armenian String)", "Tala", "Taleggio", "Tamie",
+ "Tasmania Highland Chevre Log", "Taupiniere", "Teifi", "Telemea", "Testouri",
+ "Tete de Moine", "Tetilla", "Texas Goat Cheese", "Tibet", "Tillamook Cheddar",
+ "Tilsit", "Timboon Brie", "Toma", "Tomme Brulee", "Tomme d'Abondance",
+ "Tomme de Chevre", "Tomme de Romans", "Tomme de Savoie", "Tomme des Chouans", "Tommes",
+ "Torta del Casar", "Toscanello", "Touree de L'Aubier", "Tourmalet",
+ "Trappe (Veritable)", "Trois Cornes De Vendee", "Tronchon", "Trou du Cru", "Truffe",
+ "Tupi", "Turunmaa", "Tymsboro", "Tyn Grug", "Tyning", "Ubriaco", "Ulloa",
+ "Vacherin-Fribourgeois", "Valencay", "Vasterbottenost", "Venaco", "Vendomois",
+ "Vieux Corse", "Vignotte", "Vulscombe", "Waimata Farmhouse Blue",
+ "Washed Rind Cheese (Australian)", "Waterloo", "Weichkaese", "Wellington",
+ "Wensleydale", "White Stilton", "Whitestone Farmhouse", "Wigmore", "Woodside Cabecou",
+ "Xanadu", "Xynotyro", "Yarg Cornish", "Yarra Valley Pyramid", "Yorkshire Blue",
+ "Zamorano", "Zanetti Grana Padano", "Zanetti Parmigiano Reggiano"
+ };
+
+}
diff --git a/samples/Support7Demos/src/com/example/android/supportv7/widget/AnimatedRecyclerView.java b/samples/Support7Demos/src/com/example/android/supportv7/widget/AnimatedRecyclerView.java
new file mode 100644
index 0000000..83cf4d3
--- /dev/null
+++ b/samples/Support7Demos/src/com/example/android/supportv7/widget/AnimatedRecyclerView.java
@@ -0,0 +1,454 @@
+/*
+ * Copyright (C) 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.supportv7.widget;
+
+import android.widget.CompoundButton;
+import com.example.android.supportv7.R;
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v4.view.MenuItemCompat;
+import android.support.v7.widget.RecyclerView;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CheckBox;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+public class AnimatedRecyclerView extends Activity {
+
+ private static final int SCROLL_DISTANCE = 80; // dp
+
+ private RecyclerView mRecyclerView;
+
+ private int mNumItemsAdded = 0;
+ ArrayList<String> mItems = new ArrayList<String>();
+ MyAdapter mAdapter;
+
+ static final boolean USE_CUSTOM_ANIMATIONS = false;
+
+ boolean mAnimationsEnabled = true;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.animated_recycler_view);
+
+ ViewGroup container = (ViewGroup) findViewById(R.id.container);
+ mRecyclerView = new RecyclerView(this);
+ mRecyclerView.setLayoutManager(new MyLayoutManager(this));
+ mRecyclerView.setHasFixedSize(true);
+ mRecyclerView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT));
+ for (int i = 0; i < 6; ++i) {
+ mItems.add("Item #" + i);
+ }
+ mAdapter = new MyAdapter(mItems);
+ mRecyclerView.setAdapter(mAdapter);
+ container.addView(mRecyclerView);
+
+ CheckBox enableAnimations = (CheckBox) findViewById(R.id.enableAnimations);
+ enableAnimations.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ mAnimationsEnabled = isChecked;
+ }
+ });
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ MenuItemCompat.setShowAsAction(menu.add("Layout"), MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ mRecyclerView.requestLayout();
+ return super.onOptionsItemSelected(item);
+ }
+
+ public void checkboxClicked(View view) {
+ ViewGroup parent = (ViewGroup) view.getParent();
+ boolean selected = ((CheckBox) view).isChecked();
+ MyViewHolder holder = (MyViewHolder) mRecyclerView.getChildViewHolder(parent);
+ mAdapter.selectItem(holder, selected);
+ }
+
+ public void deleteItem(View view) {
+ int numItems = mItems.size();
+ if (numItems > 0) {
+ for (int i = numItems - 1; i >= 0; --i) {
+ final String itemText = mItems.get(i);
+ boolean selected = mAdapter.mSelected.get(itemText);
+ if (selected) {
+ removeAtPosition(i);
+ }
+ }
+ }
+ }
+
+ private String generateNewText() {
+ return "Added Item #" + mNumItemsAdded++;
+ }
+
+ public void d1a2d3(View view) {
+ removeAtPosition(1);
+ addAtPosition(2, "Added Item #" + mNumItemsAdded++);
+ removeAtPosition(3);
+ }
+
+ private void removeAtPosition(int position) {
+ mItems.remove(position);
+ mAdapter.notifyItemRemoved(position);
+ }
+
+ private void addAtPosition(int position, String text) {
+ mItems.add(position, text);
+ mAdapter.mSelected.put(text, Boolean.FALSE);
+ mAdapter.notifyItemInserted(position);
+ }
+
+ public void addDeleteItem(View view) {
+ addItem(view);
+ deleteItem(view);
+ }
+
+ public void deleteAddItem(View view) {
+ deleteItem(view);
+ addItem(view);
+ }
+
+ public void addItem(View view) {
+ addAtPosition(3, "Added Item #" + mNumItemsAdded++);
+ }
+
+ /**
+ * A basic ListView-style LayoutManager.
+ */
+ class MyLayoutManager extends RecyclerView.LayoutManager {
+ private static final String TAG = "MyLayoutManager";
+ private int mFirstPosition;
+ private final int mScrollDistance;
+
+ public MyLayoutManager(Context c) {
+ final DisplayMetrics dm = c.getResources().getDisplayMetrics();
+ mScrollDistance = (int) (SCROLL_DISTANCE * dm.density + 0.5f);
+ }
+
+ @Override
+ public boolean supportsItemAnimations() {
+ return mAnimationsEnabled;
+ }
+
+ @Override
+ public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
+ int parentBottom = getHeight() - getPaddingBottom();
+
+ final View oldTopView = getChildCount() > 0 ? getChildAt(0) : null;
+ int oldTop = getPaddingTop();
+ if (oldTopView != null) {
+ oldTop = Math.min(oldTopView.getTop(), oldTop);
+ }
+
+ // Note that we add everything to the scrap, but we do not clean it up;
+ // that is handled by the RecyclerView after this method returns
+ detachAndScrapAttachedViews(recycler);
+
+ int top = oldTop;
+ int bottom = top;
+ final int left = getPaddingLeft();
+ final int right = getWidth() - getPaddingRight();
+
+ int count = state.getItemCount();
+ for (int i = 0; mFirstPosition + i < count && top < parentBottom; i++, top = bottom) {
+ View v = recycler.getViewForPosition(mFirstPosition + i);
+
+ RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) v.getLayoutParams();
+ if (!params.isItemRemoved()) {
+ addView(v);
+ }
+ measureChild(v, 0, 0);
+ bottom = top + v.getMeasuredHeight();
+ v.layout(left, top, right, bottom);
+ if (params.isItemRemoved()) {
+ parentBottom += v.getHeight();
+ }
+ }
+
+ // Now that we've run a full layout, figure out which views were not used
+ // (cached in previousViews). For each of these views, position it where
+ // it would go, according to its position relative to the visible
+ // positions in the list. This information will be used by RecyclerView to
+ // record post-layout positions of these items for the purposes of animating them
+ // out of view
+
+ View lastVisibleView = getChildAt(getChildCount() - 1);
+ if (lastVisibleView != null) {
+ RecyclerView.LayoutParams lastParams =
+ (RecyclerView.LayoutParams) lastVisibleView.getLayoutParams();
+ int lastPosition = lastParams.getViewPosition();
+ final List<RecyclerView.ViewHolder> previousViews = recycler.getScrapList();
+ count = previousViews.size();
+ for (int i = 0; i < count; ++i) {
+ View view = previousViews.get(i).itemView;
+ RecyclerView.LayoutParams params =
+ (RecyclerView.LayoutParams) view.getLayoutParams();
+ int position = params.getViewPosition();
+ int newTop;
+ if (position < mFirstPosition) {
+ newTop = view.getHeight() * (position - mFirstPosition);
+ } else {
+ newTop = lastVisibleView.getTop() + view.getHeight() *
+ (position - lastPosition);
+ }
+ view.offsetTopAndBottom(newTop - view.getTop());
+ }
+ }
+ }
+
+ @Override
+ public RecyclerView.LayoutParams generateDefaultLayoutParams() {
+ return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT);
+ }
+
+ @Override
+ public boolean canScrollVertically() {
+ return true;
+ }
+
+ @Override
+ public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler,
+ RecyclerView.State state) {
+ if (getChildCount() == 0) {
+ return 0;
+ }
+
+ int scrolled = 0;
+ final int left = getPaddingLeft();
+ final int right = getWidth() - getPaddingRight();
+ if (dy < 0) {
+ while (scrolled > dy) {
+ final View topView = getChildAt(0);
+ final int hangingTop = Math.max(-topView.getTop(), 0);
+ final int scrollBy = Math.min(scrolled - dy, hangingTop);
+ scrolled -= scrollBy;
+ offsetChildrenVertical(scrollBy);
+ if (mFirstPosition > 0 && scrolled > dy) {
+ mFirstPosition--;
+ View v = recycler.getViewForPosition(mFirstPosition);
+ addView(v, 0);
+ measureChild(v, 0, 0);
+ final int bottom = topView.getTop(); // TODO decorated top?
+ final int top = bottom - v.getMeasuredHeight();
+ v.layout(left, top, right, bottom);
+ } else {
+ break;
+ }
+ }
+ } else if (dy > 0) {
+ final int parentHeight = getHeight();
+ while (scrolled < dy) {
+ final View bottomView = getChildAt(getChildCount() - 1);
+ final int hangingBottom = Math.max(bottomView.getBottom() - parentHeight, 0);
+ final int scrollBy = -Math.min(dy - scrolled, hangingBottom);
+ scrolled -= scrollBy;
+ offsetChildrenVertical(scrollBy);
+ if (scrolled < dy && getItemCount() > mFirstPosition + getChildCount()) {
+ View v = recycler.getViewForPosition(mFirstPosition + getChildCount());
+ final int top = getChildAt(getChildCount() - 1).getBottom();
+ addView(v);
+ measureChild(v, 0, 0);
+ final int bottom = top + v.getMeasuredHeight();
+ v.layout(left, top, right, bottom);
+ } else {
+ break;
+ }
+ }
+ }
+ recycleViewsOutOfBounds(recycler);
+ return scrolled;
+ }
+
+ @Override
+ public View onFocusSearchFailed(View focused, int direction,
+ RecyclerView.Recycler recycler, RecyclerView.State state) {
+ final int oldCount = getChildCount();
+
+ if (oldCount == 0) {
+ return null;
+ }
+
+ final int left = getPaddingLeft();
+ final int right = getWidth() - getPaddingRight();
+
+ View toFocus = null;
+ int newViewsHeight = 0;
+ if (direction == View.FOCUS_UP || direction == View.FOCUS_BACKWARD) {
+ while (mFirstPosition > 0 && newViewsHeight < mScrollDistance) {
+ mFirstPosition--;
+ View v = recycler.getViewForPosition(mFirstPosition);
+ final int bottom = getChildAt(0).getTop(); // TODO decorated top?
+ addView(v, 0);
+ measureChild(v, 0, 0);
+ final int top = bottom - v.getMeasuredHeight();
+ v.layout(left, top, right, bottom);
+ if (v.isFocusable()) {
+ toFocus = v;
+ break;
+ }
+ }
+ }
+ if (direction == View.FOCUS_DOWN || direction == View.FOCUS_FORWARD) {
+ while (mFirstPosition + getChildCount() < getItemCount() &&
+ newViewsHeight < mScrollDistance) {
+ View v = recycler.getViewForPosition(mFirstPosition + getChildCount());
+ final int top = getChildAt(getChildCount() - 1).getBottom();
+ addView(v);
+ measureChild(v, 0, 0);
+ final int bottom = top + v.getMeasuredHeight();
+ v.layout(left, top, right, bottom);
+ if (v.isFocusable()) {
+ toFocus = v;
+ break;
+ }
+ }
+ }
+
+ return toFocus;
+ }
+
+ public void recycleViewsOutOfBounds(RecyclerView.Recycler recycler) {
+ final int childCount = getChildCount();
+ final int parentWidth = getWidth();
+ final int parentHeight = getHeight();
+ boolean foundFirst = false;
+ int first = 0;
+ int last = 0;
+ for (int i = 0; i < childCount; i++) {
+ final View v = getChildAt(i);
+ if (v.hasFocus() || (v.getRight() >= 0 && v.getLeft() <= parentWidth &&
+ v.getBottom() >= 0 && v.getTop() <= parentHeight)) {
+ if (!foundFirst) {
+ first = i;
+ foundFirst = true;
+ }
+ last = i;
+ }
+ }
+ for (int i = childCount - 1; i > last; i--) {
+ removeAndRecycleViewAt(i, recycler);
+ }
+ for (int i = first - 1; i >= 0; i--) {
+ removeAndRecycleViewAt(i, recycler);
+ }
+ if (getChildCount() == 0) {
+ mFirstPosition = 0;
+ } else {
+ mFirstPosition += first;
+ }
+ }
+
+ @Override
+ public void onItemsAdded(RecyclerView recyclerView, int positionStart, int itemCount) {
+ if (positionStart < mFirstPosition) {
+ mFirstPosition += itemCount;
+ }
+ }
+
+ @Override
+ public void onItemsRemoved(RecyclerView recyclerView, int positionStart, int itemCount) {
+ if (positionStart < mFirstPosition) {
+ mFirstPosition -= itemCount;
+ }
+ }
+ }
+
+ class MyAdapter extends RecyclerView.Adapter {
+ private int mBackground;
+ List<String> mData;
+ HashMap<String, Boolean> mSelected = new HashMap<String, Boolean>();
+
+ public MyAdapter(List<String> data) {
+ TypedValue val = new TypedValue();
+ AnimatedRecyclerView.this.getTheme().resolveAttribute(
+ R.attr.selectableItemBackground, val, true);
+ mBackground = val.resourceId;
+ mData = data;
+ for (String itemText : mData) {
+ mSelected.put(itemText, Boolean.FALSE);
+ }
+ }
+
+ @Override
+ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ MyViewHolder h = new MyViewHolder(getLayoutInflater().inflate(R.layout.selectable_item,
+ null));
+ h.textView.setMinimumHeight(128);
+ h.textView.setFocusable(true);
+ h.textView.setBackgroundResource(mBackground);
+ return h;
+ }
+
+ @Override
+ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
+ String itemText = mData.get(position);
+ ((MyViewHolder) holder).textView.setText(itemText);
+ boolean selected = false;
+ if (mSelected.get(itemText) != null) {
+ selected = mSelected.get(itemText);
+ }
+ ((MyViewHolder) holder).checkBox.setChecked(selected);
+ }
+
+ @Override
+ public int getItemCount() {
+ return mData.size();
+ }
+
+ public void selectItem(String itemText, boolean selected) {
+ mSelected.put(itemText, selected);
+ }
+
+ public void selectItem(MyViewHolder holder, boolean selected) {
+ mSelected.put((String) holder.textView.getText(), selected);
+ }
+ }
+
+ static class MyViewHolder extends RecyclerView.ViewHolder {
+ public TextView textView;
+ public CheckBox checkBox;
+
+ public MyViewHolder(View v) {
+ super(v);
+ textView = (TextView) v.findViewById(R.id.text);
+ checkBox = (CheckBox) v.findViewById(R.id.selected);
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + " \"" + textView.getText() + "\"";
+ }
+ }}
diff --git a/samples/Support7Demos/src/com/example/android/supportv7/widget/LinearLayoutManagerActivity.java b/samples/Support7Demos/src/com/example/android/supportv7/widget/LinearLayoutManagerActivity.java
new file mode 100644
index 0000000..8c2caa9
--- /dev/null
+++ b/samples/Support7Demos/src/com/example/android/supportv7/widget/LinearLayoutManagerActivity.java
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 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.supportv7.widget;
+
+import com.example.android.supportv7.Cheeses;
+import com.example.android.supportv7.widget.adapter.SimpleStringAdapter;
+import com.example.android.supportv7.widget.decorator.DividerItemDecoration;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.support.v4.view.ViewCompat;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.EditText;
+import android.widget.Spinner;
+import android.widget.TextView;
+
+import com.example.android.supportv7.R;
+
+/**
+ * A sample activity that uses {@link android.support.v7.widget.LinearLayoutManager}.
+ */
+public class LinearLayoutManagerActivity extends Activity {
+
+ private RecyclerView.LayoutManager mListLayoutManager;
+
+ private ListWrapper mListWrapper;
+
+ private RecyclerView mRecyclerView;
+
+ private DividerItemDecoration mDividerItemDecoration;
+
+ private ConfigToggle[] mConfigToggles;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_linear_layout_manager);
+ initConfig();
+ initRecyclerView();
+ initSpinner();
+ }
+
+ private void initRecyclerView() {
+ mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
+ mRecyclerView.setHasFixedSize(true);
+ mListLayoutManager = new LinearLayoutManager(this);
+ mRecyclerView.setLayoutManager(mListLayoutManager);
+ mRecyclerView.setAdapter(new SimpleStringAdapter(this, Cheeses.sCheeseStrings) {
+ @Override
+ public SimpleStringAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
+ int viewType) {
+ final SimpleStringAdapter.ViewHolder vh = super
+ .onCreateViewHolder(parent, viewType);
+ vh.itemView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ final int pos = vh.getPosition();
+ if (pos + 1 < getItemCount()) {
+ swap(pos, pos + 1);
+ }
+ notifyItemChanged(pos);
+ }
+ });
+ return vh;
+ }
+ });
+ initListForLayoutManager();
+ }
+
+ private void initListForLayoutManager() {
+ mListWrapper = new ListWrapper() {
+ @Override
+ public int getOrientation() {
+ return lm().getOrientation();
+ }
+
+ @Override
+ public void setOrientation(int orientation) {
+ lm().setOrientation(orientation);
+ }
+
+ @Override
+ public boolean getReverseLayout() {
+ return lm().getReverseLayout();
+ }
+
+ @Override
+ public void setReverseLayout(boolean newValue) {
+ lm().setReverseLayout(newValue);
+ }
+
+ @Override
+ public boolean getStackFromEnd() {
+ return lm().getStackFromEnd();
+ }
+
+ @Override
+ public void setStackFromEnd(boolean newValue) {
+ lm().setStackFromEnd(newValue);
+ }
+
+ private LinearLayoutManager lm() {
+ return (LinearLayoutManager) mListLayoutManager;
+ }
+ };
+ if (mDividerItemDecoration != null) {
+ mRecyclerView.removeItemDecoration(mDividerItemDecoration);
+ }
+ mDividerItemDecoration = new DividerItemDecoration(this, mListWrapper.getOrientation());
+ mRecyclerView.addItemDecoration(mDividerItemDecoration);
+ }
+
+ private void initConfig() {
+ RecyclerView configView = (RecyclerView) findViewById(R.id.config_recycler_view);
+ initToggles();
+ configView.setAdapter(mConfigAdapter);
+ configView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL,
+ false));
+ configView.setHasFixedSize(true);
+ }
+
+ private void initSpinner() {
+ final CheckBox checkBox = (CheckBox)
+ findViewById(R.id.enable_smooth_scroll);
+
+ final Spinner spinner = (Spinner) findViewById(R.id.spinner);
+ final EditText scrollOffset = (EditText) findViewById(R.id.scroll_offset);
+ spinner.setAdapter(new BaseAdapter() {
+ @Override
+ public int getCount() {
+ return mRecyclerView.getAdapter().getItemCount();
+ }
+
+ @Override
+ public Integer getItem(int position) {
+ return position;
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ if (convertView == null) {
+ convertView = new TextView(parent.getContext());
+ }
+ ((TextView) convertView).setText("" + position);
+ return convertView;
+ }
+ });
+ spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+ int offset = Integer.MIN_VALUE;
+ String offsetString = scrollOffset.getText().toString();
+ try {
+ offset = Integer.parseInt(offsetString);
+ } catch (NumberFormatException ex) {
+
+ }
+
+ if (offset == Integer.MIN_VALUE) {
+ if (checkBox.isChecked()) {
+ mRecyclerView.smoothScrollToPosition(position);
+ } else {
+ mRecyclerView.scrollToPosition(position);
+ }
+ } else {
+ // ignore offset until we add recycling list view with smooth scroll to offset
+ mRecyclerView.smoothScrollToPosition(position);
+ }
+
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+
+ }
+ });
+ }
+
+ private void initToggles() {
+ mConfigToggles = new ConfigToggle[]{
+ new ConfigToggle(R.string.checkbox_orientation) {
+ @Override
+ public boolean isChecked() {
+ return mListWrapper.getOrientation() == LinearLayoutManager.HORIZONTAL;
+ }
+
+ @Override
+ public void onChange(boolean newValue) {
+ mListWrapper.setOrientation(newValue ? LinearLayoutManager.HORIZONTAL
+ : LinearLayoutManager.VERTICAL);
+ if (mDividerItemDecoration != null) {
+ mDividerItemDecoration.setOrientation(mListWrapper.getOrientation());
+ }
+
+ }
+ },
+ new ConfigToggle(R.string.checkbox_reverse) {
+ @Override
+ public boolean isChecked() {
+ return mListWrapper.getReverseLayout();
+ }
+
+ @Override
+ public void onChange(boolean newValue) {
+ mListWrapper.setReverseLayout(newValue);
+ }
+ },
+ new ConfigToggle(R.string.checkbox_layout_dir) {
+ @Override
+ public boolean isChecked() {
+ return ViewCompat.getLayoutDirection(mRecyclerView) ==
+ ViewCompat.LAYOUT_DIRECTION_RTL;
+ }
+
+ @Override
+ public void onChange(boolean newValue) {
+ ViewCompat.setLayoutDirection(mRecyclerView, newValue ?
+ ViewCompat.LAYOUT_DIRECTION_RTL : ViewCompat.LAYOUT_DIRECTION_LTR);
+ }
+ },
+ new ConfigToggle(R.string.checkbox_stack_from_end) {
+ @Override
+ public boolean isChecked() {
+ return mListWrapper.getStackFromEnd();
+ }
+
+ @Override
+ public void onChange(boolean newValue) {
+ mListWrapper.setStackFromEnd(newValue);
+ }
+ }
+ };
+ }
+
+ private class ConfigViewHolder extends RecyclerView.ViewHolder
+ implements CompoundButton.OnCheckedChangeListener {
+
+ private CheckBox mCheckBox;
+
+ private ConfigToggle mConfigToggle;
+
+ public ConfigViewHolder(View itemView) {
+ super(itemView);
+ mCheckBox = (CheckBox) itemView;
+ mCheckBox.setOnCheckedChangeListener(this);
+ }
+
+ public void render(ConfigToggle toggle) {
+ mConfigToggle = toggle;
+ mCheckBox.setText(toggle.getText());
+ mCheckBox.setChecked(toggle.isChecked());
+ }
+
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ if (mConfigToggle != null) {
+ mConfigToggle.onChange(isChecked);
+ }
+ }
+ }
+
+
+ private abstract class ConfigToggle {
+
+ private String mLabel;
+
+ protected ConfigToggle(int labelId) {
+ mLabel = getResources().getString(labelId);
+ }
+
+ public String getText() {
+ return mLabel;
+ }
+
+ abstract public boolean isChecked();
+
+ abstract public void onChange(boolean newValue);
+ }
+
+
+ private RecyclerView.Adapter mConfigAdapter = new RecyclerView.Adapter<ConfigViewHolder>() {
+ @Override
+ public ConfigViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ return new ConfigViewHolder(new CheckBox(parent.getContext()));
+ }
+
+ @Override
+ public void onBindViewHolder(ConfigViewHolder holder, int position) {
+ ConfigToggle toggle = mConfigToggles[position];
+ holder.render(toggle);
+ }
+
+ @Override
+ public int getItemCount() {
+ return mConfigToggles.length;
+ }
+ };
+
+
+ /**
+ * To avoid adding interfaces to LayoutManager for the demo, we use this wrapper class to
+ * call different LayoutManagers
+ */
+ private static interface ListWrapper {
+
+ int getOrientation();
+
+ void setOrientation(int orientation);
+
+ boolean getReverseLayout();
+
+ void setReverseLayout(boolean newValue);
+
+ boolean getStackFromEnd();
+
+ void setStackFromEnd(boolean newValue);
+ }
+
+
+}
diff --git a/samples/Support7Demos/src/com/example/android/supportv7/widget/RecyclerViewActivity.java b/samples/Support7Demos/src/com/example/android/supportv7/widget/RecyclerViewActivity.java
new file mode 100644
index 0000000..baecf86
--- /dev/null
+++ b/samples/Support7Demos/src/com/example/android/supportv7/widget/RecyclerViewActivity.java
@@ -0,0 +1,276 @@
+/*
+ * 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.supportv7.widget;
+
+import com.example.android.supportv7.Cheeses;
+import com.example.android.supportv7.widget.adapter.SimpleStringAdapter;
+import com.example.android.supportv7.widget.decorator.DividerItemDecoration;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v4.view.MenuItemCompat;
+import android.support.v7.widget.RecyclerView;
+import android.util.DisplayMetrics;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class RecyclerViewActivity extends Activity {
+
+ private static final String TAG = "RecyclerViewActivity";
+
+ private RecyclerView mRecyclerView;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ final RecyclerView rv = new RecyclerView(this);
+ rv.setLayoutManager(new MyLayoutManager(this));
+ rv.setHasFixedSize(true);
+ rv.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT));
+ rv.setAdapter(new SimpleStringAdapter(this, Cheeses.sCheeseStrings) {
+ @Override
+ public SimpleStringAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
+ int viewType) {
+ final SimpleStringAdapter.ViewHolder vh = super
+ .onCreateViewHolder(parent, viewType);
+ vh.itemView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ final int pos = vh.getPosition();
+ if (pos + 1 < getItemCount()) {
+ swap(pos, pos + 1);
+ }
+ }
+ });
+ return vh;
+ }
+ });
+ rv.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST));
+ setContentView(rv);
+ mRecyclerView = rv;
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ MenuItemCompat.setShowAsAction(menu.add("Layout"), MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ mRecyclerView.requestLayout();
+ return super.onOptionsItemSelected(item);
+ }
+
+ private static final int SCROLL_DISTANCE = 80; // dp
+
+ /**
+ * A basic ListView-style LayoutManager.
+ */
+ class MyLayoutManager extends RecyclerView.LayoutManager {
+
+ private static final String TAG = "MyLayoutManager";
+
+ private int mFirstPosition;
+
+ private final int mScrollDistance;
+
+ public MyLayoutManager(Context c) {
+ final DisplayMetrics dm = c.getResources().getDisplayMetrics();
+ mScrollDistance = (int) (SCROLL_DISTANCE * dm.density + 0.5f);
+ }
+
+ @Override
+ public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
+ final int parentBottom = getHeight() - getPaddingBottom();
+ final View oldTopView = getChildCount() > 0 ? getChildAt(0) : null;
+ int oldTop = getPaddingTop();
+ if (oldTopView != null) {
+ oldTop = oldTopView.getTop();
+ }
+
+ detachAndScrapAttachedViews(recycler);
+
+ int top = oldTop;
+ int bottom;
+ final int left = getPaddingLeft();
+ final int right = getWidth() - getPaddingRight();
+
+ final int count = state.getItemCount();
+ for (int i = 0; mFirstPosition + i < count && top < parentBottom; i++, top = bottom) {
+ View v = recycler.getViewForPosition(mFirstPosition + i);
+ addView(v, i);
+ measureChildWithMargins(v, 0, 0);
+ bottom = top + getDecoratedMeasuredHeight(v);
+ layoutDecorated(v, left, top, right, bottom);
+ }
+ }
+
+ @Override
+ public RecyclerView.LayoutParams generateDefaultLayoutParams() {
+ return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT);
+ }
+
+ @Override
+ public boolean canScrollVertically() {
+ return true;
+ }
+
+ @Override
+ public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler,
+ RecyclerView.State state) {
+ if (getChildCount() == 0) {
+ return 0;
+ }
+
+ int scrolled = 0;
+ final int left = getPaddingLeft();
+ final int right = getWidth() - getPaddingRight();
+ if (dy < 0) {
+ while (scrolled > dy) {
+ final View topView = getChildAt(0);
+ final int hangingTop = Math.max(-getDecoratedTop(topView), 0);
+ final int scrollBy = Math.min(scrolled - dy, hangingTop);
+ scrolled -= scrollBy;
+ offsetChildrenVertical(scrollBy);
+ if (mFirstPosition > 0 && scrolled > dy) {
+ mFirstPosition--;
+ View v = recycler.getViewForPosition(mFirstPosition);
+ addView(v, 0);
+ measureChildWithMargins(v, 0, 0);
+ final int bottom = getDecoratedTop(topView);
+ final int top = bottom - getDecoratedMeasuredHeight(v);
+ layoutDecorated(v, left, top, right, bottom);
+ } else {
+ break;
+ }
+ }
+ } else if (dy > 0) {
+ final int parentHeight = getHeight();
+ while (scrolled < dy) {
+ final View bottomView = getChildAt(getChildCount() - 1);
+ final int hangingBottom =
+ Math.max(getDecoratedBottom(bottomView) - parentHeight, 0);
+ final int scrollBy = -Math.min(dy - scrolled, hangingBottom);
+ scrolled -= scrollBy;
+ offsetChildrenVertical(scrollBy);
+ if (scrolled < dy && getItemCount() > mFirstPosition + getChildCount()) {
+ View v = recycler.getViewForPosition(mFirstPosition + getChildCount());
+ final int top = getDecoratedBottom(getChildAt(getChildCount() - 1));
+ addView(v);
+ measureChildWithMargins(v, 0, 0);
+ final int bottom = top + getDecoratedMeasuredHeight(v);
+ layoutDecorated(v, left, top, right, bottom);
+ } else {
+ break;
+ }
+ }
+ }
+ recycleViewsOutOfBounds(recycler);
+ return scrolled;
+ }
+
+ @Override
+ public View onFocusSearchFailed(View focused, int direction,
+ RecyclerView.Recycler recycler, RecyclerView.State state) {
+ final int oldCount = getChildCount();
+
+ if (oldCount == 0) {
+ return null;
+ }
+
+ final int left = getPaddingLeft();
+ final int right = getWidth() - getPaddingRight();
+
+ View toFocus = null;
+ int newViewsHeight = 0;
+ if (direction == View.FOCUS_UP || direction == View.FOCUS_BACKWARD) {
+ while (mFirstPosition > 0 && newViewsHeight < mScrollDistance) {
+ mFirstPosition--;
+ View v = recycler.getViewForPosition(mFirstPosition);
+ final int bottom = getDecoratedTop(getChildAt(0));
+ addView(v, 0);
+ measureChildWithMargins(v, 0, 0);
+ final int top = bottom - getDecoratedMeasuredHeight(v);
+ layoutDecorated(v, left, top, right, bottom);
+ if (v.isFocusable()) {
+ toFocus = v;
+ break;
+ }
+ }
+ }
+ if (direction == View.FOCUS_DOWN || direction == View.FOCUS_FORWARD) {
+ while (mFirstPosition + getChildCount() < getItemCount() &&
+ newViewsHeight < mScrollDistance) {
+ View v = recycler.getViewForPosition(mFirstPosition + getChildCount());
+ final int top = getDecoratedBottom(getChildAt(getChildCount() - 1));
+ addView(v);
+ measureChildWithMargins(v, 0, 0);
+ final int bottom = top + getDecoratedMeasuredHeight(v);
+ layoutDecorated(v, left, top, right, bottom);
+ if (v.isFocusable()) {
+ toFocus = v;
+ break;
+ }
+ }
+ }
+
+ return toFocus;
+ }
+
+ public void recycleViewsOutOfBounds(RecyclerView.Recycler recycler) {
+ final int childCount = getChildCount();
+ final int parentWidth = getWidth();
+ final int parentHeight = getHeight();
+ boolean foundFirst = false;
+ int first = 0;
+ int last = 0;
+ for (int i = 0; i < childCount; i++) {
+ final View v = getChildAt(i);
+ if (v.hasFocus() || (getDecoratedRight(v) >= 0 &&
+ getDecoratedLeft(v) <= parentWidth &&
+ getDecoratedBottom(v) >= 0 &&
+ getDecoratedTop(v) <= parentHeight)) {
+ if (!foundFirst) {
+ first = i;
+ foundFirst = true;
+ }
+ last = i;
+ }
+ }
+ for (int i = childCount - 1; i > last; i--) {
+ removeAndRecycleViewAt(i, recycler);
+ }
+ for (int i = first - 1; i >= 0; i--) {
+ removeAndRecycleViewAt(i, recycler);
+ }
+ if (getChildCount() == 0) {
+ mFirstPosition = 0;
+ } else {
+ mFirstPosition += first;
+ }
+ }
+ }
+}
diff --git a/samples/Support7Demos/src/com/example/android/supportv7/widget/adapter/SimpleStringAdapter.java b/samples/Support7Demos/src/com/example/android/supportv7/widget/adapter/SimpleStringAdapter.java
new file mode 100644
index 0000000..a12e79d
--- /dev/null
+++ b/samples/Support7Demos/src/com/example/android/supportv7/widget/adapter/SimpleStringAdapter.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 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.supportv7.widget.adapter;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.support.v7.widget.RecyclerView;
+import android.util.TypedValue;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.Collections;
+
+public class SimpleStringAdapter extends RecyclerView.Adapter<SimpleStringAdapter.ViewHolder> {
+
+ private int mBackground;
+
+ private ArrayList<String> mValues;
+
+ public static class ViewHolder extends RecyclerView.ViewHolder {
+
+ public TextView mTextView;
+
+ public ViewHolder(TextView v) {
+ super(v);
+ mTextView = v;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + " '" + mTextView.getText();
+ }
+ }
+
+ public SimpleStringAdapter(Context context, String[] strings) {
+ TypedValue val = new TypedValue();
+ if (context.getTheme() != null) {
+ context.getTheme().resolveAttribute(
+ android.R.attr.selectableItemBackground, val, true);
+ }
+ mBackground = val.resourceId;
+ mValues = new ArrayList<String>();
+ Collections.addAll(mValues, strings);
+ }
+
+ public void swap(int pos1, int pos2) {
+ String tmp = mValues.get(pos1);
+ mValues.set(pos1, mValues.get(pos2));
+ mValues.set(pos2, tmp);
+ notifyItemRemoved(pos1);
+ notifyItemInserted(pos2);
+ }
+
+ @Override
+ public SimpleStringAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ final ViewHolder h = new ViewHolder(new TextView(parent.getContext()));
+ h.mTextView.setMinimumHeight(128);
+ h.mTextView.setPadding(20, 0, 20, 0);
+ h.mTextView.setFocusable(true);
+ h.mTextView.setBackgroundResource(mBackground);
+ RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT);
+ lp.leftMargin = 10;
+ lp.rightMargin = 5;
+ lp.topMargin = 20;
+ lp.bottomMargin = 15;
+ h.mTextView.setLayoutParams(lp);
+ return h;
+ }
+
+ @Override
+ public void onBindViewHolder(ViewHolder holder, int position) {
+ holder.mTextView.setText(position + ":" + mValues.get(position));
+ holder.mTextView.setMinHeight((200 + mValues.get(position).length() * 10));
+ holder.mTextView.setBackgroundColor(getBackgroundColor(position));
+ }
+
+ private int getBackgroundColor(int position) {
+ switch (position % 4) {
+ case 0: return Color.BLACK;
+ case 1: return Color.RED;
+ case 2: return Color.GREEN;
+ case 3: return Color.BLUE;
+ }
+ return Color.TRANSPARENT;
+ }
+
+ @Override
+ public int getItemCount() {
+ return mValues.size();
+ }
+}
diff --git a/samples/Support7Demos/src/com/example/android/supportv7/widget/decorator/DividerItemDecoration.java b/samples/Support7Demos/src/com/example/android/supportv7/widget/decorator/DividerItemDecoration.java
new file mode 100644
index 0000000..4d5d208
--- /dev/null
+++ b/samples/Support7Demos/src/com/example/android/supportv7/widget/decorator/DividerItemDecoration.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 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.supportv7.widget.decorator;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+
+public class DividerItemDecoration extends RecyclerView.ItemDecoration {
+
+ private static final int[] ATTRS = new int[]{
+ android.R.attr.listDivider
+ };
+
+ public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
+
+ public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
+
+ private Drawable mDivider;
+
+ private int mOrientation;
+
+ public DividerItemDecoration(Context context, int orientation) {
+ final TypedArray a = context.obtainStyledAttributes(ATTRS);
+ mDivider = a.getDrawable(0);
+ a.recycle();
+ setOrientation(orientation);
+ }
+
+ public void setOrientation(int orientation) {
+ if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
+ throw new IllegalArgumentException("invalid orientation");
+ }
+ mOrientation = orientation;
+ }
+
+ @Override
+ public void onDraw(Canvas c, RecyclerView parent) {
+ if (mOrientation == VERTICAL_LIST) {
+ drawVertical(c, parent);
+ } else {
+ drawHorizontal(c, parent);
+ }
+ }
+
+ public void drawVertical(Canvas c, RecyclerView parent) {
+ final int left = parent.getPaddingLeft();
+ final int right = parent.getWidth() - parent.getPaddingRight();
+
+ final int childCount = parent.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ final View child = parent.getChildAt(i);
+ final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
+ .getLayoutParams();
+ final int top = child.getBottom() + params.bottomMargin;
+ final int bottom = top + mDivider.getIntrinsicHeight();
+ mDivider.setBounds(left, top, right, bottom);
+ mDivider.draw(c);
+ }
+ }
+
+ public void drawHorizontal(Canvas c, RecyclerView parent) {
+ final int top = parent.getPaddingTop();
+ final int bottom = parent.getHeight() - parent.getPaddingBottom();
+
+ final int childCount = parent.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ final View child = parent.getChildAt(i);
+ final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
+ .getLayoutParams();
+ final int left = child.getRight() + params.rightMargin;
+ final int right = left + mDivider.getIntrinsicHeight();
+ mDivider.setBounds(left, top, right, bottom);
+ mDivider.draw(c);
+ }
+ }
+
+ @Override
+ public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
+ if (mOrientation == VERTICAL_LIST) {
+ outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
+ } else {
+ outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
+ }
+ }
+}
diff --git a/samples/SupportLeanbackDemos/Android.mk b/samples/SupportLeanbackDemos/Android.mk
new file mode 100644
index 0000000..41424a7
--- /dev/null
+++ b/samples/SupportLeanbackDemos/Android.mk
@@ -0,0 +1,35 @@
+# Copyright (C) 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+# Build the samples.
+# We need to add some special AAPT flags to generate R classes
+# for resources that are included from the libraries.
+include $(CLEAR_VARS)
+LOCAL_PACKAGE_NAME := SupportLeanbackDemos
+LOCAL_MODULE_TAGS := samples tests
+LOCAL_SDK_VERSION := current
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ android-support-v4 \
+ android-support-v7-recyclerview \
+ android-support-v17-leanback
+LOCAL_RESOURCE_DIR = \
+ $(LOCAL_PATH)/res \
+ frameworks/support/v17/leanback/res
+LOCAL_AAPT_FLAGS := \
+ --auto-add-overlay \
+ --extra-packages android.support.v17.leanback
+include $(BUILD_PACKAGE)
diff --git a/samples/SupportLeanbackDemos/AndroidManifest.xml b/samples/SupportLeanbackDemos/AndroidManifest.xml
new file mode 100644
index 0000000..ee0707d
--- /dev/null
+++ b/samples/SupportLeanbackDemos/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.leanback"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <uses-sdk android:minSdkVersion="17" android:targetSdkVersion="19" />
+
+ <application
+ android:label="@string/app_name"
+ android:icon="@drawable/ic_launcher"
+ android:theme="@style/Theme.Leanback">
+
+ <activity android:name="MainActivity"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name="DetailsActivity"
+ android:exported="true" />
+
+ <activity android:name="VerticalGridActivity"
+ android:exported="true" />
+
+ <activity android:name="SearchActivity"
+ android:exported="true" />
+
+ </application>
+</manifest>
diff --git a/samples/SupportLeanbackDemos/res/drawable-hdpi/ic_launcher.png b/samples/SupportLeanbackDemos/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..96a442e
--- /dev/null
+++ b/samples/SupportLeanbackDemos/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/SupportLeanbackDemos/res/drawable-ldpi/ic_launcher.png b/samples/SupportLeanbackDemos/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 0000000..9923872
--- /dev/null
+++ b/samples/SupportLeanbackDemos/res/drawable-ldpi/ic_launcher.png
Binary files differ
diff --git a/samples/SupportLeanbackDemos/res/drawable-mdpi/ic_launcher.png b/samples/SupportLeanbackDemos/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..359047d
--- /dev/null
+++ b/samples/SupportLeanbackDemos/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/SupportLeanbackDemos/res/drawable-xhdpi/grid_bg.png b/samples/SupportLeanbackDemos/res/drawable-xhdpi/grid_bg.png
new file mode 100644
index 0000000..476c698
--- /dev/null
+++ b/samples/SupportLeanbackDemos/res/drawable-xhdpi/grid_bg.png
Binary files differ
diff --git a/samples/SupportLeanbackDemos/res/drawable-xhdpi/ic_launcher.png b/samples/SupportLeanbackDemos/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..71c6d76
--- /dev/null
+++ b/samples/SupportLeanbackDemos/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/SupportLeanbackDemos/res/drawable/details_img.png b/samples/SupportLeanbackDemos/res/drawable/details_img.png
new file mode 100644
index 0000000..7ea688b
--- /dev/null
+++ b/samples/SupportLeanbackDemos/res/drawable/details_img.png
Binary files differ
diff --git a/samples/SupportLeanbackDemos/res/drawable/ic_action_a.png b/samples/SupportLeanbackDemos/res/drawable/ic_action_a.png
new file mode 100644
index 0000000..3d555ef
--- /dev/null
+++ b/samples/SupportLeanbackDemos/res/drawable/ic_action_a.png
Binary files differ
diff --git a/samples/SupportLeanbackDemos/res/drawable/ic_title.png b/samples/SupportLeanbackDemos/res/drawable/ic_title.png
new file mode 100644
index 0000000..1c62b2e
--- /dev/null
+++ b/samples/SupportLeanbackDemos/res/drawable/ic_title.png
Binary files differ
diff --git a/samples/SupportLeanbackDemos/res/drawable/text_bg.xml b/samples/SupportLeanbackDemos/res/drawable/text_bg.xml
new file mode 100644
index 0000000..c67924c
--- /dev/null
+++ b/samples/SupportLeanbackDemos/res/drawable/text_bg.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <gradient
+ android:startColor="#FFFF0000"
+ android:endColor="#80FF00FF"
+ android:angle="45" />
+ <padding
+ android:left="7dp"
+ android:top="7dp"
+ android:right="7dp"
+ android:bottom="7dp" />
+</shape>
diff --git a/samples/SupportLeanbackDemos/res/layout/details.xml b/samples/SupportLeanbackDemos/res/layout/details.xml
new file mode 100644
index 0000000..4af4e6a
--- /dev/null
+++ b/samples/SupportLeanbackDemos/res/layout/details.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 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.
+-->
+
+<fragment xmlns:android="http://schemas.android.com/apk/res/android"
+ android:name="com.example.android.leanback.DetailsFragment"
+ android:id="@+id/details_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+/>
diff --git a/samples/SupportLeanbackDemos/res/layout/main.xml b/samples/SupportLeanbackDemos/res/layout/main.xml
new file mode 100644
index 0000000..b6b08b3
--- /dev/null
+++ b/samples/SupportLeanbackDemos/res/layout/main.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 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.
+-->
+
+<fragment xmlns:android="http://schemas.android.com/apk/res/android"
+ android:name="com.example.android.leanback.BrowseFragment"
+ android:id="@+id/main_browse_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+/>
diff --git a/samples/SupportLeanbackDemos/res/layout/search.xml b/samples/SupportLeanbackDemos/res/layout/search.xml
new file mode 100644
index 0000000..b65600c
--- /dev/null
+++ b/samples/SupportLeanbackDemos/res/layout/search.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 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.
+-->
+
+<fragment xmlns:android="http://schemas.android.com/apk/res/android"
+ android:name="com.example.android.leanback.SearchFragment"
+ android:id="@+id/search_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ />
\ No newline at end of file
diff --git a/samples/SupportLeanbackDemos/res/layout/vertical_grid.xml b/samples/SupportLeanbackDemos/res/layout/vertical_grid.xml
new file mode 100644
index 0000000..1007042
--- /dev/null
+++ b/samples/SupportLeanbackDemos/res/layout/vertical_grid.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 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.
+-->
+
+<fragment xmlns:android="http://schemas.android.com/apk/res/android"
+ android:name="com.example.android.leanback.VerticalGridFragment"
+ android:id="@+id/vertical_grid_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+/>
diff --git a/samples/SupportLeanbackDemos/res/values/strings.xml b/samples/SupportLeanbackDemos/res/values/strings.xml
new file mode 100644
index 0000000..e884043
--- /dev/null
+++ b/samples/SupportLeanbackDemos/res/values/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 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="app_name">MainActivity</string>
+</resources>
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/BrowseFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/BrowseFragment.java
new file mode 100644
index 0000000..2345ed0
--- /dev/null
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/BrowseFragment.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 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.leanback;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v17.leanback.widget.ArrayObjectAdapter;
+import android.support.v17.leanback.widget.HeaderItem;
+import android.support.v17.leanback.widget.ListRow;
+import android.support.v17.leanback.widget.ListRowPresenter;
+import android.support.v17.leanback.widget.OnItemClickedListener;
+import android.support.v17.leanback.widget.Row;
+import android.util.Log;
+import android.view.View;
+
+public class BrowseFragment extends android.support.v17.leanback.app.BrowseFragment {
+ private static final String TAG = "leanback.BrowseFragment";
+
+ private static final int NUM_ROWS = 3;
+ private ArrayObjectAdapter mRowsAdapter;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ Log.i(TAG, "onCreate");
+ super.onCreate(savedInstanceState);
+
+ Params p = new Params();
+ p.setBadgeImage(getActivity().getResources().getDrawable(R.drawable.ic_title));
+ p.setTitle("Leanback Sample App");
+ p.setHeadersState(HEADERS_ENABLED);
+ setBrowseParams(p);
+
+ setOnSearchClickedListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getActivity(), SearchActivity.class);
+ startActivity(intent);
+ }
+ });
+
+ setupRows();
+ setOnItemClickedListener(new ItemClickedListener());
+ }
+
+ private void setupRows() {
+ mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
+
+ for (int i = 0; i < NUM_ROWS; ++i) {
+ ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(new CardPresenter());
+ listRowAdapter.add("Hello world");
+ listRowAdapter.add("This is a test");
+ HeaderItem header = new HeaderItem(i, "Row " + i, null);
+ mRowsAdapter.add(new ListRow(header, listRowAdapter));
+ }
+
+ setAdapter(mRowsAdapter);
+ }
+
+ private final class ItemClickedListener implements OnItemClickedListener {
+ public void onItemClicked(Object item, Row row) {
+ // TODO: use a fragment transaction instead of launching a new
+ // activity
+ Intent intent = new Intent(getActivity(), DetailsActivity.class);
+ startActivity(intent);
+ }
+ }
+}
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/CardPresenter.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/CardPresenter.java
new file mode 100644
index 0000000..502c77a
--- /dev/null
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/CardPresenter.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 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.leanback;
+
+import android.support.v17.leanback.widget.ImageCardView;
+import android.support.v17.leanback.widget.Presenter;
+import android.util.Log;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+public class CardPresenter extends Presenter {
+ private static final String TAG = "CardPresenter";
+
+ public ViewHolder onCreateViewHolder(ViewGroup parent) {
+ Log.d(TAG, "onCreateViewHolder");
+ ImageCardView v = new ImageCardView(parent.getContext());
+ v.setFocusable(true);
+ v.setFocusableInTouchMode(true);
+ v.setMainImage(
+ parent.getContext().getResources().getDrawable(R.drawable.text_bg));
+ return new ViewHolder(v);
+ }
+
+ public void onBindViewHolder(ViewHolder viewHolder, Object item) {
+ Log.d(TAG, "onBindViewHolder for " + item.toString());
+ ((ImageCardView) viewHolder.view).setTitleText(item.toString());
+ }
+
+ public void onUnbindViewHolder(ViewHolder viewHolder) {
+ Log.d(TAG, "onUnbindViewHolder");
+ }
+}
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsActivity.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsActivity.java
new file mode 100644
index 0000000..082b134
--- /dev/null
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsActivity.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 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.leanback;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class DetailsActivity extends Activity
+{
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.details);
+ }
+}
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsDescriptionPresenter.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsDescriptionPresenter.java
new file mode 100644
index 0000000..6d376f0
--- /dev/null
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsDescriptionPresenter.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 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.leanback;
+
+import android.support.v17.leanback.widget.AbstractDetailsDescriptionPresenter;
+import android.support.v17.leanback.widget.DetailsOverviewRow;
+
+public class DetailsDescriptionPresenter extends AbstractDetailsDescriptionPresenter {
+
+ @Override
+ protected void onBindDescription(ViewHolder vh, Object item) {
+ vh.getTitle().setText(item.toString());
+ vh.getSubtitle().setText("2013 - 2014 Drama TV-14");
+ vh.getBody().setText("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do "
+ + "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
+ + "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo "
+ + "consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse "
+ + "cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non "
+ + "proident, sunt in culpa qui officia deserunt mollit anim id est laborum.");
+ }
+}
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsFragment.java
new file mode 100644
index 0000000..c9a85f3
--- /dev/null
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsFragment.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 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.leanback;
+
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.support.v17.leanback.widget.Action;
+import android.support.v17.leanback.widget.ArrayObjectAdapter;
+import android.support.v17.leanback.widget.ClassPresenterSelector;
+import android.support.v17.leanback.widget.DetailsOverviewRow;
+import android.support.v17.leanback.widget.DetailsOverviewRowPresenter;
+import android.support.v17.leanback.widget.HeaderItem;
+import android.support.v17.leanback.widget.ListRow;
+import android.support.v17.leanback.widget.ListRowPresenter;
+import android.support.v17.leanback.widget.OnActionClickedListener;
+import android.util.Log;
+import android.widget.Toast;
+
+public class DetailsFragment extends android.support.v17.leanback.app.DetailsFragment {
+ private static final String TAG = "leanback.BrowseFragment";
+
+ private static final int NUM_ROWS = 3;
+ private ArrayObjectAdapter mRowsAdapter;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ Log.i(TAG, "onCreate");
+ super.onCreate(savedInstanceState);
+
+ setupRows();
+ }
+
+ private void setupRows() {
+ ClassPresenterSelector ps = new ClassPresenterSelector();
+ DetailsOverviewRowPresenter dorPresenter =
+ new DetailsOverviewRowPresenter(new DetailsDescriptionPresenter());
+ dorPresenter.setOnActionClickedListener(new OnActionClickedListener() {
+ public void onActionClicked(Action action) {
+ Toast.makeText(getActivity(), action.toString(), Toast.LENGTH_SHORT).show();
+ }
+ });
+
+ ps.addClassPresenter(DetailsOverviewRow.class, dorPresenter);
+ ps.addClassPresenter(ListRow.class,
+ new ListRowPresenter());
+ mRowsAdapter = new ArrayObjectAdapter(ps);
+
+ Resources res = getActivity().getResources();
+ DetailsOverviewRow dor = new DetailsOverviewRow("Details Overview");
+ dor.setImageDrawable(res.getDrawable(R.drawable.details_img));
+ dor.addAction(new Action(1, "Buy $9.99"));
+ dor.addAction(new Action(2, "Rent", "$3.99", res.getDrawable(R.drawable.ic_action_a)));
+ mRowsAdapter.add(dor);
+
+ for (int i = 0; i < NUM_ROWS; ++i) {
+ ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(new StringPresenter());
+ listRowAdapter.add("Hello world");
+ listRowAdapter.add("This is a test");
+ HeaderItem header = new HeaderItem(i, "Row " + i, null);
+ mRowsAdapter.add(new ListRow(header, listRowAdapter));
+ }
+
+ setAdapter(mRowsAdapter);
+ }
+
+}
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/MainActivity.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/MainActivity.java
new file mode 100644
index 0000000..74e7fb2
--- /dev/null
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/MainActivity.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 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.leanback;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class MainActivity extends Activity
+{
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+ }
+}
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/SearchActivity.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/SearchActivity.java
new file mode 100644
index 0000000..437bd72
--- /dev/null
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/SearchActivity.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 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.leanback;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class SearchActivity extends Activity
+{
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.search);
+ }
+}
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/SearchFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/SearchFragment.java
new file mode 100644
index 0000000..0489196
--- /dev/null
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/SearchFragment.java
@@ -0,0 +1,85 @@
+package com.example.android.leanback;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.v17.leanback.widget.ArrayObjectAdapter;
+import android.support.v17.leanback.widget.HeaderItem;
+import android.support.v17.leanback.widget.ListRow;
+import android.support.v17.leanback.widget.ListRowPresenter;
+import android.support.v17.leanback.widget.ObjectAdapter;
+import android.support.v17.leanback.widget.OnItemClickedListener;
+import android.support.v17.leanback.widget.Row;
+import android.text.TextUtils;
+import android.util.Log;
+
+public class SearchFragment extends android.support.v17.leanback.app.SearchFragment
+ implements android.support.v17.leanback.app.SearchFragment.SearchResultProvider {
+ private static final String TAG = "leanback.SearchFragment";
+ private static final int NUM_ROWS = 3;
+ private static final int SEARCH_DELAY_MS = 300;
+
+ private ArrayObjectAdapter mRowsAdapter;
+ private Handler mHandler = new Handler();
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
+ setSearchResultProvider(this);
+ setOnItemClickedListener(new ItemClickedListener());
+ }
+
+ @Override
+ public ObjectAdapter getResultsAdapter() {
+ return mRowsAdapter;
+ }
+
+ @Override
+ public boolean onQueryTextChange(String newQuery) {
+ Log.i(TAG, String.format("Search Query Text Change %s", newQuery));
+ mRowsAdapter.clear();
+ if (!TextUtils.isEmpty(newQuery)) {
+ mHandler.removeCallbacks(mDelayedLoad);
+ mHandler.postDelayed(mDelayedLoad, SEARCH_DELAY_MS);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean onQueryTextSubmit(String query) {
+ Log.i(TAG, String.format("Search Query Text Submit %s", query));
+ mRowsAdapter.clear();
+ if (!TextUtils.isEmpty(query)) {
+ mHandler.removeCallbacks(mDelayedLoad);
+ mHandler.postDelayed(mDelayedLoad, SEARCH_DELAY_MS);
+ }
+ return true;
+ }
+
+ private void loadRows() {
+ for (int i = 0; i < NUM_ROWS; ++i) {
+ ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(new StringPresenter());
+ listRowAdapter.add("Hello world");
+ listRowAdapter.add("This is a test");
+ HeaderItem header = new HeaderItem(i, "Row " + i, null);
+ mRowsAdapter.add(new ListRow(header, listRowAdapter));
+ }
+ }
+
+ private Runnable mDelayedLoad = new Runnable() {
+ @Override
+ public void run() {
+ loadRows();
+ }
+ };
+ private final class ItemClickedListener implements OnItemClickedListener {
+ public void onItemClicked(Object item, Row row) {
+ // TODO: use a fragment transaction instead of launching a new
+ // activity
+ Intent intent = new Intent(getActivity(), DetailsActivity.class);
+ startActivity(intent);
+ }
+ }
+}
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/StringPresenter.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/StringPresenter.java
new file mode 100644
index 0000000..5c80e0b
--- /dev/null
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/StringPresenter.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 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.leanback;
+
+import android.support.v17.leanback.widget.Presenter;
+import android.util.Log;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+public class StringPresenter extends Presenter {
+ private static final String TAG = "StringPresenter";
+
+ public ViewHolder onCreateViewHolder(ViewGroup parent) {
+ Log.d(TAG, "onCreateViewHolder");
+ TextView tv = new TextView(parent.getContext());
+ tv.setFocusable(true);
+ tv.setFocusableInTouchMode(true);
+ tv.setBackground(
+ parent.getContext().getResources().getDrawable(R.drawable.text_bg));
+ return new ViewHolder(tv);
+ }
+
+ public void onBindViewHolder(ViewHolder viewHolder, Object item) {
+ Log.d(TAG, "onBindViewHolder for " + item.toString());
+ ((TextView) viewHolder.view).setText(item.toString());
+ }
+
+ public void onUnbindViewHolder(ViewHolder viewHolder) {
+ Log.d(TAG, "onUnbindViewHolder");
+ }
+}
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/VerticalGridActivity.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/VerticalGridActivity.java
new file mode 100644
index 0000000..c5262b9
--- /dev/null
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/VerticalGridActivity.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 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.leanback;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class VerticalGridActivity extends Activity
+{
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.vertical_grid);
+ getWindow().setBackgroundDrawableResource(R.drawable.grid_bg);
+ }
+}
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/VerticalGridFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/VerticalGridFragment.java
new file mode 100644
index 0000000..495bebe
--- /dev/null
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/VerticalGridFragment.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 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.leanback;
+
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.support.v17.leanback.widget.ArrayObjectAdapter;
+import android.support.v17.leanback.widget.Presenter;
+import android.support.v17.leanback.widget.VerticalGridPresenter;
+import android.support.v17.leanback.widget.Row;
+import android.support.v17.leanback.widget.OnItemClickedListener;
+import android.support.v17.leanback.widget.OnItemSelectedListener;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import java.util.Random;
+
+public class VerticalGridFragment extends android.support.v17.leanback.app.VerticalGridFragment {
+ private static final String TAG = "leanback.VerticalGridFragment";
+
+ private static final int NUM_COLUMNS = 3;
+ private static final int NUM_ITEMS = 50;
+ private static final int HEIGHT = 200;
+
+ private ArrayObjectAdapter mAdapter;
+ private Random mRandom;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ Log.i(TAG, "onCreate");
+ super.onCreate(savedInstanceState);
+
+ mRandom = new Random();
+
+ Params p = new Params();
+ p.setBadgeImage(getActivity().getResources().getDrawable(R.drawable.ic_title));
+ p.setTitle("Leanback Vertical Grid Demo");
+ setParams(p);
+
+ setupFragment();
+ }
+
+ private void setupFragment() {
+ VerticalGridPresenter gridPresenter = new VerticalGridPresenter();
+ gridPresenter.setNumberOfColumns(NUM_COLUMNS);
+ setGridPresenter(gridPresenter);
+
+ mAdapter = new ArrayObjectAdapter(new GridItemPresenter());
+ for (int i = 0; i < NUM_ITEMS; i++) {
+ mAdapter.add(new MyItem(i));
+ }
+ setAdapter(mAdapter);
+
+ setOnItemSelectedListener(new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(Object item, Row row) {
+ Log.i(TAG, "item selected: " + ((MyItem) item).id);
+ }
+ });
+
+ setOnItemClickedListener(new OnItemClickedListener() {
+ @Override
+ public void onItemClicked(Object item, Row row) {
+ Log.i(TAG, "item clicked: " + ((MyItem) item).id);
+ }
+ });
+ }
+
+ private class GridItemPresenter extends Presenter {
+ public ViewHolder onCreateViewHolder(ViewGroup parent) {
+ TextView view = new TextView(parent.getContext());
+ // Choose a random height between HEIGHT and 1.5 * HEIGHT to
+ // demonstrate the staggered nature of the grid.
+ final int height = HEIGHT + mRandom.nextInt(HEIGHT / 2);
+ view.setLayoutParams(new ViewGroup.LayoutParams(200, height));
+ view.setFocusable(true);
+ view.setFocusableInTouchMode(true);
+ view.setBackgroundColor(Color.DKGRAY);
+ view.setGravity(Gravity.CENTER);
+ return new ViewHolder(view);
+ }
+
+ public void onBindViewHolder(ViewHolder viewHolder, Object item) {
+ ((TextView) viewHolder.view).setText(Integer.toString(((MyItem) item).id));
+ }
+
+ public void onUnbindViewHolder(ViewHolder viewHolder) {}
+ }
+
+ static class MyItem {
+ int id;
+ MyItem(int id) {
+ this.id = id;
+ }
+ }
+}
diff --git a/samples/browseable/ActionBarCompat-Basic/res/values-v11/template-styles.xml b/samples/browseable/ActionBarCompat-Basic/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/ActionBarCompat-Basic/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/ActionBarCompat-Basic/res/values/template-styles.xml b/samples/browseable/ActionBarCompat-Basic/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/ActionBarCompat-Basic/res/values/template-styles.xml
+++ b/samples/browseable/ActionBarCompat-Basic/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/ActionBarCompat-ListPopupMenu/res/values-v11/template-styles.xml b/samples/browseable/ActionBarCompat-ListPopupMenu/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/ActionBarCompat-ListPopupMenu/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/ActionBarCompat-ListPopupMenu/res/values/template-styles.xml b/samples/browseable/ActionBarCompat-ListPopupMenu/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/ActionBarCompat-ListPopupMenu/res/values/template-styles.xml
+++ b/samples/browseable/ActionBarCompat-ListPopupMenu/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/ActionBarCompat-ShareActionProvider/res/values-v11/template-styles.xml b/samples/browseable/ActionBarCompat-ShareActionProvider/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/ActionBarCompat-ShareActionProvider/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/ActionBarCompat-ShareActionProvider/res/values/template-styles.xml b/samples/browseable/ActionBarCompat-ShareActionProvider/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/ActionBarCompat-ShareActionProvider/res/values/template-styles.xml
+++ b/samples/browseable/ActionBarCompat-ShareActionProvider/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/ActionBarCompat-Styled/res/values-v11/template-styles.xml b/samples/browseable/ActionBarCompat-Styled/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/ActionBarCompat-Styled/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/ActionBarCompat-Styled/res/values/template-styles.xml b/samples/browseable/ActionBarCompat-Styled/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/ActionBarCompat-Styled/res/values/template-styles.xml
+++ b/samples/browseable/ActionBarCompat-Styled/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/ActivityInstrumentation/res/values-v11/template-styles.xml b/samples/browseable/ActivityInstrumentation/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/ActivityInstrumentation/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/ActivityInstrumentation/res/values/template-styles.xml b/samples/browseable/ActivityInstrumentation/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/ActivityInstrumentation/res/values/template-styles.xml
+++ b/samples/browseable/ActivityInstrumentation/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/AdapterTransition/res/menu/fragment_adapter_transition.xml b/samples/browseable/AdapterTransition/res/menu/fragment_adapter_transition.xml
index 2a51b11..10057b8 100644
--- a/samples/browseable/AdapterTransition/res/menu/fragment_adapter_transition.xml
+++ b/samples/browseable/AdapterTransition/res/menu/fragment_adapter_transition.xml
@@ -18,6 +18,6 @@
<item
android:id="@+id/action_toggle"
android:icon="@drawable/ic_action_grid"
- android:showAsAction="always"
- android:title="Toggle view"/>
+ android:showAsAction="always|withText"
+ android:title="@string/show_as_grid"/>
</menu>
diff --git a/samples/browseable/AdapterTransition/res/values-v11/template-styles.xml b/samples/browseable/AdapterTransition/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/AdapterTransition/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/AdapterTransition/res/values-w820dp/dimens.xml b/samples/browseable/AdapterTransition/res/values-w820dp/dimens.xml
deleted file mode 100644
index 63fc816..0000000
--- a/samples/browseable/AdapterTransition/res/values-w820dp/dimens.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<resources>
- <!-- Example customization of dimensions originally defined in res/values/dimens.xml
- (such as screen margins) for screens with more than 820dp of available width. This
- would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
- <dimen name="activity_horizontal_margin">64dp</dimen>
-</resources>
diff --git a/samples/browseable/AdapterTransition/res/values/base-strings.xml b/samples/browseable/AdapterTransition/res/values/base-strings.xml
index 353c67e..ee0c4bd 100644
--- a/samples/browseable/AdapterTransition/res/values/base-strings.xml
+++ b/samples/browseable/AdapterTransition/res/values/base-strings.xml
@@ -23,7 +23,7 @@
<![CDATA[
- Transition cannot be directly applied to AdapterViews. In this sample, we demonstrate how to create a overlay layout and run a Transition on it.
+ Transition cannot be directly applied to AdapterViews. In this sample, we demonstrate how to create an overlay layout and run a Transition on it. Press the action bar button to toggle between ListView and GridView.
]]>
diff --git a/samples/browseable/AdapterTransition/res/values/dimens.xml b/samples/browseable/AdapterTransition/res/values/dimens.xml
deleted file mode 100644
index a0171a7..0000000
--- a/samples/browseable/AdapterTransition/res/values/dimens.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<resources>
- <!-- Default screen margins, per the Android Design guidelines. -->
- <dimen name="activity_horizontal_margin">16dp</dimen>
- <dimen name="activity_vertical_margin">16dp</dimen>
-
- </resources>
diff --git a/samples/browseable/AdapterTransition/res/values/template-styles.xml b/samples/browseable/AdapterTransition/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/AdapterTransition/res/values/template-styles.xml
+++ b/samples/browseable/AdapterTransition/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/AdapterTransition/src/com.example.android.adaptertransition/AdapterTransitionFragment.java b/samples/browseable/AdapterTransition/src/com.example.android.adaptertransition/AdapterTransitionFragment.java
index 525ed40..a949818 100644
--- a/samples/browseable/AdapterTransition/src/com.example.android.adaptertransition/AdapterTransitionFragment.java
+++ b/samples/browseable/AdapterTransition/src/com.example.android.adaptertransition/AdapterTransitionFragment.java
@@ -33,6 +33,7 @@
import android.widget.FrameLayout;
import android.widget.GridView;
import android.widget.ListView;
+import android.widget.Toast;
/**
* Main screen for AdapterTransition sample.
@@ -46,6 +47,11 @@
private static final int ROOT_ID = 1;
/**
+ * A tag for saving state whether the mAbsListView is ListView or GridView.
+ */
+ private static final String STATE_IS_LISTVIEW = "is_listview";
+
+ /**
* This is where we place our AdapterView (ListView / GridView).
*/
private FrameLayout mContent;
@@ -80,20 +86,32 @@
}
@Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- // We use a ListView at first
- mAbsListView = (AbsListView) inflater.inflate(R.layout.fragment_meat_list, container, false);
- mAdapter = new MeatAdapter(inflater, R.layout.item_meat_list);
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ // If savedInstanceState is available, we restore the state whether the list is a ListView
+ // or a GridView.
+ boolean isListView;
+ if (null == savedInstanceState) {
+ isListView = true;
+ } else {
+ isListView = savedInstanceState.getBoolean(STATE_IS_LISTVIEW, true);
+ }
+ inflateAbsList(inflater, container, isListView);
return inflater.inflate(R.layout.fragment_adapter_transition, container, false);
}
@Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putBoolean(STATE_IS_LISTVIEW, mAbsListView instanceof ListView);
+ }
+
+ @Override
public void onViewCreated(View view, Bundle savedInstanceState) {
// Retaining references for FrameLayouts that we use later.
mContent = (FrameLayout) view.findViewById(R.id.content);
mCover = (FrameLayout) view.findViewById(R.id.cover);
// We are attaching the list to the screen here.
- mAbsListView.setAdapter(mAdapter);
mContent.addView(mAbsListView);
}
@@ -109,8 +127,10 @@
if (null != item) {
if (mAbsListView instanceof ListView) {
item.setIcon(R.drawable.ic_action_grid);
+ item.setTitle(R.string.show_as_grid);
} else {
item.setIcon(R.drawable.ic_action_list);
+ item.setTitle(R.string.show_as_list);
}
}
}
@@ -152,6 +172,29 @@
}
/**
+ * Inflate a ListView or a GridView with a corresponding ListAdapter.
+ *
+ * @param inflater The LayoutInflater.
+ * @param container The ViewGroup that contains this AbsListView. The AbsListView won't be
+ * attached to it.
+ * @param inflateListView Pass true to inflate a ListView, or false to inflate a GridView.
+ */
+ private void inflateAbsList(LayoutInflater inflater, ViewGroup container,
+ boolean inflateListView) {
+ if (inflateListView) {
+ mAbsListView = (AbsListView) inflater.inflate(R.layout.fragment_meat_list,
+ container, false);
+ mAdapter = new MeatAdapter(inflater, R.layout.item_meat_list);
+ } else {
+ mAbsListView = (AbsListView) inflater.inflate(R.layout.fragment_meat_grid,
+ container, false);
+ mAdapter = new MeatAdapter(inflater, R.layout.item_meat_grid);
+ }
+ mAbsListView.setAdapter(mAdapter);
+ mAbsListView.setOnItemClickListener(mAdapter);
+ }
+
+ /**
* Toggle the UI between ListView and GridView.
*/
private void toggle() {
@@ -190,15 +233,8 @@
// If the current list is a GridView, we replace it with a ListView. If it is a ListView,
// a GridView.
LayoutInflater inflater = LayoutInflater.from(getActivity());
- if (mAbsListView instanceof GridView) {
- mAbsListView = (AbsListView) inflater.inflate(
- R.layout.fragment_meat_list, (ViewGroup) mAbsListView.getParent(), false);
- mAdapter = new MeatAdapter(inflater, R.layout.item_meat_list);
- } else {
- mAbsListView = (AbsListView) inflater.inflate(
- R.layout.fragment_meat_grid, (ViewGroup) mAbsListView.getParent(), false);
- mAdapter = new MeatAdapter(inflater, R.layout.item_meat_grid);
- }
+ inflateAbsList(inflater, (ViewGroup) mAbsListView.getParent(),
+ mAbsListView instanceof GridView);
mAbsListView.setAdapter(mAdapter);
// We restore the scrolling position here.
mAbsListView.setSelection(first);
diff --git a/samples/browseable/AdapterTransition/src/com.example.android.adaptertransition/MeatAdapter.java b/samples/browseable/AdapterTransition/src/com.example.android.adaptertransition/MeatAdapter.java
index c7630ce..dea4435 100644
--- a/samples/browseable/AdapterTransition/src/com.example.android.adaptertransition/MeatAdapter.java
+++ b/samples/browseable/AdapterTransition/src/com.example.android.adaptertransition/MeatAdapter.java
@@ -16,18 +16,22 @@
package com.example.android.adaptertransition;
+import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.AbsListView;
+import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
+import android.widget.Toast;
/**
* This class provides data as Views. It is designed to support both ListView and GridView by
* changing a layout resource file to inflate.
*/
-public class MeatAdapter extends BaseAdapter {
+public class MeatAdapter extends BaseAdapter implements AbsListView.OnItemClickListener {
private final LayoutInflater mLayoutInflater;
private final int mResourceId;
@@ -80,6 +84,16 @@
return view;
}
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ ViewHolder holder = (ViewHolder) view.getTag();
+ Context context = view.getContext();
+ if (null != holder && null != holder.title && null != context) {
+ Toast.makeText(context, context.getString(R.string.item_clicked,
+ holder.title.getText()), Toast.LENGTH_SHORT).show();
+ }
+ }
+
private static class ViewHolder {
public ImageView image;
public TextView title;
diff --git a/samples/browseable/AdvancedImmersiveMode/res/values-v11/template-styles.xml b/samples/browseable/AdvancedImmersiveMode/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/AdvancedImmersiveMode/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/AdvancedImmersiveMode/res/values/template-styles.xml b/samples/browseable/AdvancedImmersiveMode/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/AdvancedImmersiveMode/res/values/template-styles.xml
+++ b/samples/browseable/AdvancedImmersiveMode/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/AppRestrictions/res/values-v11/template-styles.xml b/samples/browseable/AppRestrictions/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/AppRestrictions/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/AppRestrictions/res/values/template-styles.xml b/samples/browseable/AppRestrictions/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/AppRestrictions/res/values/template-styles.xml
+++ b/samples/browseable/AppRestrictions/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/BasicAccessibility/res/values-v11/template-styles.xml b/samples/browseable/BasicAccessibility/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/BasicAccessibility/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/BasicAccessibility/res/values/template-styles.xml b/samples/browseable/BasicAccessibility/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/BasicAccessibility/res/values/template-styles.xml
+++ b/samples/browseable/BasicAccessibility/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/BasicAndroidKeyStore/res/values-v11/template-styles.xml b/samples/browseable/BasicAndroidKeyStore/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/BasicAndroidKeyStore/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/BasicContactables/res/values-v11/template-styles.xml b/samples/browseable/BasicContactables/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/BasicContactables/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/BasicContactables/res/values/template-styles.xml b/samples/browseable/BasicContactables/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/BasicContactables/res/values/template-styles.xml
+++ b/samples/browseable/BasicContactables/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/BasicGestureDetect/res/layout-sw600dp-land/activity_main.xml b/samples/browseable/BasicGestureDetect/res/layout-sw600dp-land/activity_main.xml
new file mode 100755
index 0000000..653454b
--- /dev/null
+++ b/samples/browseable/BasicGestureDetect/res/layout-sw600dp-land/activity_main.xml
@@ -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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:id="@+id/sample_main_layout">
+ <TextView android:id="@+id/sample_output"
+ style="@style/Widget.SampleMessage"
+ android:background="@android:color/white"
+ android:layout_weight="1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:text="@string/intro_message"
+ android:layout_margin="16dp" />
+ <fragment
+ android:name="com.example.android.common.logger.LogFragment"
+ android:id="@+id/log_fragment"
+ android:layout_weight="1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="16dp" />
+</LinearLayout>
diff --git a/samples/browseable/BasicGestureDetect/res/layout-sw600dp/activity_main.xml b/samples/browseable/BasicGestureDetect/res/layout-sw600dp/activity_main.xml
new file mode 100755
index 0000000..f6f4157
--- /dev/null
+++ b/samples/browseable/BasicGestureDetect/res/layout-sw600dp/activity_main.xml
@@ -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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:id="@+id/sample_main_layout" >
+
+ <TextView android:id="@+id/sample_output"
+ style="@style/Widget.SampleMessage"
+ android:background="@android:color/white"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/intro_message"
+ android:padding="16dp"
+ android:layout_margin="16dp"/>
+ <fragment
+ android:name="com.example.android.common.logger.LogFragment"
+ android:id="@+id/log_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="16dp" />
+</LinearLayout>
diff --git a/samples/browseable/BasicGestureDetect/res/layout/activity_main.xml b/samples/browseable/BasicGestureDetect/res/layout/activity_main.xml
index bc5a575..6f41369 100755
--- a/samples/browseable/BasicGestureDetect/res/layout/activity_main.xml
+++ b/samples/browseable/BasicGestureDetect/res/layout/activity_main.xml
@@ -24,7 +24,8 @@
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:text="@string/intro_message" />
+ android:text="@string/intro_message"
+ android:padding="16dp" />
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
diff --git a/samples/browseable/BasicGestureDetect/res/values-sw600dp/template-styles.xml b/samples/browseable/BasicGestureDetect/res/values-sw600dp/template-styles.xml
index 03d1974..b6ea1a0 100644
--- a/samples/browseable/BasicGestureDetect/res/values-sw600dp/template-styles.xml
+++ b/samples/browseable/BasicGestureDetect/res/values-sw600dp/template-styles.xml
@@ -17,9 +17,17 @@
<resources>
<style name="Widget.SampleMessage">
- <item name="android:textAppearance">?android:textAppearanceLarge</item>
- <item name="android:lineSpacingMultiplier">1.2</item>
+ <item name="android:padding">@dimen/margin_medium</item>
+ <item name="android:textAppearance">?android:textAppearanceMedium</item>
+ <item name="android:lineSpacingMultiplier">1.1</item>
+
+ <item name="android:layout_margin">16dp</item>
<item name="android:shadowDy">-6.5</item>
</style>
+ <style name="Log" parent="Widget.SampleOutput">
+ <item name="android:typeface">monospace</item>
+ </style>
+
+
</resources>
diff --git a/samples/browseable/BasicGestureDetect/res/values-v11/template-styles.xml b/samples/browseable/BasicGestureDetect/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/BasicGestureDetect/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/BasicGestureDetect/src/com.example.android.basicgesturedetect/MainActivity.java b/samples/browseable/BasicGestureDetect/src/com.example.android.basicgesturedetect/MainActivity.java
index 1547807..de4a39f 100644
--- a/samples/browseable/BasicGestureDetect/src/com.example.android.basicgesturedetect/MainActivity.java
+++ b/samples/browseable/BasicGestureDetect/src/com.example.android.basicgesturedetect/MainActivity.java
@@ -19,6 +19,7 @@
package com.example.android.basicgesturedetect;
+import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import android.view.Menu;
@@ -74,6 +75,9 @@
LogFragment logFragment = (LogFragment) getSupportFragmentManager()
.findFragmentById(R.id.log_fragment);
msgFilter.setNext(logFragment.getLogView());
+ logFragment.getLogView().setTextAppearance(this, R.style.Log);
+ logFragment.getLogView().setBackgroundColor(Color.WHITE);
+
Log.i(TAG, "Ready");
}
diff --git a/samples/browseable/BasicImmersiveMode/res/layout-sw600dp-land/activity_main.xml b/samples/browseable/BasicImmersiveMode/res/layout-sw600dp-land/activity_main.xml
new file mode 100755
index 0000000..653454b
--- /dev/null
+++ b/samples/browseable/BasicImmersiveMode/res/layout-sw600dp-land/activity_main.xml
@@ -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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:id="@+id/sample_main_layout">
+ <TextView android:id="@+id/sample_output"
+ style="@style/Widget.SampleMessage"
+ android:background="@android:color/white"
+ android:layout_weight="1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:text="@string/intro_message"
+ android:layout_margin="16dp" />
+ <fragment
+ android:name="com.example.android.common.logger.LogFragment"
+ android:id="@+id/log_fragment"
+ android:layout_weight="1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="16dp" />
+</LinearLayout>
diff --git a/samples/browseable/BasicImmersiveMode/res/layout-sw600dp/activity_main.xml b/samples/browseable/BasicImmersiveMode/res/layout-sw600dp/activity_main.xml
new file mode 100755
index 0000000..f6f4157
--- /dev/null
+++ b/samples/browseable/BasicImmersiveMode/res/layout-sw600dp/activity_main.xml
@@ -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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:id="@+id/sample_main_layout" >
+
+ <TextView android:id="@+id/sample_output"
+ style="@style/Widget.SampleMessage"
+ android:background="@android:color/white"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/intro_message"
+ android:padding="16dp"
+ android:layout_margin="16dp"/>
+ <fragment
+ android:name="com.example.android.common.logger.LogFragment"
+ android:id="@+id/log_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="16dp" />
+</LinearLayout>
diff --git a/samples/browseable/BasicImmersiveMode/res/layout/activity_main.xml b/samples/browseable/BasicImmersiveMode/res/layout/activity_main.xml
index bc5a575..6f41369 100755
--- a/samples/browseable/BasicImmersiveMode/res/layout/activity_main.xml
+++ b/samples/browseable/BasicImmersiveMode/res/layout/activity_main.xml
@@ -24,7 +24,8 @@
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:text="@string/intro_message" />
+ android:text="@string/intro_message"
+ android:padding="16dp" />
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
diff --git a/samples/browseable/BasicImmersiveMode/res/values-sw600dp/template-styles.xml b/samples/browseable/BasicImmersiveMode/res/values-sw600dp/template-styles.xml
index 03d1974..b6ea1a0 100644
--- a/samples/browseable/BasicImmersiveMode/res/values-sw600dp/template-styles.xml
+++ b/samples/browseable/BasicImmersiveMode/res/values-sw600dp/template-styles.xml
@@ -17,9 +17,17 @@
<resources>
<style name="Widget.SampleMessage">
- <item name="android:textAppearance">?android:textAppearanceLarge</item>
- <item name="android:lineSpacingMultiplier">1.2</item>
+ <item name="android:padding">@dimen/margin_medium</item>
+ <item name="android:textAppearance">?android:textAppearanceMedium</item>
+ <item name="android:lineSpacingMultiplier">1.1</item>
+
+ <item name="android:layout_margin">16dp</item>
<item name="android:shadowDy">-6.5</item>
</style>
+ <style name="Log" parent="Widget.SampleOutput">
+ <item name="android:typeface">monospace</item>
+ </style>
+
+
</resources>
diff --git a/samples/browseable/BasicImmersiveMode/res/values-v11/template-styles.xml b/samples/browseable/BasicImmersiveMode/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/BasicImmersiveMode/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/BasicImmersiveMode/src/com.example.android.basicimmersivemode/MainActivity.java b/samples/browseable/BasicImmersiveMode/src/com.example.android.basicimmersivemode/MainActivity.java
index 83e8f0e..0c1bcef 100644
--- a/samples/browseable/BasicImmersiveMode/src/com.example.android.basicimmersivemode/MainActivity.java
+++ b/samples/browseable/BasicImmersiveMode/src/com.example.android.basicimmersivemode/MainActivity.java
@@ -19,6 +19,7 @@
package com.example.android.basicimmersivemode;
+import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import android.view.Menu;
@@ -74,6 +75,9 @@
LogFragment logFragment = (LogFragment) getSupportFragmentManager()
.findFragmentById(R.id.log_fragment);
msgFilter.setNext(logFragment.getLogView());
+ logFragment.getLogView().setTextAppearance(this, R.style.Log);
+ logFragment.getLogView().setBackgroundColor(Color.WHITE);
+
Log.i(TAG, "Ready");
}
diff --git a/samples/browseable/BasicMediaDecoder/res/values-v11/template-styles.xml b/samples/browseable/BasicMediaDecoder/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/BasicMediaDecoder/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/BasicMediaDecoder/res/values/template-styles.xml b/samples/browseable/BasicMediaDecoder/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/BasicMediaDecoder/res/values/template-styles.xml
+++ b/samples/browseable/BasicMediaDecoder/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/BasicMediaRouter/res/values-v11/template-styles.xml b/samples/browseable/BasicMediaRouter/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/BasicMediaRouter/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/BasicMediaRouter/res/values/template-styles.xml b/samples/browseable/BasicMediaRouter/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/BasicMediaRouter/res/values/template-styles.xml
+++ b/samples/browseable/BasicMediaRouter/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/BasicMultitouch/res/values-v11/template-styles.xml b/samples/browseable/BasicMultitouch/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/BasicMultitouch/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/BasicMultitouch/res/values/template-styles.xml b/samples/browseable/BasicMultitouch/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/BasicMultitouch/res/values/template-styles.xml
+++ b/samples/browseable/BasicMultitouch/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/BasicNetworking/res/values-v11/template-styles.xml b/samples/browseable/BasicNetworking/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/BasicNetworking/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/BasicNetworking/res/values/template-styles.xml b/samples/browseable/BasicNetworking/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/BasicNetworking/res/values/template-styles.xml
+++ b/samples/browseable/BasicNetworking/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/BasicNotifications/res/values-v11/template-styles.xml b/samples/browseable/BasicNotifications/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/BasicNotifications/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/BasicNotifications/res/values/template-styles.xml b/samples/browseable/BasicNotifications/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/BasicNotifications/res/values/template-styles.xml
+++ b/samples/browseable/BasicNotifications/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/BasicRenderScript/res/values-v11/template-styles.xml b/samples/browseable/BasicRenderScript/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/BasicRenderScript/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/BasicRenderScript/res/values/template-styles.xml b/samples/browseable/BasicRenderScript/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/BasicRenderScript/res/values/template-styles.xml
+++ b/samples/browseable/BasicRenderScript/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/BasicRenderScript/src/rs/saturation.rs b/samples/browseable/BasicRenderScript/src/rs/saturation.rs
new file mode 100644
index 0000000..cf043d1
--- /dev/null
+++ b/samples/browseable/BasicRenderScript/src/rs/saturation.rs
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.example.android.basicrenderscript)
+#pragma rs_fp_relaxed
+
+const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
+
+float saturationValue = 0.f;
+
+/*
+RenderScript kernel that performs saturation manipulation.
+*/
+uchar4 __attribute__((kernel)) saturation(uchar4 in)
+{
+ float4 f4 = rsUnpackColor8888(in);
+ float3 result = dot(f4.rgb, gMonoMult);
+ result = mix( result, f4.rgb, saturationValue );
+
+ return rsPackColorTo8888(result);
+}
+
diff --git a/samples/browseable/BasicSyncAdapter/res/values-v11/template-styles.xml b/samples/browseable/BasicSyncAdapter/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/BasicSyncAdapter/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/BasicSyncAdapter/res/values/template-styles.xml b/samples/browseable/BasicSyncAdapter/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/BasicSyncAdapter/res/values/template-styles.xml
+++ b/samples/browseable/BasicSyncAdapter/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/BasicTransition/res/layout/scene3.xml b/samples/browseable/BasicTransition/res/layout/scene3.xml
index 06246da..a4cac0f 100644
--- a/samples/browseable/BasicTransition/res/layout/scene3.xml
+++ b/samples/browseable/BasicTransition/res/layout/scene3.xml
@@ -48,7 +48,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
- android:text="@string/this_is_scene_3"
+ android:text="@string/additional_message"
android:textAppearance="?android:attr/textAppearanceLarge"/>
</RelativeLayout>
\ No newline at end of file
diff --git a/samples/browseable/BasicTransition/res/values-v11/template-styles.xml b/samples/browseable/BasicTransition/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/BasicTransition/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/BasicTransition/res/values/template-styles.xml b/samples/browseable/BasicTransition/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/BasicTransition/res/values/template-styles.xml
+++ b/samples/browseable/BasicTransition/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/BatchStepSensor/res/layout/activity_main.xml b/samples/browseable/BatchStepSensor/res/layout/activity_main.xml
index b8a123e..63f1297 100755
--- a/samples/browseable/BatchStepSensor/res/layout/activity_main.xml
+++ b/samples/browseable/BatchStepSensor/res/layout/activity_main.xml
@@ -19,7 +19,7 @@
<fragment
android:id="@+id/fragment_cardstream"
- android:name="com.example.android.batchstepsensor.CardStreamFragment"
+ android:name="com.example.android.batchstepsensor.cardstream.CardStreamFragment"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
diff --git a/samples/browseable/BatchStepSensor/res/layout/card.xml b/samples/browseable/BatchStepSensor/res/layout/card.xml
index 24bffeb..5deb6f5 100644
--- a/samples/browseable/BatchStepSensor/res/layout/card.xml
+++ b/samples/browseable/BatchStepSensor/res/layout/card.xml
@@ -17,7 +17,7 @@
-<com.example.android.batchstepsensor.CardLayout
+<com.example.android.batchstepsensor.cardstream.CardLayout
android:id="@+id/card_layout"
style="@style/Card"
xmlns:android="http://schemas.android.com/apk/res/android"
@@ -71,4 +71,4 @@
android:layout_alignWithParentIfMissing="false"
android:visibility="invisible"/>
-</com.example.android.batchstepsensor.CardLayout>
+</com.example.android.batchstepsensor.cardstream.CardLayout>
diff --git a/samples/browseable/BatchStepSensor/res/layout/card_button_negative.xml b/samples/browseable/BatchStepSensor/res/layout/card_button_negative.xml
index bf66150..7ca9677 100644
--- a/samples/browseable/BatchStepSensor/res/layout/card_button_negative.xml
+++ b/samples/browseable/BatchStepSensor/res/layout/card_button_negative.xml
@@ -17,7 +17,7 @@
-<com.example.android.batchstepsensor.CardActionButton xmlns:android="http://schemas.android.com/apk/res/android"
+<com.example.android.batchstepsensor.cardstream.CardActionButton xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/card_button"
style="@style/CardActionNegative"
android:layout_width="match_parent"
diff --git a/samples/browseable/BatchStepSensor/res/layout/card_button_neutral.xml b/samples/browseable/BatchStepSensor/res/layout/card_button_neutral.xml
index 7f759fc..da74448 100644
--- a/samples/browseable/BatchStepSensor/res/layout/card_button_neutral.xml
+++ b/samples/browseable/BatchStepSensor/res/layout/card_button_neutral.xml
@@ -17,7 +17,7 @@
-<com.example.android.batchstepsensor.CardActionButton xmlns:android="http://schemas.android.com/apk/res/android"
+<com.example.android.batchstepsensor.cardstream.CardActionButton xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/card_button"
style="@style/CardActionNeutral"
android:layout_width="match_parent"
diff --git a/samples/browseable/BatchStepSensor/res/layout/card_button_positive.xml b/samples/browseable/BatchStepSensor/res/layout/card_button_positive.xml
index 2011f9c..afbda8a 100644
--- a/samples/browseable/BatchStepSensor/res/layout/card_button_positive.xml
+++ b/samples/browseable/BatchStepSensor/res/layout/card_button_positive.xml
@@ -17,7 +17,7 @@
-<com.example.android.batchstepsensor.CardActionButton xmlns:android="http://schemas.android.com/apk/res/android"
+<com.example.android.batchstepsensor.cardstream.CardActionButton xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/card_button"
style="@style/CardActionPositive"
android:layout_width="match_parent"
diff --git a/samples/browseable/BatchStepSensor/res/layout/cardstream.xml b/samples/browseable/BatchStepSensor/res/layout/cardstream.xml
index 463af5c..a6b917b 100644
--- a/samples/browseable/BatchStepSensor/res/layout/cardstream.xml
+++ b/samples/browseable/BatchStepSensor/res/layout/cardstream.xml
@@ -22,10 +22,10 @@
android:layout_height="match_parent"
android:fillViewport="true">
- <com.example.android.batchstepsensor.CardStreamLinearLayout
+ <com.example.android.batchstepsensor.cardstream.CardStreamLinearLayout
style="@style/CardStream"
android:id="@+id/card_stream"
android:layout_width="match_parent"
- android:layout_height="match_parent">
- </com.example.android.batchstepsensor.CardStreamLinearLayout>
+ android:layout_height="match_parent"/>
+
</ScrollView>
diff --git a/samples/browseable/BatchStepSensor/res/values-v11/template-styles.xml b/samples/browseable/BatchStepSensor/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/BatchStepSensor/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/BatchStepSensor/res/values/template-styles.xml b/samples/browseable/BatchStepSensor/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/BatchStepSensor/res/values/template-styles.xml
+++ b/samples/browseable/BatchStepSensor/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/BatchStepSensorFragment.java b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/BatchStepSensorFragment.java
index aab0fc3..467c427 100644
--- a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/BatchStepSensorFragment.java
+++ b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/BatchStepSensorFragment.java
@@ -26,6 +26,10 @@
import android.support.v4.app.Fragment;
import com.example.android.common.logger.Log;
+import com.example.android.batchstepsensor.cardstream.Card;
+import com.example.android.batchstepsensor.cardstream.CardStream;
+import com.example.android.batchstepsensor.cardstream.CardStreamFragment;
+import com.example.android.batchstepsensor.cardstream.OnCardClickListener;
public class BatchStepSensorFragment extends Fragment implements OnCardClickListener {
diff --git a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/MainActivity.java b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/MainActivity.java
index bb1f9a1..5e4f7e3 100644
--- a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/MainActivity.java
+++ b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/MainActivity.java
@@ -26,6 +26,12 @@
import com.example.android.common.activities.SampleActivityBase;
import com.example.android.common.logger.Log;
+import com.example.android.batchstepsensor.cardstream.CardStream;
+import com.example.android.batchstepsensor.cardstream.CardStreamFragment;
+import com.example.android.batchstepsensor.cardstream.CardStreamState;
+import com.example.android.batchstepsensor.cardstream.OnCardClickListener;
+import com.example.android.batchstepsensor.cardstream.StreamRetentionFragment;
+
public class MainActivity extends SampleActivityBase implements CardStream {
public static final String TAG = "MainActivity";
public static final String FRAGTAG = "BatchStepSensorFragment";
diff --git a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/Card.java b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/Card.java
similarity index 99%
rename from samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/Card.java
rename to samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/Card.java
index fb885c7..a3723e8 100644
--- a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/Card.java
+++ b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/Card.java
@@ -17,7 +17,7 @@
-package com.example.android.batchstepsensor;
+package com.example.android.batchstepsensor.cardstream;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -31,6 +31,8 @@
import android.widget.ProgressBar;
import android.widget.TextView;
+import com.example.android.batchstepsensor.R;
+
import java.util.ArrayList;
/**
diff --git a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/CardActionButton.java b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardActionButton.java
similarity index 97%
rename from samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/CardActionButton.java
rename to samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardActionButton.java
index ea37e66..01c7094 100644
--- a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/CardActionButton.java
+++ b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardActionButton.java
@@ -17,7 +17,7 @@
-package com.example.android.batchstepsensor;
+package com.example.android.batchstepsensor.cardstream;
import android.content.Context;
import android.util.AttributeSet;
diff --git a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/CardLayout.java b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardLayout.java
similarity index 97%
rename from samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/CardLayout.java
rename to samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardLayout.java
index 8215275..ce20f7f 100644
--- a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/CardLayout.java
+++ b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardLayout.java
@@ -17,7 +17,7 @@
-package com.example.android.batchstepsensor;
+package com.example.android.batchstepsensor.cardstream;
import android.content.Context;
import android.util.AttributeSet;
diff --git a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/CardStream.java b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStream.java
similarity index 92%
rename from samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/CardStream.java
rename to samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStream.java
index 5de9852..70cc5dd 100644
--- a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/CardStream.java
+++ b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStream.java
@@ -17,7 +17,7 @@
-package com.example.android.batchstepsensor;
+package com.example.android.batchstepsensor.cardstream;
public interface CardStream {
public CardStreamFragment getCardStream();
diff --git a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/CardStreamAnimator.java b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStreamAnimator.java
similarity index 98%
rename from samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/CardStreamAnimator.java
rename to samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStreamAnimator.java
index a22ddd7..de06cf6 100644
--- a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/CardStreamAnimator.java
+++ b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStreamAnimator.java
@@ -17,7 +17,7 @@
-package com.example.android.batchstepsensor;
+package com.example.android.batchstepsensor.cardstream;
import android.animation.ObjectAnimator;
import android.content.Context;
diff --git a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/CardStreamFragment.java b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStreamFragment.java
similarity index 98%
rename from samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/CardStreamFragment.java
rename to samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStreamFragment.java
index 9f8b7cb..5388cd9 100644
--- a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/CardStreamFragment.java
+++ b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStreamFragment.java
@@ -17,7 +17,7 @@
-package com.example.android.batchstepsensor;
+package com.example.android.batchstepsensor.cardstream;
import android.os.Bundle;
import android.support.v4.app.Fragment;
@@ -30,6 +30,7 @@
import java.util.HashSet;
import java.util.LinkedHashMap;
+import com.example.android.batchstepsensor.R;
/**
* A Fragment that handles a stream of cards.
diff --git a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/CardStreamLinearLayout.java b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStreamLinearLayout.java
similarity index 99%
rename from samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/CardStreamLinearLayout.java
rename to samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStreamLinearLayout.java
index aeab770..5e4ba15 100644
--- a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/CardStreamLinearLayout.java
+++ b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStreamLinearLayout.java
@@ -17,7 +17,7 @@
-package com.example.android.batchstepsensor;
+package com.example.android.batchstepsensor.cardstream;
import android.animation.Animator;
import android.animation.LayoutTransition;
@@ -38,6 +38,7 @@
import android.widget.ScrollView;
import com.example.android.common.logger.Log;
+import com.example.android.batchstepsensor.R;
import java.util.ArrayList;
diff --git a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/CardStreamState.java b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStreamState.java
similarity index 92%
rename from samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/CardStreamState.java
rename to samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStreamState.java
index 08432a9..57ba177 100644
--- a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/CardStreamState.java
+++ b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStreamState.java
@@ -17,14 +17,14 @@
-package com.example.android.batchstepsensor;
+package com.example.android.batchstepsensor.cardstream;
import java.util.HashSet;
/**
* A struct object that holds the state of a {@link CardStreamFragment}.
*/
-class CardStreamState{
+public class CardStreamState {
protected Card[] visibleCards;
protected Card[] hiddenCards;
protected HashSet<String> dismissibleCards;
diff --git a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/DefaultCardStreamAnimator.java b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/DefaultCardStreamAnimator.java
similarity index 98%
rename from samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/DefaultCardStreamAnimator.java
rename to samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/DefaultCardStreamAnimator.java
index 19ef43b..21e54d3 100644
--- a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/DefaultCardStreamAnimator.java
+++ b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/DefaultCardStreamAnimator.java
@@ -17,7 +17,7 @@
-package com.example.android.batchstepsensor;
+package com.example.android.batchstepsensor.cardstream;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
diff --git a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/OnCardClickListener.java b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/OnCardClickListener.java
similarity index 92%
rename from samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/OnCardClickListener.java
rename to samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/OnCardClickListener.java
index f024110..90ba21e 100644
--- a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/OnCardClickListener.java
+++ b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/OnCardClickListener.java
@@ -17,7 +17,7 @@
-package com.example.android.batchstepsensor;
+package com.example.android.batchstepsensor.cardstream;
public interface OnCardClickListener {
public void onCardClick(int cardActionId, String cardTag);
diff --git a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/StreamRetentionFragment.java b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/StreamRetentionFragment.java
similarity index 94%
rename from samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/StreamRetentionFragment.java
rename to samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/StreamRetentionFragment.java
index 7cd7f2b..51d5428 100644
--- a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/StreamRetentionFragment.java
+++ b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/StreamRetentionFragment.java
@@ -16,7 +16,7 @@
-package com.example.android.batchstepsensor;
+package com.example.android.batchstepsensor.cardstream;
import android.os.Bundle;
import android.support.v4.app.Fragment;
diff --git a/samples/browseable/BluetoothLeGatt/res/values-v11/template-styles.xml b/samples/browseable/BluetoothLeGatt/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/BluetoothLeGatt/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/BluetoothLeGatt/res/values/template-styles.xml b/samples/browseable/BluetoothLeGatt/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/BluetoothLeGatt/res/values/template-styles.xml
+++ b/samples/browseable/BluetoothLeGatt/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/BorderlessButtons/res/values-v11/template-styles.xml b/samples/browseable/BorderlessButtons/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/BorderlessButtons/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/BorderlessButtons/res/values/template-styles.xml b/samples/browseable/BorderlessButtons/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/BorderlessButtons/res/values/template-styles.xml
+++ b/samples/browseable/BorderlessButtons/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/CardEmulation/res/values-v11/template-styles.xml b/samples/browseable/CardEmulation/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/CardEmulation/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/CardEmulation/res/values/template-styles.xml b/samples/browseable/CardEmulation/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/CardEmulation/res/values/template-styles.xml
+++ b/samples/browseable/CardEmulation/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/CardReader/res/values-v11/template-styles.xml b/samples/browseable/CardReader/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/CardReader/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/CardReader/res/values/template-styles.xml b/samples/browseable/CardReader/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/CardReader/res/values/template-styles.xml
+++ b/samples/browseable/CardReader/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/CustomChoiceList/res/values-v11/template-styles.xml b/samples/browseable/CustomChoiceList/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/CustomChoiceList/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/CustomChoiceList/res/values/template-styles.xml b/samples/browseable/CustomChoiceList/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/CustomChoiceList/res/values/template-styles.xml
+++ b/samples/browseable/CustomChoiceList/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/CustomNotifications/res/values-v11/template-styles.xml b/samples/browseable/CustomNotifications/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/CustomNotifications/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/CustomNotifications/res/values/template-styles.xml b/samples/browseable/CustomNotifications/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/CustomNotifications/res/values/template-styles.xml
+++ b/samples/browseable/CustomNotifications/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/CustomTransition/AndroidManifest.xml b/samples/browseable/CustomTransition/AndroidManifest.xml
new file mode 100644
index 0000000..b3328f1
--- /dev/null
+++ b/samples/browseable/CustomTransition/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.customtransition"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <uses-sdk android:minSdkVersion="19" 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/samples/browseable/CustomTransition/_index.jd b/samples/browseable/CustomTransition/_index.jd
new file mode 100644
index 0000000..c68a762
--- /dev/null
+++ b/samples/browseable/CustomTransition/_index.jd
@@ -0,0 +1,8 @@
+
+
+
+page.tags="CustomTransition"
+sample.group=UI
+@jd:body
+
+<p>This sample demonstrates how to create and use a custom {@link android.transition.Transition}.</p>
diff --git a/samples/browseable/CustomTransition/res/drawable-hdpi/ic_launcher.png b/samples/browseable/CustomTransition/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..846a7fe
--- /dev/null
+++ b/samples/browseable/CustomTransition/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/CustomTransition/res/drawable-hdpi/tile.9.png b/samples/browseable/CustomTransition/res/drawable-hdpi/tile.9.png
new file mode 100644
index 0000000..1358628
--- /dev/null
+++ b/samples/browseable/CustomTransition/res/drawable-hdpi/tile.9.png
Binary files differ
diff --git a/samples/browseable/CustomTransition/res/drawable-mdpi/ic_launcher.png b/samples/browseable/CustomTransition/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..7a21d06
--- /dev/null
+++ b/samples/browseable/CustomTransition/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/CustomTransition/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/CustomTransition/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..71734d7
--- /dev/null
+++ b/samples/browseable/CustomTransition/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/CustomTransition/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/CustomTransition/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..d6d9b26
--- /dev/null
+++ b/samples/browseable/CustomTransition/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/CustomTransition/res/layout-w720dp/activity_main.xml b/samples/browseable/CustomTransition/res/layout-w720dp/activity_main.xml
new file mode 100755
index 0000000..c9a52f6
--- /dev/null
+++ b/samples/browseable/CustomTransition/res/layout-w720dp/activity_main.xml
@@ -0,0 +1,73 @@
+<!--
+ 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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/sample_main_layout">
+
+ <LinearLayout
+ android:id="@+id/sample_output"
+ android:layout_width="0px"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:orientation="vertical">
+
+ <FrameLayout
+ style="@style/Widget.SampleMessageTile"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ style="@style/Widget.SampleMessage"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="@dimen/margin_medium"
+ android:paddingRight="@dimen/margin_medium"
+ android:paddingTop="@dimen/margin_large"
+ android:paddingBottom="@dimen/margin_large"
+ android:text="@string/intro_message" />
+ </FrameLayout>
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:background="@android:color/darker_gray" />
+
+ <fragment
+ android:name="com.example.android.common.logger.LogFragment"
+ android:id="@+id/log_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="0px"
+ android:layout_weight="1" />
+
+ </LinearLayout>
+
+ <View
+ android:layout_width="1dp"
+ android:layout_height="match_parent"
+ android:background="@android:color/darker_gray" />
+
+ <FrameLayout
+ android:id="@+id/sample_content_fragment"
+ android:layout_weight="2"
+ android:layout_width="0px"
+ android:layout_height="match_parent" />
+
+</LinearLayout>
+
+
diff --git a/samples/browseable/CustomTransition/res/layout/activity_main.xml b/samples/browseable/CustomTransition/res/layout/activity_main.xml
new file mode 100755
index 0000000..1ae4f98
--- /dev/null
+++ b/samples/browseable/CustomTransition/res/layout/activity_main.xml
@@ -0,0 +1,65 @@
+<!--
+ 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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/sample_main_layout">
+
+ <ViewAnimator
+ android:id="@+id/sample_output"
+ android:layout_width="match_parent"
+ android:layout_height="0px"
+ android:layout_weight="1">
+
+ <ScrollView
+ style="@style/Widget.SampleMessageTile"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <TextView
+ style="@style/Widget.SampleMessage"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="@dimen/horizontal_page_margin"
+ android:paddingRight="@dimen/horizontal_page_margin"
+ android:paddingTop="@dimen/vertical_page_margin"
+ android:paddingBottom="@dimen/vertical_page_margin"
+ android:text="@string/intro_message" />
+ </ScrollView>
+
+ <fragment
+ android:name="com.example.android.common.logger.LogFragment"
+ android:id="@+id/log_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ </ViewAnimator>
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:background="@android:color/darker_gray" />
+
+ <FrameLayout
+ android:id="@+id/sample_content_fragment"
+ android:layout_weight="2"
+ android:layout_width="match_parent"
+ android:layout_height="0px" />
+
+</LinearLayout>
+
diff --git a/samples/browseable/CustomTransition/res/layout/fragment_custom_transition.xml b/samples/browseable/CustomTransition/res/layout/fragment_custom_transition.xml
new file mode 100644
index 0000000..c48f270
--- /dev/null
+++ b/samples/browseable/CustomTransition/res/layout/fragment_custom_transition.xml
@@ -0,0 +1,36 @@
+<?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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ tools:context="com.example.android.customtransition.CustomTransitionFragment">
+
+ <Button
+ android:id="@+id/show_next_scene"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Show next scene"/>
+
+ <FrameLayout
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1"/>
+
+</LinearLayout>
diff --git a/samples/browseable/CustomTransition/res/layout/scene1.xml b/samples/browseable/CustomTransition/res/layout/scene1.xml
new file mode 100644
index 0000000..e686ff7
--- /dev/null
+++ b/samples/browseable/CustomTransition/res/layout/scene1.xml
@@ -0,0 +1,47 @@
+<?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.
+-->
+<LinearLayout
+ android:id="@+id/container"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal"
+ tools:context="com.example.android.customtransition.CustomTransitionFragment">
+
+ <View
+ android:id="@+id/view_1"
+ android:layout_width="64dp"
+ android:layout_height="64dp"
+ android:layout_margin="8dp"
+ android:background="#f00"/>
+
+ <View
+ android:id="@+id/view_2"
+ android:layout_width="64dp"
+ android:layout_height="64dp"
+ android:layout_margin="8dp"
+ android:background="#0f0"/>
+
+ <View
+ android:id="@+id/view_3"
+ android:layout_width="64dp"
+ android:layout_height="64dp"
+ android:layout_margin="8dp"
+ android:background="#00f"/>
+
+</LinearLayout>
diff --git a/samples/browseable/CustomTransition/res/layout/scene2.xml b/samples/browseable/CustomTransition/res/layout/scene2.xml
new file mode 100644
index 0000000..e37e8b0
--- /dev/null
+++ b/samples/browseable/CustomTransition/res/layout/scene2.xml
@@ -0,0 +1,47 @@
+<?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.
+-->
+<LinearLayout
+ android:id="@+id/container"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal"
+ tools:context="com.example.android.customtransition.CustomTransitionFragment">
+
+ <View
+ android:id="@+id/view_1"
+ android:layout_width="64dp"
+ android:layout_height="64dp"
+ android:layout_margin="8dp"
+ android:background="#0f0"/>
+
+ <View
+ android:id="@+id/view_2"
+ android:layout_width="64dp"
+ android:layout_height="64dp"
+ android:layout_margin="8dp"
+ android:background="#00f"/>
+
+ <View
+ android:id="@+id/view_3"
+ android:layout_width="64dp"
+ android:layout_height="64dp"
+ android:layout_margin="8dp"
+ android:background="#f00"/>
+
+</LinearLayout>
diff --git a/samples/browseable/CustomTransition/res/layout/scene3.xml b/samples/browseable/CustomTransition/res/layout/scene3.xml
new file mode 100644
index 0000000..e95fc3c
--- /dev/null
+++ b/samples/browseable/CustomTransition/res/layout/scene3.xml
@@ -0,0 +1,47 @@
+<?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.
+-->
+<LinearLayout
+ android:id="@+id/container"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal"
+ tools:context="com.example.android.customtransition.CustomTransitionFragment">
+
+ <View
+ android:id="@+id/view_1"
+ android:layout_width="64dp"
+ android:layout_height="64dp"
+ android:layout_margin="8dp"
+ android:background="#00f"/>
+
+ <View
+ android:id="@+id/view_2"
+ android:layout_width="64dp"
+ android:layout_height="64dp"
+ android:layout_margin="8dp"
+ android:background="#f00"/>
+
+ <View
+ android:id="@+id/view_3"
+ android:layout_width="64dp"
+ android:layout_height="64dp"
+ android:layout_margin="8dp"
+ android:background="#0f0"/>
+
+</LinearLayout>
diff --git a/samples/browseable/CustomTransition/res/menu/main.xml b/samples/browseable/CustomTransition/res/menu/main.xml
new file mode 100644
index 0000000..b49c2c5
--- /dev/null
+++ b/samples/browseable/CustomTransition/res/menu/main.xml
@@ -0,0 +1,21 @@
+<!--
+ 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.
+ -->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/menu_toggle_log"
+ android:showAsAction="always"
+ android:title="@string/sample_show_log" />
+</menu>
diff --git a/samples/browseable/CustomTransition/res/values-sw600dp/template-dimens.xml b/samples/browseable/CustomTransition/res/values-sw600dp/template-dimens.xml
new file mode 100644
index 0000000..22074a2
--- /dev/null
+++ b/samples/browseable/CustomTransition/res/values-sw600dp/template-dimens.xml
@@ -0,0 +1,24 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Semantic definitions -->
+
+ <dimen name="horizontal_page_margin">@dimen/margin_huge</dimen>
+ <dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
+
+</resources>
diff --git a/samples/browseable/CustomTransition/res/values-sw600dp/template-styles.xml b/samples/browseable/CustomTransition/res/values-sw600dp/template-styles.xml
new file mode 100644
index 0000000..03d1974
--- /dev/null
+++ b/samples/browseable/CustomTransition/res/values-sw600dp/template-styles.xml
@@ -0,0 +1,25 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <style name="Widget.SampleMessage">
+ <item name="android:textAppearance">?android:textAppearanceLarge</item>
+ <item name="android:lineSpacingMultiplier">1.2</item>
+ <item name="android:shadowDy">-6.5</item>
+ </style>
+
+</resources>
diff --git a/samples/browseable/CustomTransition/res/values-v11/template-styles.xml b/samples/browseable/CustomTransition/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/CustomTransition/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/CustomTransition/res/values/base-strings.xml b/samples/browseable/CustomTransition/res/values/base-strings.xml
new file mode 100644
index 0000000..68c9c41
--- /dev/null
+++ b/samples/browseable/CustomTransition/res/values/base-strings.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+
+
+
+<resources>
+ <string name="app_name">CustomTransition</string>
+ <string name="intro_message">
+ <![CDATA[
+
+
+ This sample demonstrates how to create and use a custom Transition.
+
+
+ ]]>
+ </string>
+</resources>
diff --git a/samples/browseable/CustomTransition/res/values/strings.xml b/samples/browseable/CustomTransition/res/values/strings.xml
new file mode 100755
index 0000000..7b9d9ec
--- /dev/null
+++ b/samples/browseable/CustomTransition/res/values/strings.xml
@@ -0,0 +1,19 @@
+<!--
+ 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.
+-->
+<resources>
+ <string name="sample_show_log">Show Log</string>
+ <string name="sample_hide_log">Hide Log</string>
+</resources>
diff --git a/samples/browseable/CustomTransition/res/values/template-dimens.xml b/samples/browseable/CustomTransition/res/values/template-dimens.xml
new file mode 100644
index 0000000..39e710b
--- /dev/null
+++ b/samples/browseable/CustomTransition/res/values/template-dimens.xml
@@ -0,0 +1,32 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Define standard dimensions to comply with Holo-style grids and rhythm. -->
+
+ <dimen name="margin_tiny">4dp</dimen>
+ <dimen name="margin_small">8dp</dimen>
+ <dimen name="margin_medium">16dp</dimen>
+ <dimen name="margin_large">32dp</dimen>
+ <dimen name="margin_huge">64dp</dimen>
+
+ <!-- Semantic definitions -->
+
+ <dimen name="horizontal_page_margin">@dimen/margin_medium</dimen>
+ <dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
+
+</resources>
diff --git a/samples/browseable/CustomTransition/res/values/template-styles.xml b/samples/browseable/CustomTransition/res/values/template-styles.xml
new file mode 100644
index 0000000..6e7d593
--- /dev/null
+++ b/samples/browseable/CustomTransition/res/values/template-styles.xml
@@ -0,0 +1,42 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+
+ <style name="Theme.Base" parent="android:Theme.Light" />
+
+ <style name="Theme.Sample" parent="Theme.Base" />
+
+ <style name="AppTheme" parent="Theme.Sample" />
+ <!-- Widget styling -->
+
+ <style name="Widget" />
+
+ <style name="Widget.SampleMessage">
+ <item name="android:textAppearance">?android:textAppearanceMedium</item>
+ <item name="android:lineSpacingMultiplier">1.1</item>
+ </style>
+
+ <style name="Widget.SampleMessageTile">
+ <item name="android:background">@drawable/tile</item>
+ <item name="android:shadowColor">#7F000000</item>
+ <item name="android:shadowDy">-3.5</item>
+ <item name="android:shadowRadius">2</item>
+ </style>
+
+</resources>
diff --git a/samples/browseable/CustomTransition/src/com.example.android.common/activities/SampleActivityBase.java b/samples/browseable/CustomTransition/src/com.example.android.common/activities/SampleActivityBase.java
new file mode 100644
index 0000000..3228927
--- /dev/null
+++ b/samples/browseable/CustomTransition/src/com.example.android.common/activities/SampleActivityBase.java
@@ -0,0 +1,52 @@
+/*
+* 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.
+*/
+
+package com.example.android.common.activities;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+
+import com.example.android.common.logger.Log;
+import com.example.android.common.logger.LogWrapper;
+
+/**
+ * Base launcher activity, to handle most of the common plumbing for samples.
+ */
+public class SampleActivityBase extends FragmentActivity {
+
+ public static final String TAG = "SampleActivityBase";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ initializeLogging();
+ }
+
+ /** Set up targets to receive log data */
+ public void initializeLogging() {
+ // Using Log, front-end to the logging chain, emulates android.util.log method signatures.
+ // Wraps Android's native log framework
+ LogWrapper logWrapper = new LogWrapper();
+ Log.setLogNode(logWrapper);
+
+ Log.i(TAG, "Ready");
+ }
+}
diff --git a/samples/browseable/CustomTransition/src/com.example.android.common/logger/Log.java b/samples/browseable/CustomTransition/src/com.example.android.common/logger/Log.java
new file mode 100644
index 0000000..17503c5
--- /dev/null
+++ b/samples/browseable/CustomTransition/src/com.example.android.common/logger/Log.java
@@ -0,0 +1,236 @@
+/*
+ * 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.logger;
+
+/**
+ * Helper class for a list (or tree) of LoggerNodes.
+ *
+ * <p>When this is set as the head of the list,
+ * an instance of it can function as a drop-in replacement for {@link android.util.Log}.
+ * Most of the methods in this class server only to map a method call in Log to its equivalent
+ * in LogNode.</p>
+ */
+public class Log {
+ // Grabbing the native values from Android's native logging facilities,
+ // to make for easy migration and interop.
+ public static final int NONE = -1;
+ public static final int VERBOSE = android.util.Log.VERBOSE;
+ public static final int DEBUG = android.util.Log.DEBUG;
+ public static final int INFO = android.util.Log.INFO;
+ public static final int WARN = android.util.Log.WARN;
+ public static final int ERROR = android.util.Log.ERROR;
+ public static final int ASSERT = android.util.Log.ASSERT;
+
+ // Stores the beginning of the LogNode topology.
+ private static LogNode mLogNode;
+
+ /**
+ * Returns the next LogNode in the linked list.
+ */
+ public static LogNode getLogNode() {
+ return mLogNode;
+ }
+
+ /**
+ * Sets the LogNode data will be sent to.
+ */
+ public static void setLogNode(LogNode node) {
+ mLogNode = node;
+ }
+
+ /**
+ * Instructs the LogNode to print the log data provided. Other LogNodes can
+ * be chained to the end of the LogNode as desired.
+ *
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void println(int priority, String tag, String msg, Throwable tr) {
+ if (mLogNode != null) {
+ mLogNode.println(priority, tag, msg, tr);
+ }
+ }
+
+ /**
+ * Instructs the LogNode to print the log data provided. Other LogNodes can
+ * be chained to the end of the LogNode as desired.
+ *
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ */
+ public static void println(int priority, String tag, String msg) {
+ println(priority, tag, msg, null);
+ }
+
+ /**
+ * Prints a message at VERBOSE priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void v(String tag, String msg, Throwable tr) {
+ println(VERBOSE, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at VERBOSE priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void v(String tag, String msg) {
+ v(tag, msg, null);
+ }
+
+
+ /**
+ * Prints a message at DEBUG priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void d(String tag, String msg, Throwable tr) {
+ println(DEBUG, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at DEBUG priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void d(String tag, String msg) {
+ d(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at INFO priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void i(String tag, String msg, Throwable tr) {
+ println(INFO, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at INFO priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void i(String tag, String msg) {
+ i(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at WARN priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void w(String tag, String msg, Throwable tr) {
+ println(WARN, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at WARN priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void w(String tag, String msg) {
+ w(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at WARN priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void w(String tag, Throwable tr) {
+ w(tag, null, tr);
+ }
+
+ /**
+ * Prints a message at ERROR priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void e(String tag, String msg, Throwable tr) {
+ println(ERROR, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at ERROR priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void e(String tag, String msg) {
+ e(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at ASSERT priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void wtf(String tag, String msg, Throwable tr) {
+ println(ASSERT, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at ASSERT priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void wtf(String tag, String msg) {
+ wtf(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at ASSERT priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void wtf(String tag, Throwable tr) {
+ wtf(tag, null, tr);
+ }
+}
diff --git a/samples/browseable/CustomTransition/src/com.example.android.common/logger/LogFragment.java b/samples/browseable/CustomTransition/src/com.example.android.common/logger/LogFragment.java
new file mode 100644
index 0000000..b302acd
--- /dev/null
+++ b/samples/browseable/CustomTransition/src/com.example.android.common/logger/LogFragment.java
@@ -0,0 +1,109 @@
+/*
+* 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 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.logger;
+
+import android.graphics.Typeface;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ScrollView;
+
+/**
+ * Simple fraggment which contains a LogView and uses is to output log data it receives
+ * through the LogNode interface.
+ */
+public class LogFragment extends Fragment {
+
+ private LogView mLogView;
+ private ScrollView mScrollView;
+
+ public LogFragment() {}
+
+ public View inflateViews() {
+ mScrollView = new ScrollView(getActivity());
+ ViewGroup.LayoutParams scrollParams = new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT);
+ mScrollView.setLayoutParams(scrollParams);
+
+ mLogView = new LogView(getActivity());
+ ViewGroup.LayoutParams logParams = new ViewGroup.LayoutParams(scrollParams);
+ logParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+ mLogView.setLayoutParams(logParams);
+ mLogView.setClickable(true);
+ mLogView.setFocusable(true);
+ mLogView.setTypeface(Typeface.MONOSPACE);
+
+ // Want to set padding as 16 dips, setPadding takes pixels. Hooray math!
+ int paddingDips = 16;
+ double scale = getResources().getDisplayMetrics().density;
+ int paddingPixels = (int) ((paddingDips * (scale)) + .5);
+ mLogView.setPadding(paddingPixels, paddingPixels, paddingPixels, paddingPixels);
+ mLogView.setCompoundDrawablePadding(paddingPixels);
+
+ mLogView.setGravity(Gravity.BOTTOM);
+ mLogView.setTextAppearance(getActivity(), android.R.style.TextAppearance_Holo_Medium);
+
+ mScrollView.addView(mLogView);
+ return mScrollView;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+
+ View result = inflateViews();
+
+ mLogView.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {}
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ mScrollView.fullScroll(ScrollView.FOCUS_DOWN);
+ }
+ });
+ return result;
+ }
+
+ public LogView getLogView() {
+ return mLogView;
+ }
+}
\ No newline at end of file
diff --git a/samples/browseable/CustomTransition/src/com.example.android.common/logger/LogNode.java b/samples/browseable/CustomTransition/src/com.example.android.common/logger/LogNode.java
new file mode 100644
index 0000000..bc37cab
--- /dev/null
+++ b/samples/browseable/CustomTransition/src/com.example.android.common/logger/LogNode.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012 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.logger;
+
+/**
+ * Basic interface for a logging system that can output to one or more targets.
+ * Note that in addition to classes that will output these logs in some format,
+ * one can also implement this interface over a filter and insert that in the chain,
+ * such that no targets further down see certain data, or see manipulated forms of the data.
+ * You could, for instance, write a "ToHtmlLoggerNode" that just converted all the log data
+ * it received to HTML and sent it along to the next node in the chain, without printing it
+ * anywhere.
+ */
+public interface LogNode {
+
+ /**
+ * Instructs first LogNode in the list to print the log data provided.
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public void println(int priority, String tag, String msg, Throwable tr);
+
+}
diff --git a/samples/browseable/CustomTransition/src/com.example.android.common/logger/LogView.java b/samples/browseable/CustomTransition/src/com.example.android.common/logger/LogView.java
new file mode 100644
index 0000000..c01542b
--- /dev/null
+++ b/samples/browseable/CustomTransition/src/com.example.android.common/logger/LogView.java
@@ -0,0 +1,145 @@
+/*
+ * 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.logger;
+
+import android.app.Activity;
+import android.content.Context;
+import android.util.*;
+import android.widget.TextView;
+
+/** Simple TextView which is used to output log data received through the LogNode interface.
+*/
+public class LogView extends TextView implements LogNode {
+
+ public LogView(Context context) {
+ super(context);
+ }
+
+ public LogView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public LogView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ /**
+ * Formats the log data and prints it out to the LogView.
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ @Override
+ public void println(int priority, String tag, String msg, Throwable tr) {
+
+
+ String priorityStr = null;
+
+ // For the purposes of this View, we want to print the priority as readable text.
+ switch(priority) {
+ case android.util.Log.VERBOSE:
+ priorityStr = "VERBOSE";
+ break;
+ case android.util.Log.DEBUG:
+ priorityStr = "DEBUG";
+ break;
+ case android.util.Log.INFO:
+ priorityStr = "INFO";
+ break;
+ case android.util.Log.WARN:
+ priorityStr = "WARN";
+ break;
+ case android.util.Log.ERROR:
+ priorityStr = "ERROR";
+ break;
+ case android.util.Log.ASSERT:
+ priorityStr = "ASSERT";
+ break;
+ default:
+ break;
+ }
+
+ // Handily, the Log class has a facility for converting a stack trace into a usable string.
+ String exceptionStr = null;
+ if (tr != null) {
+ exceptionStr = android.util.Log.getStackTraceString(tr);
+ }
+
+ // Take the priority, tag, message, and exception, and concatenate as necessary
+ // into one usable line of text.
+ final StringBuilder outputBuilder = new StringBuilder();
+
+ String delimiter = "\t";
+ appendIfNotNull(outputBuilder, priorityStr, delimiter);
+ appendIfNotNull(outputBuilder, tag, delimiter);
+ appendIfNotNull(outputBuilder, msg, delimiter);
+ appendIfNotNull(outputBuilder, exceptionStr, delimiter);
+
+ // In case this was originally called from an AsyncTask or some other off-UI thread,
+ // make sure the update occurs within the UI thread.
+ ((Activity) getContext()).runOnUiThread( (new Thread(new Runnable() {
+ @Override
+ public void run() {
+ // Display the text we just generated within the LogView.
+ appendToLog(outputBuilder.toString());
+ }
+ })));
+
+ if (mNext != null) {
+ mNext.println(priority, tag, msg, tr);
+ }
+ }
+
+ public LogNode getNext() {
+ return mNext;
+ }
+
+ public void setNext(LogNode node) {
+ mNext = node;
+ }
+
+ /** Takes a string and adds to it, with a separator, if the bit to be added isn't null. Since
+ * the logger takes so many arguments that might be null, this method helps cut out some of the
+ * agonizing tedium of writing the same 3 lines over and over.
+ * @param source StringBuilder containing the text to append to.
+ * @param addStr The String to append
+ * @param delimiter The String to separate the source and appended strings. A tab or comma,
+ * for instance.
+ * @return The fully concatenated String as a StringBuilder
+ */
+ private StringBuilder appendIfNotNull(StringBuilder source, String addStr, String delimiter) {
+ if (addStr != null) {
+ if (addStr.length() == 0) {
+ delimiter = "";
+ }
+
+ return source.append(addStr).append(delimiter);
+ }
+ return source;
+ }
+
+ // The next LogNode in the chain.
+ LogNode mNext;
+
+ /** Outputs the string as a new line of log data in the LogView. */
+ public void appendToLog(String s) {
+ append("\n" + s);
+ }
+
+
+}
diff --git a/samples/browseable/CustomTransition/src/com.example.android.common/logger/LogWrapper.java b/samples/browseable/CustomTransition/src/com.example.android.common/logger/LogWrapper.java
new file mode 100644
index 0000000..16a9e7b
--- /dev/null
+++ b/samples/browseable/CustomTransition/src/com.example.android.common/logger/LogWrapper.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2012 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.logger;
+
+import android.util.Log;
+
+/**
+ * Helper class which wraps Android's native Log utility in the Logger interface. This way
+ * normal DDMS output can be one of the many targets receiving and outputting logs simultaneously.
+ */
+public class LogWrapper implements LogNode {
+
+ // For piping: The next node to receive Log data after this one has done its work.
+ private LogNode mNext;
+
+ /**
+ * Returns the next LogNode in the linked list.
+ */
+ public LogNode getNext() {
+ return mNext;
+ }
+
+ /**
+ * Sets the LogNode data will be sent to..
+ */
+ public void setNext(LogNode node) {
+ mNext = node;
+ }
+
+ /**
+ * Prints data out to the console using Android's native log mechanism.
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ @Override
+ public void println(int priority, String tag, String msg, Throwable tr) {
+ // There actually are log methods that don't take a msg parameter. For now,
+ // if that's the case, just convert null to the empty string and move on.
+ String useMsg = msg;
+ if (useMsg == null) {
+ useMsg = "";
+ }
+
+ // If an exeption was provided, convert that exception to a usable string and attach
+ // it to the end of the msg method.
+ if (tr != null) {
+ msg += "\n" + Log.getStackTraceString(tr);
+ }
+
+ // This is functionally identical to Log.x(tag, useMsg);
+ // For instance, if priority were Log.VERBOSE, this would be the same as Log.v(tag, useMsg)
+ Log.println(priority, tag, useMsg);
+
+ // If this isn't the last node in the chain, move things along.
+ if (mNext != null) {
+ mNext.println(priority, tag, msg, tr);
+ }
+ }
+}
diff --git a/samples/browseable/CustomTransition/src/com.example.android.common/logger/MessageOnlyLogFilter.java b/samples/browseable/CustomTransition/src/com.example.android.common/logger/MessageOnlyLogFilter.java
new file mode 100644
index 0000000..19967dc
--- /dev/null
+++ b/samples/browseable/CustomTransition/src/com.example.android.common/logger/MessageOnlyLogFilter.java
@@ -0,0 +1,60 @@
+/*
+ * 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.logger;
+
+/**
+ * Simple {@link LogNode} filter, removes everything except the message.
+ * Useful for situations like on-screen log output where you don't want a lot of metadata displayed,
+ * just easy-to-read message updates as they're happening.
+ */
+public class MessageOnlyLogFilter implements LogNode {
+
+ LogNode mNext;
+
+ /**
+ * Takes the "next" LogNode as a parameter, to simplify chaining.
+ *
+ * @param next The next LogNode in the pipeline.
+ */
+ public MessageOnlyLogFilter(LogNode next) {
+ mNext = next;
+ }
+
+ public MessageOnlyLogFilter() {
+ }
+
+ @Override
+ public void println(int priority, String tag, String msg, Throwable tr) {
+ if (mNext != null) {
+ getNext().println(Log.NONE, null, msg, null);
+ }
+ }
+
+ /**
+ * Returns the next LogNode in the chain.
+ */
+ public LogNode getNext() {
+ return mNext;
+ }
+
+ /**
+ * Sets the LogNode data will be sent to..
+ */
+ public void setNext(LogNode node) {
+ mNext = node;
+ }
+
+}
diff --git a/samples/browseable/CustomTransition/src/com.example.android.customtransition/ChangeColor.java b/samples/browseable/CustomTransition/src/com.example.android.customtransition/ChangeColor.java
new file mode 100644
index 0000000..d36cfb4
--- /dev/null
+++ b/samples/browseable/CustomTransition/src/com.example.android.customtransition/ChangeColor.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 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.customtransition;
+
+import android.animation.Animator;
+import android.animation.ArgbEvaluator;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.animation.ValueAnimator;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.TransitionDrawable;
+import android.transition.ChangeBounds;
+import android.transition.Transition;
+import android.transition.TransitionValues;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewPropertyAnimator;
+
+public class ChangeColor extends Transition {
+
+ /** Key to store a color value in TransitionValues object */
+ private static final String PROPNAME_BACKGROUND = "customtransition:change_color:background";
+
+ // BEGIN_INCLUDE (capture_values)
+ /**
+ * Convenience method: Add the background Drawable property value
+ * to the TransitionsValues.value Map for a target.
+ */
+ private void captureValues(TransitionValues values) {
+ // Capture the property values of views for later use
+ values.values.put(PROPNAME_BACKGROUND, values.view.getBackground());
+ }
+
+ @Override
+ public void captureStartValues(TransitionValues transitionValues) {
+ captureValues(transitionValues);
+ }
+
+ // Capture the value of the background drawable property for a target in the ending Scene.
+ @Override
+ public void captureEndValues(TransitionValues transitionValues) {
+ captureValues(transitionValues);
+ }
+ // END_INCLUDE (capture_values)
+
+ // BEGIN_INCLUDE (create_animator)
+ // Create an animation for each target that is in both the starting and ending Scene. For each
+ // pair of targets, if their background property value is a color (rather than a graphic),
+ // create a ValueAnimator based on an ArgbEvaluator that interpolates between the starting and
+ // ending color. Also create an update listener that sets the View background color for each
+ // animation frame
+ @Override
+ public Animator createAnimator(ViewGroup sceneRoot,
+ TransitionValues startValues, TransitionValues endValues) {
+ // This transition can only be applied to views that are on both starting and ending scenes.
+ if (null == startValues || null == endValues) {
+ return null;
+ }
+ // Store a convenient reference to the target. Both the starting and ending layout have the
+ // same target.
+ final View view = endValues.view;
+ // Store the object containing the background property for both the starting and ending
+ // layouts.
+ Drawable startBackground = (Drawable) startValues.values.get(PROPNAME_BACKGROUND);
+ Drawable endBackground = (Drawable) endValues.values.get(PROPNAME_BACKGROUND);
+ // This transition changes background colors for a target. It doesn't animate any other
+ // background changes. If the property isn't a ColorDrawable, ignore the target.
+ if (startBackground instanceof ColorDrawable && endBackground instanceof ColorDrawable) {
+ ColorDrawable startColor = (ColorDrawable) startBackground;
+ ColorDrawable endColor = (ColorDrawable) endBackground;
+ // If the background color for the target in the starting and ending layouts is
+ // different, create an animation.
+ if (startColor.getColor() != endColor.getColor()) {
+ // Create a new Animator object to apply to the targets as the transitions framework
+ // changes from the starting to the ending layout. Use the class ValueAnimator,
+ // which provides a timing pulse to change property values provided to it. The
+ // animation runs on the UI thread. The Evaluator controls what type of
+ // interpolation is done. In this case, an ArgbEvaluator interpolates between two
+ // #argb values, which are specified as the 2nd and 3rd input arguments.
+ ValueAnimator animator = ValueAnimator.ofObject(new ArgbEvaluator(),
+ startColor.getColor(), endColor.getColor());
+ // Add an update listener to the Animator object.
+ animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ Object value = animation.getAnimatedValue();
+ // Each time the ValueAnimator produces a new frame in the animation, change
+ // the background color of the target. Ensure that the value isn't null.
+ if (null != value) {
+ view.setBackgroundColor((Integer) value);
+ }
+ }
+ });
+ // Return the Animator object to the transitions framework. As the framework changes
+ // between the starting and ending layouts, it applies the animation you've created.
+ return animator;
+ }
+ }
+ // For non-ColorDrawable backgrounds, we just return null, and no animation will take place.
+ return null;
+ }
+ // END_INCLUDE (create_animator)
+
+}
diff --git a/samples/browseable/CustomTransition/src/com.example.android.customtransition/CustomTransitionFragment.java b/samples/browseable/CustomTransition/src/com.example.android.customtransition/CustomTransitionFragment.java
new file mode 100644
index 0000000..8ef695a
--- /dev/null
+++ b/samples/browseable/CustomTransition/src/com.example.android.customtransition/CustomTransitionFragment.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 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.customtransition;
+
+import com.example.android.common.logger.Log;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.transition.Scene;
+import android.transition.Transition;
+import android.transition.TransitionManager;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+public class CustomTransitionFragment extends Fragment implements View.OnClickListener {
+
+ private static final String STATE_CURRENT_SCENE = "current_scene";
+
+ /** Tag for the logger */
+ private static final String TAG = "CustomTransitionFragment";
+
+ /** These are the Scenes we use. */
+ private Scene[] mScenes;
+
+ /** The current index for mScenes. */
+ private int mCurrentScene;
+
+ /** This is the custom Transition we use in this sample. */
+ private Transition mTransition;
+
+ public CustomTransitionFragment() {
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.fragment_custom_transition, container, false);
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ Context context = getActivity();
+ FrameLayout container = (FrameLayout) view.findViewById(R.id.container);
+ view.findViewById(R.id.show_next_scene).setOnClickListener(this);
+ if (null != savedInstanceState) {
+ mCurrentScene = savedInstanceState.getInt(STATE_CURRENT_SCENE);
+ }
+ // We set up the Scenes here.
+ mScenes = new Scene[] {
+ Scene.getSceneForLayout(container, R.layout.scene1, context),
+ Scene.getSceneForLayout(container, R.layout.scene2, context),
+ Scene.getSceneForLayout(container, R.layout.scene3, context),
+ };
+ // This is the custom Transition.
+ mTransition = new ChangeColor();
+ // Show the initial Scene.
+ TransitionManager.go(mScenes[mCurrentScene % mScenes.length]);
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putInt(STATE_CURRENT_SCENE, mCurrentScene);
+ }
+
+ @Override
+ public void onClick(View v) {
+ switch (v.getId()) {
+ case R.id.show_next_scene: {
+ mCurrentScene = (mCurrentScene + 1) % mScenes.length;
+ Log.i(TAG, "Transitioning to scene #" + mCurrentScene);
+ // Pass the custom Transition as second argument for TransitionManager.go
+ TransitionManager.go(mScenes[mCurrentScene], mTransition);
+ break;
+ }
+ }
+ }
+
+}
diff --git a/samples/browseable/CustomTransition/src/com.example.android.customtransition/MainActivity.java b/samples/browseable/CustomTransition/src/com.example.android.customtransition/MainActivity.java
new file mode 100644
index 0000000..04c4e4d
--- /dev/null
+++ b/samples/browseable/CustomTransition/src/com.example.android.customtransition/MainActivity.java
@@ -0,0 +1,110 @@
+/*
+* 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.
+*/
+
+
+
+
+package com.example.android.customtransition;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentTransaction;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.ViewAnimator;
+
+import com.example.android.common.activities.SampleActivityBase;
+import com.example.android.common.logger.Log;
+import com.example.android.common.logger.LogFragment;
+import com.example.android.common.logger.LogWrapper;
+import com.example.android.common.logger.MessageOnlyLogFilter;
+
+/**
+ * A simple launcher activity containing a summary sample description, sample log and a custom
+ * {@link android.support.v4.app.Fragment} which can display a view.
+ * <p>
+ * For devices with displays with a width of 720dp or greater, the sample log is always visible,
+ * on other devices it's visibility is controlled by an item on the Action Bar.
+ */
+public class MainActivity extends SampleActivityBase {
+
+ public static final String TAG = "MainActivity";
+
+ // Whether the Log Fragment is currently shown
+ private boolean mLogShown;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+ CustomTransitionFragment fragment = new CustomTransitionFragment();
+ transaction.replace(R.id.sample_content_fragment, fragment);
+ transaction.commit();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.main, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ MenuItem logToggle = menu.findItem(R.id.menu_toggle_log);
+ logToggle.setVisible(findViewById(R.id.sample_output) instanceof ViewAnimator);
+ logToggle.setTitle(mLogShown ? R.string.sample_hide_log : R.string.sample_show_log);
+
+ return super.onPrepareOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch(item.getItemId()) {
+ case R.id.menu_toggle_log:
+ mLogShown = !mLogShown;
+ ViewAnimator output = (ViewAnimator) findViewById(R.id.sample_output);
+ if (mLogShown) {
+ output.setDisplayedChild(1);
+ } else {
+ output.setDisplayedChild(0);
+ }
+ supportInvalidateOptionsMenu();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ /** Create a chain of targets that will receive log data */
+ @Override
+ public void initializeLogging() {
+ // Wraps Android's native log framework.
+ LogWrapper logWrapper = new LogWrapper();
+ // Using Log, front-end to the logging chain, emulates android.util.log method signatures.
+ Log.setLogNode(logWrapper);
+
+ // Filter strips out everything except the message text.
+ MessageOnlyLogFilter msgFilter = new MessageOnlyLogFilter();
+ logWrapper.setNext(msgFilter);
+
+ // On screen logging via a fragment with a TextView.
+ LogFragment logFragment = (LogFragment) getSupportFragmentManager()
+ .findFragmentById(R.id.log_fragment);
+ msgFilter.setNext(logFragment.getLogView());
+
+ Log.i(TAG, "Ready");
+ }
+}
diff --git a/samples/browseable/DisplayingBitmaps/res/values-v11/template-styles.xml b/samples/browseable/DisplayingBitmaps/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/DisplayingBitmaps/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/DisplayingBitmaps/res/values/template-styles.xml b/samples/browseable/DisplayingBitmaps/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/DisplayingBitmaps/res/values/template-styles.xml
+++ b/samples/browseable/DisplayingBitmaps/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/DoneBar/res/values-v11/template-styles.xml b/samples/browseable/DoneBar/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/DoneBar/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/FragmentTransition/AndroidManifest.xml b/samples/browseable/FragmentTransition/AndroidManifest.xml
new file mode 100644
index 0000000..8d02eb0
--- /dev/null
+++ b/samples/browseable/FragmentTransition/AndroidManifest.xml
@@ -0,0 +1,40 @@
+<?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.fragmenttransition"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="19" />
+
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ <activity
+ android:name="com.example.android.fragmenttransition.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/samples/browseable/FragmentTransition/_index.jd b/samples/browseable/FragmentTransition/_index.jd
new file mode 100644
index 0000000..f0efe32
--- /dev/null
+++ b/samples/browseable/FragmentTransition/_index.jd
@@ -0,0 +1,8 @@
+
+
+
+page.tags="FragmentTransition"
+sample.group=UI
+@jd:body
+
+<p>This sample demonstrates how to start a transition right after a fragment transaction.</p>
diff --git a/samples/browseable/FragmentTransition/res/drawable-hdpi/ic_launcher.png b/samples/browseable/FragmentTransition/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..dfa1b45
--- /dev/null
+++ b/samples/browseable/FragmentTransition/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/FragmentTransition/res/drawable-hdpi/tile.9.png b/samples/browseable/FragmentTransition/res/drawable-hdpi/tile.9.png
new file mode 100644
index 0000000..1358628
--- /dev/null
+++ b/samples/browseable/FragmentTransition/res/drawable-hdpi/tile.9.png
Binary files differ
diff --git a/samples/browseable/FragmentTransition/res/drawable-mdpi/ic_launcher.png b/samples/browseable/FragmentTransition/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..5f4ae7b
--- /dev/null
+++ b/samples/browseable/FragmentTransition/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/FragmentTransition/res/drawable-nodpi/p1.jpg b/samples/browseable/FragmentTransition/res/drawable-nodpi/p1.jpg
new file mode 100644
index 0000000..10f07ac
--- /dev/null
+++ b/samples/browseable/FragmentTransition/res/drawable-nodpi/p1.jpg
Binary files differ
diff --git a/samples/browseable/FragmentTransition/res/drawable-nodpi/p10.jpg b/samples/browseable/FragmentTransition/res/drawable-nodpi/p10.jpg
new file mode 100644
index 0000000..4272f4c
--- /dev/null
+++ b/samples/browseable/FragmentTransition/res/drawable-nodpi/p10.jpg
Binary files differ
diff --git a/samples/browseable/FragmentTransition/res/drawable-nodpi/p11.jpg b/samples/browseable/FragmentTransition/res/drawable-nodpi/p11.jpg
new file mode 100644
index 0000000..c5722b2
--- /dev/null
+++ b/samples/browseable/FragmentTransition/res/drawable-nodpi/p11.jpg
Binary files differ
diff --git a/samples/browseable/FragmentTransition/res/drawable-nodpi/p2.jpg b/samples/browseable/FragmentTransition/res/drawable-nodpi/p2.jpg
new file mode 100644
index 0000000..ca380ae
--- /dev/null
+++ b/samples/browseable/FragmentTransition/res/drawable-nodpi/p2.jpg
Binary files differ
diff --git a/samples/browseable/FragmentTransition/res/drawable-nodpi/p3.jpg b/samples/browseable/FragmentTransition/res/drawable-nodpi/p3.jpg
new file mode 100644
index 0000000..6fc71e7
--- /dev/null
+++ b/samples/browseable/FragmentTransition/res/drawable-nodpi/p3.jpg
Binary files differ
diff --git a/samples/browseable/FragmentTransition/res/drawable-nodpi/p4.jpg b/samples/browseable/FragmentTransition/res/drawable-nodpi/p4.jpg
new file mode 100644
index 0000000..153c1ff
--- /dev/null
+++ b/samples/browseable/FragmentTransition/res/drawable-nodpi/p4.jpg
Binary files differ
diff --git a/samples/browseable/FragmentTransition/res/drawable-nodpi/p5.jpg b/samples/browseable/FragmentTransition/res/drawable-nodpi/p5.jpg
new file mode 100644
index 0000000..46d6a13
--- /dev/null
+++ b/samples/browseable/FragmentTransition/res/drawable-nodpi/p5.jpg
Binary files differ
diff --git a/samples/browseable/FragmentTransition/res/drawable-nodpi/p6.jpg b/samples/browseable/FragmentTransition/res/drawable-nodpi/p6.jpg
new file mode 100644
index 0000000..89ccb83
--- /dev/null
+++ b/samples/browseable/FragmentTransition/res/drawable-nodpi/p6.jpg
Binary files differ
diff --git a/samples/browseable/FragmentTransition/res/drawable-nodpi/p7.jpg b/samples/browseable/FragmentTransition/res/drawable-nodpi/p7.jpg
new file mode 100644
index 0000000..7e9546d
--- /dev/null
+++ b/samples/browseable/FragmentTransition/res/drawable-nodpi/p7.jpg
Binary files differ
diff --git a/samples/browseable/FragmentTransition/res/drawable-nodpi/p8.jpg b/samples/browseable/FragmentTransition/res/drawable-nodpi/p8.jpg
new file mode 100644
index 0000000..21e25ba
--- /dev/null
+++ b/samples/browseable/FragmentTransition/res/drawable-nodpi/p8.jpg
Binary files differ
diff --git a/samples/browseable/FragmentTransition/res/drawable-nodpi/p9.jpg b/samples/browseable/FragmentTransition/res/drawable-nodpi/p9.jpg
new file mode 100644
index 0000000..79854cb
--- /dev/null
+++ b/samples/browseable/FragmentTransition/res/drawable-nodpi/p9.jpg
Binary files differ
diff --git a/samples/browseable/FragmentTransition/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/FragmentTransition/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..5e00f33
--- /dev/null
+++ b/samples/browseable/FragmentTransition/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/FragmentTransition/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/FragmentTransition/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..e061498
--- /dev/null
+++ b/samples/browseable/FragmentTransition/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/FragmentTransition/res/layout-w720dp/activity_main.xml b/samples/browseable/FragmentTransition/res/layout-w720dp/activity_main.xml
new file mode 100755
index 0000000..c9a52f6
--- /dev/null
+++ b/samples/browseable/FragmentTransition/res/layout-w720dp/activity_main.xml
@@ -0,0 +1,73 @@
+<!--
+ 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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/sample_main_layout">
+
+ <LinearLayout
+ android:id="@+id/sample_output"
+ android:layout_width="0px"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:orientation="vertical">
+
+ <FrameLayout
+ style="@style/Widget.SampleMessageTile"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ style="@style/Widget.SampleMessage"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="@dimen/margin_medium"
+ android:paddingRight="@dimen/margin_medium"
+ android:paddingTop="@dimen/margin_large"
+ android:paddingBottom="@dimen/margin_large"
+ android:text="@string/intro_message" />
+ </FrameLayout>
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:background="@android:color/darker_gray" />
+
+ <fragment
+ android:name="com.example.android.common.logger.LogFragment"
+ android:id="@+id/log_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="0px"
+ android:layout_weight="1" />
+
+ </LinearLayout>
+
+ <View
+ android:layout_width="1dp"
+ android:layout_height="match_parent"
+ android:background="@android:color/darker_gray" />
+
+ <FrameLayout
+ android:id="@+id/sample_content_fragment"
+ android:layout_weight="2"
+ android:layout_width="0px"
+ android:layout_height="match_parent" />
+
+</LinearLayout>
+
+
diff --git a/samples/browseable/FragmentTransition/res/layout/activity_main.xml b/samples/browseable/FragmentTransition/res/layout/activity_main.xml
new file mode 100755
index 0000000..1ae4f98
--- /dev/null
+++ b/samples/browseable/FragmentTransition/res/layout/activity_main.xml
@@ -0,0 +1,65 @@
+<!--
+ 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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/sample_main_layout">
+
+ <ViewAnimator
+ android:id="@+id/sample_output"
+ android:layout_width="match_parent"
+ android:layout_height="0px"
+ android:layout_weight="1">
+
+ <ScrollView
+ style="@style/Widget.SampleMessageTile"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <TextView
+ style="@style/Widget.SampleMessage"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="@dimen/horizontal_page_margin"
+ android:paddingRight="@dimen/horizontal_page_margin"
+ android:paddingTop="@dimen/vertical_page_margin"
+ android:paddingBottom="@dimen/vertical_page_margin"
+ android:text="@string/intro_message" />
+ </ScrollView>
+
+ <fragment
+ android:name="com.example.android.common.logger.LogFragment"
+ android:id="@+id/log_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ </ViewAnimator>
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:background="@android:color/darker_gray" />
+
+ <FrameLayout
+ android:id="@+id/sample_content_fragment"
+ android:layout_weight="2"
+ android:layout_width="match_parent"
+ android:layout_height="0px" />
+
+</LinearLayout>
+
diff --git a/samples/browseable/FragmentTransition/res/layout/fragment_detail.xml b/samples/browseable/FragmentTransition/res/layout/fragment_detail.xml
new file mode 100644
index 0000000..d94256f
--- /dev/null
+++ b/samples/browseable/FragmentTransition/res/layout/fragment_detail.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+<FrameLayout
+ android:id="@+id/container"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"/>
diff --git a/samples/browseable/FragmentTransition/res/layout/fragment_detail_content.xml b/samples/browseable/FragmentTransition/res/layout/fragment_detail_content.xml
new file mode 100644
index 0000000..2068460
--- /dev/null
+++ b/samples/browseable/FragmentTransition/res/layout/fragment_detail_content.xml
@@ -0,0 +1,66 @@
+<?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.
+-->
+<ScrollView
+ android:id="@+id/frame"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scrollbars="none">
+
+ <RelativeLayout
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <ImageView
+ android:id="@+id/image"
+ android:layout_width="match_parent"
+ android:layout_height="180dp"
+ android:scaleType="centerCrop"
+ tools:src="@drawable/p1"/>
+
+ <TextView
+ android:id="@+id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignBottom="@id/image"
+ android:layout_alignEnd="@id/image"
+ android:layout_marginEnd="16dp"
+ android:shadowColor="#000000"
+ android:shadowDx="0"
+ android:shadowDy="0"
+ android:shadowRadius="10"
+ android:textColor="#ffffff"
+ android:textSize="24sp"
+ android:textStyle="bold"
+ tools:text="Image"/>
+
+ <TextView
+ android:id="@+id/body"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/image"
+ android:layout_marginBottom="16dp"
+ android:layout_marginEnd="16dp"
+ android:layout_marginStart="16dp"
+ android:layout_marginTop="16dp"
+ android:text="@string/lorem_ipsum"/>
+
+ </RelativeLayout>
+
+</ScrollView>
\ No newline at end of file
diff --git a/samples/browseable/FragmentTransition/res/layout/fragment_fragment_transition.xml b/samples/browseable/FragmentTransition/res/layout/fragment_fragment_transition.xml
new file mode 100644
index 0000000..6e1c7a1
--- /dev/null
+++ b/samples/browseable/FragmentTransition/res/layout/fragment_fragment_transition.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+<GridView
+ android:id="@+id/grid"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:clipToPadding="false"
+ android:columnWidth="150dp"
+ android:horizontalSpacing="1dp"
+ android:numColumns="auto_fit"
+ android:padding="1dp"
+ android:scrollbars="none"
+ android:stretchMode="columnWidth"
+ android:verticalSpacing="1dp"
+ tools:context="com.example.android.fragmenttransition.FragmentTransitionFragment"/>
diff --git a/samples/browseable/FragmentTransition/res/layout/item_meat_grid.xml b/samples/browseable/FragmentTransition/res/layout/item_meat_grid.xml
new file mode 100644
index 0000000..df34883
--- /dev/null
+++ b/samples/browseable/FragmentTransition/res/layout/item_meat_grid.xml
@@ -0,0 +1,58 @@
+<?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.
+-->
+<FrameLayout
+ android:id="@+id/frame"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <RelativeLayout
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="150dp"
+ tools:ignore="UselessParent">
+
+ <ImageView
+ android:id="@+id/image"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scaleType="centerCrop"
+ tools:src="@drawable/p1"/>
+
+ <TextView
+ android:id="@+id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentEnd="true"
+ android:layout_gravity="bottom|end"
+ android:layout_marginEnd="16dp"
+ android:layout_marginStart="16dp"
+ android:gravity="center_horizontal"
+ android:shadowColor="#000000"
+ android:shadowDx="0"
+ android:shadowDy="0"
+ android:shadowRadius="10"
+ android:textColor="#ffffff"
+ android:textSize="24sp"
+ android:textStyle="bold"
+ tools:text="Hello"/>
+
+ </RelativeLayout>
+
+</FrameLayout>
diff --git a/samples/browseable/FragmentTransition/res/menu/main.xml b/samples/browseable/FragmentTransition/res/menu/main.xml
new file mode 100644
index 0000000..b49c2c5
--- /dev/null
+++ b/samples/browseable/FragmentTransition/res/menu/main.xml
@@ -0,0 +1,21 @@
+<!--
+ 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.
+ -->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/menu_toggle_log"
+ android:showAsAction="always"
+ android:title="@string/sample_show_log" />
+</menu>
diff --git a/samples/browseable/FragmentTransition/res/values-sw600dp/template-dimens.xml b/samples/browseable/FragmentTransition/res/values-sw600dp/template-dimens.xml
new file mode 100644
index 0000000..22074a2
--- /dev/null
+++ b/samples/browseable/FragmentTransition/res/values-sw600dp/template-dimens.xml
@@ -0,0 +1,24 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Semantic definitions -->
+
+ <dimen name="horizontal_page_margin">@dimen/margin_huge</dimen>
+ <dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
+
+</resources>
diff --git a/samples/browseable/FragmentTransition/res/values-sw600dp/template-styles.xml b/samples/browseable/FragmentTransition/res/values-sw600dp/template-styles.xml
new file mode 100644
index 0000000..03d1974
--- /dev/null
+++ b/samples/browseable/FragmentTransition/res/values-sw600dp/template-styles.xml
@@ -0,0 +1,25 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <style name="Widget.SampleMessage">
+ <item name="android:textAppearance">?android:textAppearanceLarge</item>
+ <item name="android:lineSpacingMultiplier">1.2</item>
+ <item name="android:shadowDy">-6.5</item>
+ </style>
+
+</resources>
diff --git a/samples/browseable/FragmentTransition/res/values-v11/template-styles.xml b/samples/browseable/FragmentTransition/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/FragmentTransition/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/FragmentTransition/res/values/base-strings.xml b/samples/browseable/FragmentTransition/res/values/base-strings.xml
new file mode 100644
index 0000000..933e1f2
--- /dev/null
+++ b/samples/browseable/FragmentTransition/res/values/base-strings.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+
+
+
+<resources>
+ <string name="app_name">FragmentTransition</string>
+ <string name="intro_message">
+ <![CDATA[
+
+
+ This sample demonstrates how to start a transition right after a fragment transaction.
+
+
+ ]]>
+ </string>
+</resources>
diff --git a/samples/browseable/FragmentTransition/res/values/strings.xml b/samples/browseable/FragmentTransition/res/values/strings.xml
new file mode 100755
index 0000000..7b9d9ec
--- /dev/null
+++ b/samples/browseable/FragmentTransition/res/values/strings.xml
@@ -0,0 +1,19 @@
+<!--
+ 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.
+-->
+<resources>
+ <string name="sample_show_log">Show Log</string>
+ <string name="sample_hide_log">Hide Log</string>
+</resources>
diff --git a/samples/browseable/FragmentTransition/res/values/template-dimens.xml b/samples/browseable/FragmentTransition/res/values/template-dimens.xml
new file mode 100644
index 0000000..39e710b
--- /dev/null
+++ b/samples/browseable/FragmentTransition/res/values/template-dimens.xml
@@ -0,0 +1,32 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Define standard dimensions to comply with Holo-style grids and rhythm. -->
+
+ <dimen name="margin_tiny">4dp</dimen>
+ <dimen name="margin_small">8dp</dimen>
+ <dimen name="margin_medium">16dp</dimen>
+ <dimen name="margin_large">32dp</dimen>
+ <dimen name="margin_huge">64dp</dimen>
+
+ <!-- Semantic definitions -->
+
+ <dimen name="horizontal_page_margin">@dimen/margin_medium</dimen>
+ <dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
+
+</resources>
diff --git a/samples/browseable/FragmentTransition/res/values/template-styles.xml b/samples/browseable/FragmentTransition/res/values/template-styles.xml
new file mode 100644
index 0000000..6e7d593
--- /dev/null
+++ b/samples/browseable/FragmentTransition/res/values/template-styles.xml
@@ -0,0 +1,42 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+
+ <style name="Theme.Base" parent="android:Theme.Light" />
+
+ <style name="Theme.Sample" parent="Theme.Base" />
+
+ <style name="AppTheme" parent="Theme.Sample" />
+ <!-- Widget styling -->
+
+ <style name="Widget" />
+
+ <style name="Widget.SampleMessage">
+ <item name="android:textAppearance">?android:textAppearanceMedium</item>
+ <item name="android:lineSpacingMultiplier">1.1</item>
+ </style>
+
+ <style name="Widget.SampleMessageTile">
+ <item name="android:background">@drawable/tile</item>
+ <item name="android:shadowColor">#7F000000</item>
+ <item name="android:shadowDy">-3.5</item>
+ <item name="android:shadowRadius">2</item>
+ </style>
+
+</resources>
diff --git a/samples/browseable/FragmentTransition/src/com.example.android.common/activities/SampleActivityBase.java b/samples/browseable/FragmentTransition/src/com.example.android.common/activities/SampleActivityBase.java
new file mode 100644
index 0000000..3228927
--- /dev/null
+++ b/samples/browseable/FragmentTransition/src/com.example.android.common/activities/SampleActivityBase.java
@@ -0,0 +1,52 @@
+/*
+* 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.
+*/
+
+package com.example.android.common.activities;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+
+import com.example.android.common.logger.Log;
+import com.example.android.common.logger.LogWrapper;
+
+/**
+ * Base launcher activity, to handle most of the common plumbing for samples.
+ */
+public class SampleActivityBase extends FragmentActivity {
+
+ public static final String TAG = "SampleActivityBase";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ initializeLogging();
+ }
+
+ /** Set up targets to receive log data */
+ public void initializeLogging() {
+ // Using Log, front-end to the logging chain, emulates android.util.log method signatures.
+ // Wraps Android's native log framework
+ LogWrapper logWrapper = new LogWrapper();
+ Log.setLogNode(logWrapper);
+
+ Log.i(TAG, "Ready");
+ }
+}
diff --git a/samples/browseable/FragmentTransition/src/com.example.android.common/logger/Log.java b/samples/browseable/FragmentTransition/src/com.example.android.common/logger/Log.java
new file mode 100644
index 0000000..17503c5
--- /dev/null
+++ b/samples/browseable/FragmentTransition/src/com.example.android.common/logger/Log.java
@@ -0,0 +1,236 @@
+/*
+ * 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.logger;
+
+/**
+ * Helper class for a list (or tree) of LoggerNodes.
+ *
+ * <p>When this is set as the head of the list,
+ * an instance of it can function as a drop-in replacement for {@link android.util.Log}.
+ * Most of the methods in this class server only to map a method call in Log to its equivalent
+ * in LogNode.</p>
+ */
+public class Log {
+ // Grabbing the native values from Android's native logging facilities,
+ // to make for easy migration and interop.
+ public static final int NONE = -1;
+ public static final int VERBOSE = android.util.Log.VERBOSE;
+ public static final int DEBUG = android.util.Log.DEBUG;
+ public static final int INFO = android.util.Log.INFO;
+ public static final int WARN = android.util.Log.WARN;
+ public static final int ERROR = android.util.Log.ERROR;
+ public static final int ASSERT = android.util.Log.ASSERT;
+
+ // Stores the beginning of the LogNode topology.
+ private static LogNode mLogNode;
+
+ /**
+ * Returns the next LogNode in the linked list.
+ */
+ public static LogNode getLogNode() {
+ return mLogNode;
+ }
+
+ /**
+ * Sets the LogNode data will be sent to.
+ */
+ public static void setLogNode(LogNode node) {
+ mLogNode = node;
+ }
+
+ /**
+ * Instructs the LogNode to print the log data provided. Other LogNodes can
+ * be chained to the end of the LogNode as desired.
+ *
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void println(int priority, String tag, String msg, Throwable tr) {
+ if (mLogNode != null) {
+ mLogNode.println(priority, tag, msg, tr);
+ }
+ }
+
+ /**
+ * Instructs the LogNode to print the log data provided. Other LogNodes can
+ * be chained to the end of the LogNode as desired.
+ *
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ */
+ public static void println(int priority, String tag, String msg) {
+ println(priority, tag, msg, null);
+ }
+
+ /**
+ * Prints a message at VERBOSE priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void v(String tag, String msg, Throwable tr) {
+ println(VERBOSE, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at VERBOSE priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void v(String tag, String msg) {
+ v(tag, msg, null);
+ }
+
+
+ /**
+ * Prints a message at DEBUG priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void d(String tag, String msg, Throwable tr) {
+ println(DEBUG, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at DEBUG priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void d(String tag, String msg) {
+ d(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at INFO priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void i(String tag, String msg, Throwable tr) {
+ println(INFO, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at INFO priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void i(String tag, String msg) {
+ i(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at WARN priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void w(String tag, String msg, Throwable tr) {
+ println(WARN, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at WARN priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void w(String tag, String msg) {
+ w(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at WARN priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void w(String tag, Throwable tr) {
+ w(tag, null, tr);
+ }
+
+ /**
+ * Prints a message at ERROR priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void e(String tag, String msg, Throwable tr) {
+ println(ERROR, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at ERROR priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void e(String tag, String msg) {
+ e(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at ASSERT priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void wtf(String tag, String msg, Throwable tr) {
+ println(ASSERT, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at ASSERT priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void wtf(String tag, String msg) {
+ wtf(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at ASSERT priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void wtf(String tag, Throwable tr) {
+ wtf(tag, null, tr);
+ }
+}
diff --git a/samples/browseable/FragmentTransition/src/com.example.android.common/logger/LogFragment.java b/samples/browseable/FragmentTransition/src/com.example.android.common/logger/LogFragment.java
new file mode 100644
index 0000000..b302acd
--- /dev/null
+++ b/samples/browseable/FragmentTransition/src/com.example.android.common/logger/LogFragment.java
@@ -0,0 +1,109 @@
+/*
+* 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 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.logger;
+
+import android.graphics.Typeface;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ScrollView;
+
+/**
+ * Simple fraggment which contains a LogView and uses is to output log data it receives
+ * through the LogNode interface.
+ */
+public class LogFragment extends Fragment {
+
+ private LogView mLogView;
+ private ScrollView mScrollView;
+
+ public LogFragment() {}
+
+ public View inflateViews() {
+ mScrollView = new ScrollView(getActivity());
+ ViewGroup.LayoutParams scrollParams = new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT);
+ mScrollView.setLayoutParams(scrollParams);
+
+ mLogView = new LogView(getActivity());
+ ViewGroup.LayoutParams logParams = new ViewGroup.LayoutParams(scrollParams);
+ logParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+ mLogView.setLayoutParams(logParams);
+ mLogView.setClickable(true);
+ mLogView.setFocusable(true);
+ mLogView.setTypeface(Typeface.MONOSPACE);
+
+ // Want to set padding as 16 dips, setPadding takes pixels. Hooray math!
+ int paddingDips = 16;
+ double scale = getResources().getDisplayMetrics().density;
+ int paddingPixels = (int) ((paddingDips * (scale)) + .5);
+ mLogView.setPadding(paddingPixels, paddingPixels, paddingPixels, paddingPixels);
+ mLogView.setCompoundDrawablePadding(paddingPixels);
+
+ mLogView.setGravity(Gravity.BOTTOM);
+ mLogView.setTextAppearance(getActivity(), android.R.style.TextAppearance_Holo_Medium);
+
+ mScrollView.addView(mLogView);
+ return mScrollView;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+
+ View result = inflateViews();
+
+ mLogView.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {}
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ mScrollView.fullScroll(ScrollView.FOCUS_DOWN);
+ }
+ });
+ return result;
+ }
+
+ public LogView getLogView() {
+ return mLogView;
+ }
+}
\ No newline at end of file
diff --git a/samples/browseable/FragmentTransition/src/com.example.android.common/logger/LogNode.java b/samples/browseable/FragmentTransition/src/com.example.android.common/logger/LogNode.java
new file mode 100644
index 0000000..bc37cab
--- /dev/null
+++ b/samples/browseable/FragmentTransition/src/com.example.android.common/logger/LogNode.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012 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.logger;
+
+/**
+ * Basic interface for a logging system that can output to one or more targets.
+ * Note that in addition to classes that will output these logs in some format,
+ * one can also implement this interface over a filter and insert that in the chain,
+ * such that no targets further down see certain data, or see manipulated forms of the data.
+ * You could, for instance, write a "ToHtmlLoggerNode" that just converted all the log data
+ * it received to HTML and sent it along to the next node in the chain, without printing it
+ * anywhere.
+ */
+public interface LogNode {
+
+ /**
+ * Instructs first LogNode in the list to print the log data provided.
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public void println(int priority, String tag, String msg, Throwable tr);
+
+}
diff --git a/samples/browseable/FragmentTransition/src/com.example.android.common/logger/LogView.java b/samples/browseable/FragmentTransition/src/com.example.android.common/logger/LogView.java
new file mode 100644
index 0000000..c01542b
--- /dev/null
+++ b/samples/browseable/FragmentTransition/src/com.example.android.common/logger/LogView.java
@@ -0,0 +1,145 @@
+/*
+ * 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.logger;
+
+import android.app.Activity;
+import android.content.Context;
+import android.util.*;
+import android.widget.TextView;
+
+/** Simple TextView which is used to output log data received through the LogNode interface.
+*/
+public class LogView extends TextView implements LogNode {
+
+ public LogView(Context context) {
+ super(context);
+ }
+
+ public LogView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public LogView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ /**
+ * Formats the log data and prints it out to the LogView.
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ @Override
+ public void println(int priority, String tag, String msg, Throwable tr) {
+
+
+ String priorityStr = null;
+
+ // For the purposes of this View, we want to print the priority as readable text.
+ switch(priority) {
+ case android.util.Log.VERBOSE:
+ priorityStr = "VERBOSE";
+ break;
+ case android.util.Log.DEBUG:
+ priorityStr = "DEBUG";
+ break;
+ case android.util.Log.INFO:
+ priorityStr = "INFO";
+ break;
+ case android.util.Log.WARN:
+ priorityStr = "WARN";
+ break;
+ case android.util.Log.ERROR:
+ priorityStr = "ERROR";
+ break;
+ case android.util.Log.ASSERT:
+ priorityStr = "ASSERT";
+ break;
+ default:
+ break;
+ }
+
+ // Handily, the Log class has a facility for converting a stack trace into a usable string.
+ String exceptionStr = null;
+ if (tr != null) {
+ exceptionStr = android.util.Log.getStackTraceString(tr);
+ }
+
+ // Take the priority, tag, message, and exception, and concatenate as necessary
+ // into one usable line of text.
+ final StringBuilder outputBuilder = new StringBuilder();
+
+ String delimiter = "\t";
+ appendIfNotNull(outputBuilder, priorityStr, delimiter);
+ appendIfNotNull(outputBuilder, tag, delimiter);
+ appendIfNotNull(outputBuilder, msg, delimiter);
+ appendIfNotNull(outputBuilder, exceptionStr, delimiter);
+
+ // In case this was originally called from an AsyncTask or some other off-UI thread,
+ // make sure the update occurs within the UI thread.
+ ((Activity) getContext()).runOnUiThread( (new Thread(new Runnable() {
+ @Override
+ public void run() {
+ // Display the text we just generated within the LogView.
+ appendToLog(outputBuilder.toString());
+ }
+ })));
+
+ if (mNext != null) {
+ mNext.println(priority, tag, msg, tr);
+ }
+ }
+
+ public LogNode getNext() {
+ return mNext;
+ }
+
+ public void setNext(LogNode node) {
+ mNext = node;
+ }
+
+ /** Takes a string and adds to it, with a separator, if the bit to be added isn't null. Since
+ * the logger takes so many arguments that might be null, this method helps cut out some of the
+ * agonizing tedium of writing the same 3 lines over and over.
+ * @param source StringBuilder containing the text to append to.
+ * @param addStr The String to append
+ * @param delimiter The String to separate the source and appended strings. A tab or comma,
+ * for instance.
+ * @return The fully concatenated String as a StringBuilder
+ */
+ private StringBuilder appendIfNotNull(StringBuilder source, String addStr, String delimiter) {
+ if (addStr != null) {
+ if (addStr.length() == 0) {
+ delimiter = "";
+ }
+
+ return source.append(addStr).append(delimiter);
+ }
+ return source;
+ }
+
+ // The next LogNode in the chain.
+ LogNode mNext;
+
+ /** Outputs the string as a new line of log data in the LogView. */
+ public void appendToLog(String s) {
+ append("\n" + s);
+ }
+
+
+}
diff --git a/samples/browseable/FragmentTransition/src/com.example.android.common/logger/LogWrapper.java b/samples/browseable/FragmentTransition/src/com.example.android.common/logger/LogWrapper.java
new file mode 100644
index 0000000..16a9e7b
--- /dev/null
+++ b/samples/browseable/FragmentTransition/src/com.example.android.common/logger/LogWrapper.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2012 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.logger;
+
+import android.util.Log;
+
+/**
+ * Helper class which wraps Android's native Log utility in the Logger interface. This way
+ * normal DDMS output can be one of the many targets receiving and outputting logs simultaneously.
+ */
+public class LogWrapper implements LogNode {
+
+ // For piping: The next node to receive Log data after this one has done its work.
+ private LogNode mNext;
+
+ /**
+ * Returns the next LogNode in the linked list.
+ */
+ public LogNode getNext() {
+ return mNext;
+ }
+
+ /**
+ * Sets the LogNode data will be sent to..
+ */
+ public void setNext(LogNode node) {
+ mNext = node;
+ }
+
+ /**
+ * Prints data out to the console using Android's native log mechanism.
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ @Override
+ public void println(int priority, String tag, String msg, Throwable tr) {
+ // There actually are log methods that don't take a msg parameter. For now,
+ // if that's the case, just convert null to the empty string and move on.
+ String useMsg = msg;
+ if (useMsg == null) {
+ useMsg = "";
+ }
+
+ // If an exeption was provided, convert that exception to a usable string and attach
+ // it to the end of the msg method.
+ if (tr != null) {
+ msg += "\n" + Log.getStackTraceString(tr);
+ }
+
+ // This is functionally identical to Log.x(tag, useMsg);
+ // For instance, if priority were Log.VERBOSE, this would be the same as Log.v(tag, useMsg)
+ Log.println(priority, tag, useMsg);
+
+ // If this isn't the last node in the chain, move things along.
+ if (mNext != null) {
+ mNext.println(priority, tag, msg, tr);
+ }
+ }
+}
diff --git a/samples/browseable/FragmentTransition/src/com.example.android.common/logger/MessageOnlyLogFilter.java b/samples/browseable/FragmentTransition/src/com.example.android.common/logger/MessageOnlyLogFilter.java
new file mode 100644
index 0000000..19967dc
--- /dev/null
+++ b/samples/browseable/FragmentTransition/src/com.example.android.common/logger/MessageOnlyLogFilter.java
@@ -0,0 +1,60 @@
+/*
+ * 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.logger;
+
+/**
+ * Simple {@link LogNode} filter, removes everything except the message.
+ * Useful for situations like on-screen log output where you don't want a lot of metadata displayed,
+ * just easy-to-read message updates as they're happening.
+ */
+public class MessageOnlyLogFilter implements LogNode {
+
+ LogNode mNext;
+
+ /**
+ * Takes the "next" LogNode as a parameter, to simplify chaining.
+ *
+ * @param next The next LogNode in the pipeline.
+ */
+ public MessageOnlyLogFilter(LogNode next) {
+ mNext = next;
+ }
+
+ public MessageOnlyLogFilter() {
+ }
+
+ @Override
+ public void println(int priority, String tag, String msg, Throwable tr) {
+ if (mNext != null) {
+ getNext().println(Log.NONE, null, msg, null);
+ }
+ }
+
+ /**
+ * Returns the next LogNode in the chain.
+ */
+ public LogNode getNext() {
+ return mNext;
+ }
+
+ /**
+ * Sets the LogNode data will be sent to..
+ */
+ public void setNext(LogNode node) {
+ mNext = node;
+ }
+
+}
diff --git a/samples/browseable/FragmentTransition/src/com.example.android.common/view/SlidingTabLayout.java b/samples/browseable/FragmentTransition/src/com.example.android.common/view/SlidingTabLayout.java
new file mode 100644
index 0000000..20049e3
--- /dev/null
+++ b/samples/browseable/FragmentTransition/src/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/samples/browseable/FragmentTransition/src/com.example.android.common/view/SlidingTabStrip.java b/samples/browseable/FragmentTransition/src/com.example.android.common/view/SlidingTabStrip.java
new file mode 100644
index 0000000..d5bbbae
--- /dev/null
+++ b/samples/browseable/FragmentTransition/src/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/samples/browseable/FragmentTransition/src/com.example.android.fragmenttransition/DetailFragment.java b/samples/browseable/FragmentTransition/src/com.example.android.fragmenttransition/DetailFragment.java
new file mode 100644
index 0000000..81e7b46
--- /dev/null
+++ b/samples/browseable/FragmentTransition/src/com.example.android.fragmenttransition/DetailFragment.java
@@ -0,0 +1,158 @@
+/*
+ * 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.fragmenttransition;
+
+import com.example.android.common.logger.Log;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.transition.Scene;
+import android.transition.TransitionManager;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+public class DetailFragment extends Fragment implements Animation.AnimationListener {
+
+ private static final String TAG = "DetailFragment";
+
+ private static final String ARG_RESOURCE_ID = "resource_id";
+ private static final String ARG_TITLE = "title";
+ private static final String ARG_X = "x";
+ private static final String ARG_Y = "y";
+ private static final String ARG_WIDTH = "width";
+ private static final String ARG_HEIGHT = "height";
+
+ /**
+ * Create a new instance of DetailFragment.
+ *
+ * @param resourceId The resource ID of the Drawable image to show
+ * @param title The title of the image
+ * @param x The horizontal position of the grid item in pixel
+ * @param y The vertical position of the grid item in pixel
+ * @param width The width of the grid item in pixel
+ * @param height The height of the grid item in pixel
+ * @return a new instance of DetailFragment
+ */
+ public static DetailFragment newInstance(int resourceId, String title,
+ int x, int y, int width, int height) {
+ DetailFragment fragment = new DetailFragment();
+ Bundle args = new Bundle();
+ args.putInt(ARG_RESOURCE_ID, resourceId);
+ args.putString(ARG_TITLE, title);
+ args.putInt(ARG_X, x);
+ args.putInt(ARG_Y, y);
+ args.putInt(ARG_WIDTH, width);
+ args.putInt(ARG_HEIGHT, height);
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ public DetailFragment() {
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.fragment_detail, container, false);
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ FrameLayout root = (FrameLayout) view;
+ Context context = view.getContext();
+ assert context != null;
+ // This is how the fragment looks at first. Since the transition is one-way, we don't need to make
+ // this a Scene.
+ View item = LayoutInflater.from(context).inflate(R.layout.item_meat_grid, root, false);
+ assert item != null;
+ bind(item);
+ // We adjust the position of the initial image with LayoutParams using the values supplied
+ // as the fragment arguments.
+ Bundle args = getArguments();
+ FrameLayout.LayoutParams params = null;
+ if (args != null) {
+ params = new FrameLayout.LayoutParams(
+ args.getInt(ARG_WIDTH), args.getInt(ARG_HEIGHT));
+ params.topMargin = args.getInt(ARG_Y);
+ params.leftMargin = args.getInt(ARG_X);
+ }
+ root.addView(item, params);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ }
+
+ /**
+ * Bind the views inside of parent with the fragment arguments.
+ *
+ * @param parent The parent of views to bind.
+ */
+ private void bind(View parent) {
+ Bundle args = getArguments();
+ if (args == null) {
+ return;
+ }
+ ImageView image = (ImageView) parent.findViewById(R.id.image);
+ image.setImageResource(args.getInt(ARG_RESOURCE_ID));
+ TextView title = (TextView) parent.findViewById(R.id.title);
+ title.setText(args.getString(ARG_TITLE));
+ }
+
+ @Override
+ public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
+ Animation animation = AnimationUtils.loadAnimation(getActivity(),
+ enter ? android.R.anim.fade_in : android.R.anim.fade_out);
+ // We bind a listener for the fragment transaction. We only bind it when
+ // this fragment is entering.
+ if (animation != null && enter) {
+ animation.setAnimationListener(this);
+ }
+ return animation;
+ }
+
+ @Override
+ public void onAnimationStart(Animation animation) {
+ // This method is called at the end of the animation for the fragment transaction.
+ // There is nothing we need to do in this sample.
+ }
+
+ @Override
+ public void onAnimationEnd(Animation animation) {
+ // This method is called at the end of the animation for the fragment transaction,
+ // which is perfect time to start our Transition.
+ Log.i(TAG, "Fragment animation ended. Starting a Transition.");
+ final Scene scene = Scene.getSceneForLayout((ViewGroup) getView(),
+ R.layout.fragment_detail_content, getActivity());
+ TransitionManager.go(scene);
+ // Note that we need to bind views with data after we call TransitionManager.go().
+ bind(scene.getSceneRoot());
+ }
+
+ @Override
+ public void onAnimationRepeat(Animation animation) {
+ // This method is never called in this sample because the animation doesn't repeat.
+ }
+
+}
diff --git a/samples/browseable/FragmentTransition/src/com.example.android.fragmenttransition/FragmentTransitionFragment.java b/samples/browseable/FragmentTransition/src/com.example.android.fragmenttransition/FragmentTransitionFragment.java
new file mode 100644
index 0000000..c072eb9
--- /dev/null
+++ b/samples/browseable/FragmentTransition/src/com.example.android.fragmenttransition/FragmentTransitionFragment.java
@@ -0,0 +1,83 @@
+/*
+ * 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.fragmenttransition;
+
+import com.example.android.common.logger.Log;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.widget.AdapterView;
+import android.widget.GridView;
+
+public class FragmentTransitionFragment extends Fragment implements AdapterView.OnItemClickListener {
+
+ private static final String TAG = "FragmentTransitionFragment";
+
+ private MeatAdapter mAdapter;
+
+ public static FragmentTransitionFragment newInstance() {
+ return new FragmentTransitionFragment();
+ }
+
+ public FragmentTransitionFragment() {
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ // This is the adapter we use to populate the grid.
+ mAdapter = new MeatAdapter(inflater, R.layout.item_meat_grid);
+ // Inflate the layout with a GridView in it.
+ return inflater.inflate(R.layout.fragment_fragment_transition, container, false);
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ GridView grid = (GridView) view.findViewById(R.id.grid);
+ grid.setAdapter(mAdapter);
+ grid.setOnItemClickListener(this);
+ }
+
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ Meat meat = mAdapter.getItem(position);
+ Log.i(TAG, meat.title + " clicked. Replacing fragment.");
+ // We start the fragment transaction here. It is just an ordinary fragment transaction.
+ getActivity().getSupportFragmentManager()
+ .beginTransaction()
+ .replace(R.id.sample_content_fragment,
+ DetailFragment.newInstance(meat.resourceId, meat.title,
+ (int) view.getX(), (int) view.getY(),
+ view.getWidth(), view.getHeight())
+ )
+ // We push the fragment transaction to back stack. User can go back to the
+ // previous fragment by pressing back button.
+ .addToBackStack("detail")
+ .commit();
+ }
+
+ @Override
+ public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
+ return AnimationUtils.loadAnimation(getActivity(),
+ enter ? android.R.anim.fade_in : android.R.anim.fade_out);
+ }
+
+}
diff --git a/samples/browseable/FragmentTransition/src/com.example.android.fragmenttransition/MainActivity.java b/samples/browseable/FragmentTransition/src/com.example.android.fragmenttransition/MainActivity.java
new file mode 100644
index 0000000..7d6ca6f
--- /dev/null
+++ b/samples/browseable/FragmentTransition/src/com.example.android.fragmenttransition/MainActivity.java
@@ -0,0 +1,110 @@
+/*
+* 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.
+*/
+
+
+
+
+package com.example.android.fragmenttransition;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentTransaction;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.ViewAnimator;
+
+import com.example.android.common.activities.SampleActivityBase;
+import com.example.android.common.logger.Log;
+import com.example.android.common.logger.LogFragment;
+import com.example.android.common.logger.LogWrapper;
+import com.example.android.common.logger.MessageOnlyLogFilter;
+
+/**
+ * A simple launcher activity containing a summary sample description, sample log and a custom
+ * {@link android.support.v4.app.Fragment} which can display a view.
+ * <p>
+ * For devices with displays with a width of 720dp or greater, the sample log is always visible,
+ * on other devices it's visibility is controlled by an item on the Action Bar.
+ */
+public class MainActivity extends SampleActivityBase {
+
+ public static final String TAG = "MainActivity";
+
+ // Whether the Log Fragment is currently shown
+ private boolean mLogShown;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+ FragmentTransitionFragment fragment = new FragmentTransitionFragment();
+ transaction.replace(R.id.sample_content_fragment, fragment);
+ transaction.commit();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.main, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ MenuItem logToggle = menu.findItem(R.id.menu_toggle_log);
+ logToggle.setVisible(findViewById(R.id.sample_output) instanceof ViewAnimator);
+ logToggle.setTitle(mLogShown ? R.string.sample_hide_log : R.string.sample_show_log);
+
+ return super.onPrepareOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch(item.getItemId()) {
+ case R.id.menu_toggle_log:
+ mLogShown = !mLogShown;
+ ViewAnimator output = (ViewAnimator) findViewById(R.id.sample_output);
+ if (mLogShown) {
+ output.setDisplayedChild(1);
+ } else {
+ output.setDisplayedChild(0);
+ }
+ supportInvalidateOptionsMenu();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ /** Create a chain of targets that will receive log data */
+ @Override
+ public void initializeLogging() {
+ // Wraps Android's native log framework.
+ LogWrapper logWrapper = new LogWrapper();
+ // Using Log, front-end to the logging chain, emulates android.util.log method signatures.
+ Log.setLogNode(logWrapper);
+
+ // Filter strips out everything except the message text.
+ MessageOnlyLogFilter msgFilter = new MessageOnlyLogFilter();
+ logWrapper.setNext(msgFilter);
+
+ // On screen logging via a fragment with a TextView.
+ LogFragment logFragment = (LogFragment) getSupportFragmentManager()
+ .findFragmentById(R.id.log_fragment);
+ msgFilter.setNext(logFragment.getLogView());
+
+ Log.i(TAG, "Ready");
+ }
+}
diff --git a/samples/browseable/FragmentTransition/src/com.example.android.fragmenttransition/Meat.java b/samples/browseable/FragmentTransition/src/com.example.android.fragmenttransition/Meat.java
new file mode 100644
index 0000000..2f2fdfa
--- /dev/null
+++ b/samples/browseable/FragmentTransition/src/com.example.android.fragmenttransition/Meat.java
@@ -0,0 +1,46 @@
+/*
+ * 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.fragmenttransition;
+
+/**
+ * This represents a sample data.
+ */
+public class Meat {
+
+ public int resourceId;
+ public String title;
+
+ public Meat(int resourceId, String title) {
+ this.resourceId = resourceId;
+ this.title = title;
+ }
+
+ public static final Meat[] MEATS = {
+ new Meat(R.drawable.p1, "First"),
+ new Meat(R.drawable.p2, "Second"),
+ new Meat(R.drawable.p3, "Third"),
+ new Meat(R.drawable.p4, "Fourth"),
+ new Meat(R.drawable.p5, "Fifth"),
+ new Meat(R.drawable.p6, "Sixth"),
+ new Meat(R.drawable.p7, "Seventh"),
+ new Meat(R.drawable.p8, "Eighth"),
+ new Meat(R.drawable.p9, "Ninth"),
+ new Meat(R.drawable.p10, "Tenth"),
+ new Meat(R.drawable.p11, "Eleventh"),
+ };
+
+}
diff --git a/samples/browseable/FragmentTransition/src/com.example.android.fragmenttransition/MeatAdapter.java b/samples/browseable/FragmentTransition/src/com.example.android.fragmenttransition/MeatAdapter.java
new file mode 100644
index 0000000..307fd85
--- /dev/null
+++ b/samples/browseable/FragmentTransition/src/com.example.android.fragmenttransition/MeatAdapter.java
@@ -0,0 +1,81 @@
+/*
+ * 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.fragmenttransition;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+class MeatAdapter extends BaseAdapter {
+
+ private final LayoutInflater mLayoutInflater;
+ private final int mResourceId;
+
+ public MeatAdapter(LayoutInflater inflater, int resourceId) {
+ mLayoutInflater = inflater;
+ mResourceId = resourceId;
+ }
+
+ @Override
+ public int getCount() {
+ return Meat.MEATS.length;
+ }
+
+ @Override
+ public Meat getItem(int position) {
+ return Meat.MEATS[position];
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return Meat.MEATS[position].resourceId;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ final View view;
+ final ViewHolder holder;
+ if (null == convertView) {
+ view = mLayoutInflater.inflate(mResourceId, parent, false);
+ holder = new ViewHolder();
+ assert view != null;
+ holder.image = (ImageView) view.findViewById(R.id.image);
+ holder.title = (TextView) view.findViewById(R.id.title);
+ view.setTag(holder);
+ } else {
+ view = convertView;
+ holder = (ViewHolder) view.getTag();
+ }
+ bindView(holder, position);
+ return view;
+ }
+
+ public void bindView(ViewHolder holder, int position) {
+ Meat meat = getItem(position);
+ holder.image.setImageResource(meat.resourceId);
+ holder.title.setText(meat.title);
+ }
+
+ public static class ViewHolder {
+ public ImageView image;
+ public TextView title;
+ }
+
+}
diff --git a/samples/browseable/HorizontalPaging/res/values-v11/template-styles.xml b/samples/browseable/HorizontalPaging/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/HorizontalPaging/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/HorizontalPaging/res/values/template-styles.xml b/samples/browseable/HorizontalPaging/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/HorizontalPaging/res/values/template-styles.xml
+++ b/samples/browseable/HorizontalPaging/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/ImmersiveMode/res/layout-sw600dp-land/activity_main.xml b/samples/browseable/ImmersiveMode/res/layout-sw600dp-land/activity_main.xml
new file mode 100755
index 0000000..653454b
--- /dev/null
+++ b/samples/browseable/ImmersiveMode/res/layout-sw600dp-land/activity_main.xml
@@ -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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:id="@+id/sample_main_layout">
+ <TextView android:id="@+id/sample_output"
+ style="@style/Widget.SampleMessage"
+ android:background="@android:color/white"
+ android:layout_weight="1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:text="@string/intro_message"
+ android:layout_margin="16dp" />
+ <fragment
+ android:name="com.example.android.common.logger.LogFragment"
+ android:id="@+id/log_fragment"
+ android:layout_weight="1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="16dp" />
+</LinearLayout>
diff --git a/samples/browseable/ImmersiveMode/res/layout-sw600dp/activity_main.xml b/samples/browseable/ImmersiveMode/res/layout-sw600dp/activity_main.xml
new file mode 100755
index 0000000..f6f4157
--- /dev/null
+++ b/samples/browseable/ImmersiveMode/res/layout-sw600dp/activity_main.xml
@@ -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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:id="@+id/sample_main_layout" >
+
+ <TextView android:id="@+id/sample_output"
+ style="@style/Widget.SampleMessage"
+ android:background="@android:color/white"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/intro_message"
+ android:padding="16dp"
+ android:layout_margin="16dp"/>
+ <fragment
+ android:name="com.example.android.common.logger.LogFragment"
+ android:id="@+id/log_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="16dp" />
+</LinearLayout>
diff --git a/samples/browseable/ImmersiveMode/res/layout/activity_main.xml b/samples/browseable/ImmersiveMode/res/layout/activity_main.xml
index bc5a575..6f41369 100755
--- a/samples/browseable/ImmersiveMode/res/layout/activity_main.xml
+++ b/samples/browseable/ImmersiveMode/res/layout/activity_main.xml
@@ -24,7 +24,8 @@
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:text="@string/intro_message" />
+ android:text="@string/intro_message"
+ android:padding="16dp" />
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
diff --git a/samples/browseable/ImmersiveMode/res/values-sw600dp/template-styles.xml b/samples/browseable/ImmersiveMode/res/values-sw600dp/template-styles.xml
index 03d1974..b6ea1a0 100644
--- a/samples/browseable/ImmersiveMode/res/values-sw600dp/template-styles.xml
+++ b/samples/browseable/ImmersiveMode/res/values-sw600dp/template-styles.xml
@@ -17,9 +17,17 @@
<resources>
<style name="Widget.SampleMessage">
- <item name="android:textAppearance">?android:textAppearanceLarge</item>
- <item name="android:lineSpacingMultiplier">1.2</item>
+ <item name="android:padding">@dimen/margin_medium</item>
+ <item name="android:textAppearance">?android:textAppearanceMedium</item>
+ <item name="android:lineSpacingMultiplier">1.1</item>
+
+ <item name="android:layout_margin">16dp</item>
<item name="android:shadowDy">-6.5</item>
</style>
+ <style name="Log" parent="Widget.SampleOutput">
+ <item name="android:typeface">monospace</item>
+ </style>
+
+
</resources>
diff --git a/samples/browseable/ImmersiveMode/res/values-v11/template-styles.xml b/samples/browseable/ImmersiveMode/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/ImmersiveMode/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/ImmersiveMode/src/com.example.android.immersivemode/MainActivity.java b/samples/browseable/ImmersiveMode/src/com.example.android.immersivemode/MainActivity.java
index fd02112..8fb6e34 100644
--- a/samples/browseable/ImmersiveMode/src/com.example.android.immersivemode/MainActivity.java
+++ b/samples/browseable/ImmersiveMode/src/com.example.android.immersivemode/MainActivity.java
@@ -19,6 +19,7 @@
package com.example.android.immersivemode;
+import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import android.view.Menu;
@@ -74,6 +75,9 @@
LogFragment logFragment = (LogFragment) getSupportFragmentManager()
.findFragmentById(R.id.log_fragment);
msgFilter.setNext(logFragment.getLogView());
+ logFragment.getLogView().setTextAppearance(this, R.style.Log);
+ logFragment.getLogView().setBackgroundColor(Color.WHITE);
+
Log.i(TAG, "Ready");
}
diff --git a/samples/browseable/MediaRecorder/res/values-v11/template-styles.xml b/samples/browseable/MediaRecorder/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/MediaRecorder/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/MediaRecorder/res/values/template-styles.xml b/samples/browseable/MediaRecorder/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/MediaRecorder/res/values/template-styles.xml
+++ b/samples/browseable/MediaRecorder/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/MediaRouter/res/values-v11/template-styles.xml b/samples/browseable/MediaRouter/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/MediaRouter/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/MediaRouter/res/values/template-styles.xml b/samples/browseable/MediaRouter/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/MediaRouter/res/values/template-styles.xml
+++ b/samples/browseable/MediaRouter/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/NetworkConnect/res/values-v11/template-styles.xml b/samples/browseable/NetworkConnect/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/NetworkConnect/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/NetworkConnect/res/values/template-styles.xml b/samples/browseable/NetworkConnect/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/NetworkConnect/res/values/template-styles.xml
+++ b/samples/browseable/NetworkConnect/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/RenderScriptIntrinsic/res/values-v11/template-styles.xml b/samples/browseable/RenderScriptIntrinsic/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/RenderScriptIntrinsic/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/RenderScriptIntrinsic/res/values/template-styles.xml b/samples/browseable/RenderScriptIntrinsic/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/RenderScriptIntrinsic/res/values/template-styles.xml
+++ b/samples/browseable/RenderScriptIntrinsic/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/RepeatingAlarm/res/layout-sw600dp-land/activity_main.xml b/samples/browseable/RepeatingAlarm/res/layout-sw600dp-land/activity_main.xml
new file mode 100755
index 0000000..653454b
--- /dev/null
+++ b/samples/browseable/RepeatingAlarm/res/layout-sw600dp-land/activity_main.xml
@@ -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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:id="@+id/sample_main_layout">
+ <TextView android:id="@+id/sample_output"
+ style="@style/Widget.SampleMessage"
+ android:background="@android:color/white"
+ android:layout_weight="1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:text="@string/intro_message"
+ android:layout_margin="16dp" />
+ <fragment
+ android:name="com.example.android.common.logger.LogFragment"
+ android:id="@+id/log_fragment"
+ android:layout_weight="1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="16dp" />
+</LinearLayout>
diff --git a/samples/browseable/RepeatingAlarm/res/layout-sw600dp/activity_main.xml b/samples/browseable/RepeatingAlarm/res/layout-sw600dp/activity_main.xml
new file mode 100755
index 0000000..f6f4157
--- /dev/null
+++ b/samples/browseable/RepeatingAlarm/res/layout-sw600dp/activity_main.xml
@@ -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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:id="@+id/sample_main_layout" >
+
+ <TextView android:id="@+id/sample_output"
+ style="@style/Widget.SampleMessage"
+ android:background="@android:color/white"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/intro_message"
+ android:padding="16dp"
+ android:layout_margin="16dp"/>
+ <fragment
+ android:name="com.example.android.common.logger.LogFragment"
+ android:id="@+id/log_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="16dp" />
+</LinearLayout>
diff --git a/samples/browseable/RepeatingAlarm/res/layout/activity_main.xml b/samples/browseable/RepeatingAlarm/res/layout/activity_main.xml
index bc5a575..6f41369 100755
--- a/samples/browseable/RepeatingAlarm/res/layout/activity_main.xml
+++ b/samples/browseable/RepeatingAlarm/res/layout/activity_main.xml
@@ -24,7 +24,8 @@
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:text="@string/intro_message" />
+ android:text="@string/intro_message"
+ android:padding="16dp" />
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
diff --git a/samples/browseable/RepeatingAlarm/res/values-sw600dp/template-styles.xml b/samples/browseable/RepeatingAlarm/res/values-sw600dp/template-styles.xml
index 03d1974..b6ea1a0 100644
--- a/samples/browseable/RepeatingAlarm/res/values-sw600dp/template-styles.xml
+++ b/samples/browseable/RepeatingAlarm/res/values-sw600dp/template-styles.xml
@@ -17,9 +17,17 @@
<resources>
<style name="Widget.SampleMessage">
- <item name="android:textAppearance">?android:textAppearanceLarge</item>
- <item name="android:lineSpacingMultiplier">1.2</item>
+ <item name="android:padding">@dimen/margin_medium</item>
+ <item name="android:textAppearance">?android:textAppearanceMedium</item>
+ <item name="android:lineSpacingMultiplier">1.1</item>
+
+ <item name="android:layout_margin">16dp</item>
<item name="android:shadowDy">-6.5</item>
</style>
+ <style name="Log" parent="Widget.SampleOutput">
+ <item name="android:typeface">monospace</item>
+ </style>
+
+
</resources>
diff --git a/samples/browseable/RepeatingAlarm/res/values-v11/template-styles.xml b/samples/browseable/RepeatingAlarm/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/RepeatingAlarm/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/RepeatingAlarm/src/com.example.android.repeatingalarm/MainActivity.java b/samples/browseable/RepeatingAlarm/src/com.example.android.repeatingalarm/MainActivity.java
index 2d2a6aa..147f576 100644
--- a/samples/browseable/RepeatingAlarm/src/com.example.android.repeatingalarm/MainActivity.java
+++ b/samples/browseable/RepeatingAlarm/src/com.example.android.repeatingalarm/MainActivity.java
@@ -19,6 +19,7 @@
package com.example.android.repeatingalarm;
+import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import android.view.Menu;
@@ -74,6 +75,9 @@
LogFragment logFragment = (LogFragment) getSupportFragmentManager()
.findFragmentById(R.id.log_fragment);
msgFilter.setNext(logFragment.getLogView());
+ logFragment.getLogView().setTextAppearance(this, R.style.Log);
+ logFragment.getLogView().setBackgroundColor(Color.WHITE);
+
Log.i(TAG, "Ready");
}
diff --git a/samples/browseable/SlidingTabsBasic/res/values-v11/template-styles.xml b/samples/browseable/SlidingTabsBasic/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/SlidingTabsBasic/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/SlidingTabsBasic/res/values/template-styles.xml b/samples/browseable/SlidingTabsBasic/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/SlidingTabsBasic/res/values/template-styles.xml
+++ b/samples/browseable/SlidingTabsBasic/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/SlidingTabsColors/res/values-v11/template-styles.xml b/samples/browseable/SlidingTabsColors/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/SlidingTabsColors/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/SlidingTabsColors/res/values/template-styles.xml b/samples/browseable/SlidingTabsColors/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/SlidingTabsColors/res/values/template-styles.xml
+++ b/samples/browseable/SlidingTabsColors/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/StorageClient/res/layout-sw600dp-land/activity_main.xml b/samples/browseable/StorageClient/res/layout-sw600dp-land/activity_main.xml
new file mode 100755
index 0000000..653454b
--- /dev/null
+++ b/samples/browseable/StorageClient/res/layout-sw600dp-land/activity_main.xml
@@ -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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:id="@+id/sample_main_layout">
+ <TextView android:id="@+id/sample_output"
+ style="@style/Widget.SampleMessage"
+ android:background="@android:color/white"
+ android:layout_weight="1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:text="@string/intro_message"
+ android:layout_margin="16dp" />
+ <fragment
+ android:name="com.example.android.common.logger.LogFragment"
+ android:id="@+id/log_fragment"
+ android:layout_weight="1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="16dp" />
+</LinearLayout>
diff --git a/samples/browseable/StorageClient/res/layout-sw600dp/activity_main.xml b/samples/browseable/StorageClient/res/layout-sw600dp/activity_main.xml
new file mode 100755
index 0000000..f6f4157
--- /dev/null
+++ b/samples/browseable/StorageClient/res/layout-sw600dp/activity_main.xml
@@ -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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:id="@+id/sample_main_layout" >
+
+ <TextView android:id="@+id/sample_output"
+ style="@style/Widget.SampleMessage"
+ android:background="@android:color/white"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/intro_message"
+ android:padding="16dp"
+ android:layout_margin="16dp"/>
+ <fragment
+ android:name="com.example.android.common.logger.LogFragment"
+ android:id="@+id/log_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="16dp" />
+</LinearLayout>
diff --git a/samples/browseable/StorageClient/res/layout/activity_main.xml b/samples/browseable/StorageClient/res/layout/activity_main.xml
index bc5a575..6f41369 100755
--- a/samples/browseable/StorageClient/res/layout/activity_main.xml
+++ b/samples/browseable/StorageClient/res/layout/activity_main.xml
@@ -24,7 +24,8 @@
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:text="@string/intro_message" />
+ android:text="@string/intro_message"
+ android:padding="16dp" />
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
diff --git a/samples/browseable/StorageClient/res/values-sw600dp/template-styles.xml b/samples/browseable/StorageClient/res/values-sw600dp/template-styles.xml
index 03d1974..b6ea1a0 100644
--- a/samples/browseable/StorageClient/res/values-sw600dp/template-styles.xml
+++ b/samples/browseable/StorageClient/res/values-sw600dp/template-styles.xml
@@ -17,9 +17,17 @@
<resources>
<style name="Widget.SampleMessage">
- <item name="android:textAppearance">?android:textAppearanceLarge</item>
- <item name="android:lineSpacingMultiplier">1.2</item>
+ <item name="android:padding">@dimen/margin_medium</item>
+ <item name="android:textAppearance">?android:textAppearanceMedium</item>
+ <item name="android:lineSpacingMultiplier">1.1</item>
+
+ <item name="android:layout_margin">16dp</item>
<item name="android:shadowDy">-6.5</item>
</style>
+ <style name="Log" parent="Widget.SampleOutput">
+ <item name="android:typeface">monospace</item>
+ </style>
+
+
</resources>
diff --git a/samples/browseable/StorageClient/res/values-v11/template-styles.xml b/samples/browseable/StorageClient/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/StorageClient/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/StorageClient/src/com.example.android.storageclient/MainActivity.java b/samples/browseable/StorageClient/src/com.example.android.storageclient/MainActivity.java
index 69c75eb..106f26b 100644
--- a/samples/browseable/StorageClient/src/com.example.android.storageclient/MainActivity.java
+++ b/samples/browseable/StorageClient/src/com.example.android.storageclient/MainActivity.java
@@ -19,6 +19,7 @@
package com.example.android.storageclient;
+import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import android.view.Menu;
@@ -74,6 +75,9 @@
LogFragment logFragment = (LogFragment) getSupportFragmentManager()
.findFragmentById(R.id.log_fragment);
msgFilter.setNext(logFragment.getLogView());
+ logFragment.getLogView().setTextAppearance(this, R.style.Log);
+ logFragment.getLogView().setBackgroundColor(Color.WHITE);
+
Log.i(TAG, "Ready");
}
diff --git a/samples/browseable/StorageProvider/res/layout-sw600dp-land/activity_main.xml b/samples/browseable/StorageProvider/res/layout-sw600dp-land/activity_main.xml
new file mode 100755
index 0000000..653454b
--- /dev/null
+++ b/samples/browseable/StorageProvider/res/layout-sw600dp-land/activity_main.xml
@@ -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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:id="@+id/sample_main_layout">
+ <TextView android:id="@+id/sample_output"
+ style="@style/Widget.SampleMessage"
+ android:background="@android:color/white"
+ android:layout_weight="1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:text="@string/intro_message"
+ android:layout_margin="16dp" />
+ <fragment
+ android:name="com.example.android.common.logger.LogFragment"
+ android:id="@+id/log_fragment"
+ android:layout_weight="1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="16dp" />
+</LinearLayout>
diff --git a/samples/browseable/StorageProvider/res/layout-sw600dp/activity_main.xml b/samples/browseable/StorageProvider/res/layout-sw600dp/activity_main.xml
new file mode 100755
index 0000000..f6f4157
--- /dev/null
+++ b/samples/browseable/StorageProvider/res/layout-sw600dp/activity_main.xml
@@ -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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:id="@+id/sample_main_layout" >
+
+ <TextView android:id="@+id/sample_output"
+ style="@style/Widget.SampleMessage"
+ android:background="@android:color/white"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/intro_message"
+ android:padding="16dp"
+ android:layout_margin="16dp"/>
+ <fragment
+ android:name="com.example.android.common.logger.LogFragment"
+ android:id="@+id/log_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="16dp" />
+</LinearLayout>
diff --git a/samples/browseable/StorageProvider/res/layout/activity_main.xml b/samples/browseable/StorageProvider/res/layout/activity_main.xml
index bc5a575..6f41369 100755
--- a/samples/browseable/StorageProvider/res/layout/activity_main.xml
+++ b/samples/browseable/StorageProvider/res/layout/activity_main.xml
@@ -24,7 +24,8 @@
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:text="@string/intro_message" />
+ android:text="@string/intro_message"
+ android:padding="16dp" />
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
diff --git a/samples/browseable/StorageProvider/res/values-sw600dp/template-styles.xml b/samples/browseable/StorageProvider/res/values-sw600dp/template-styles.xml
index 03d1974..b6ea1a0 100644
--- a/samples/browseable/StorageProvider/res/values-sw600dp/template-styles.xml
+++ b/samples/browseable/StorageProvider/res/values-sw600dp/template-styles.xml
@@ -17,9 +17,17 @@
<resources>
<style name="Widget.SampleMessage">
- <item name="android:textAppearance">?android:textAppearanceLarge</item>
- <item name="android:lineSpacingMultiplier">1.2</item>
+ <item name="android:padding">@dimen/margin_medium</item>
+ <item name="android:textAppearance">?android:textAppearanceMedium</item>
+ <item name="android:lineSpacingMultiplier">1.1</item>
+
+ <item name="android:layout_margin">16dp</item>
<item name="android:shadowDy">-6.5</item>
</style>
+ <style name="Log" parent="Widget.SampleOutput">
+ <item name="android:typeface">monospace</item>
+ </style>
+
+
</resources>
diff --git a/samples/browseable/StorageProvider/res/values-v11/template-styles.xml b/samples/browseable/StorageProvider/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/StorageProvider/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/StorageProvider/src/com.example.android.storageprovider/MainActivity.java b/samples/browseable/StorageProvider/src/com.example.android.storageprovider/MainActivity.java
index 5f04a62..3108c1f 100644
--- a/samples/browseable/StorageProvider/src/com.example.android.storageprovider/MainActivity.java
+++ b/samples/browseable/StorageProvider/src/com.example.android.storageprovider/MainActivity.java
@@ -19,6 +19,7 @@
package com.example.android.storageprovider;
+import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import android.view.Menu;
@@ -74,6 +75,9 @@
LogFragment logFragment = (LogFragment) getSupportFragmentManager()
.findFragmentById(R.id.log_fragment);
msgFilter.setNext(logFragment.getLogView());
+ logFragment.getLogView().setTextAppearance(this, R.style.Log);
+ logFragment.getLogView().setBackgroundColor(Color.WHITE);
+
Log.i(TAG, "Ready");
}
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/AndroidManifest.xml b/samples/browseable/SwipeRefreshLayoutBasic/AndroidManifest.xml
new file mode 100644
index 0000000..fa75453
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/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.swiperefreshlayoutbasic"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <uses-sdk android:minSdkVersion="10" 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/samples/browseable/SwipeRefreshLayoutBasic/_index.jd b/samples/browseable/SwipeRefreshLayoutBasic/_index.jd
new file mode 100644
index 0000000..bfbaddb
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/_index.jd
@@ -0,0 +1,11 @@
+
+
+
+page.tags="SwipeRefreshLayoutBasic"
+sample.group=UI
+@jd:body
+
+<p>This sample demonstrates how to use {@link android.support.v4.widget.SwipeRefreshLayout} to add
+the <em>swipe-to-refresh</em> gesture to a {@link android.view.View}, which enables you to trigger
+a refresh by swiping down on the {@link android.view.View}. In this sample, the view that can
+be freshed is a {@link android.widget.ListView}.</p>
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/res/drawable-hdpi/ic_launcher.png b/samples/browseable/SwipeRefreshLayoutBasic/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..da15ae2
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/res/drawable-hdpi/tile.9.png b/samples/browseable/SwipeRefreshLayoutBasic/res/drawable-hdpi/tile.9.png
new file mode 100644
index 0000000..1358628
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/res/drawable-hdpi/tile.9.png
Binary files differ
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/res/drawable-mdpi/ic_launcher.png b/samples/browseable/SwipeRefreshLayoutBasic/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..34c3f1c
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/SwipeRefreshLayoutBasic/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..83ac286
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/SwipeRefreshLayoutBasic/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..02802a3
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/res/layout-w720dp/activity_main.xml b/samples/browseable/SwipeRefreshLayoutBasic/res/layout-w720dp/activity_main.xml
new file mode 100755
index 0000000..c9a52f6
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/res/layout-w720dp/activity_main.xml
@@ -0,0 +1,73 @@
+<!--
+ 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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/sample_main_layout">
+
+ <LinearLayout
+ android:id="@+id/sample_output"
+ android:layout_width="0px"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:orientation="vertical">
+
+ <FrameLayout
+ style="@style/Widget.SampleMessageTile"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ style="@style/Widget.SampleMessage"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="@dimen/margin_medium"
+ android:paddingRight="@dimen/margin_medium"
+ android:paddingTop="@dimen/margin_large"
+ android:paddingBottom="@dimen/margin_large"
+ android:text="@string/intro_message" />
+ </FrameLayout>
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:background="@android:color/darker_gray" />
+
+ <fragment
+ android:name="com.example.android.common.logger.LogFragment"
+ android:id="@+id/log_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="0px"
+ android:layout_weight="1" />
+
+ </LinearLayout>
+
+ <View
+ android:layout_width="1dp"
+ android:layout_height="match_parent"
+ android:background="@android:color/darker_gray" />
+
+ <FrameLayout
+ android:id="@+id/sample_content_fragment"
+ android:layout_weight="2"
+ android:layout_width="0px"
+ android:layout_height="match_parent" />
+
+</LinearLayout>
+
+
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/res/layout/activity_main.xml b/samples/browseable/SwipeRefreshLayoutBasic/res/layout/activity_main.xml
new file mode 100755
index 0000000..1ae4f98
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/res/layout/activity_main.xml
@@ -0,0 +1,65 @@
+<!--
+ 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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/sample_main_layout">
+
+ <ViewAnimator
+ android:id="@+id/sample_output"
+ android:layout_width="match_parent"
+ android:layout_height="0px"
+ android:layout_weight="1">
+
+ <ScrollView
+ style="@style/Widget.SampleMessageTile"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <TextView
+ style="@style/Widget.SampleMessage"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="@dimen/horizontal_page_margin"
+ android:paddingRight="@dimen/horizontal_page_margin"
+ android:paddingTop="@dimen/vertical_page_margin"
+ android:paddingBottom="@dimen/vertical_page_margin"
+ android:text="@string/intro_message" />
+ </ScrollView>
+
+ <fragment
+ android:name="com.example.android.common.logger.LogFragment"
+ android:id="@+id/log_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ </ViewAnimator>
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:background="@android:color/darker_gray" />
+
+ <FrameLayout
+ android:id="@+id/sample_content_fragment"
+ android:layout_weight="2"
+ android:layout_width="match_parent"
+ android:layout_height="0px" />
+
+</LinearLayout>
+
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/res/layout/fragment_sample.xml b/samples/browseable/SwipeRefreshLayoutBasic/res/layout/fragment_sample.xml
new file mode 100644
index 0000000..8900f82
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/res/layout/fragment_sample.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+
+<android.support.v4.widget.SwipeRefreshLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/swiperefresh"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <ListView
+ android:id="@android:id/list"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+</android.support.v4.widget.SwipeRefreshLayout>
\ No newline at end of file
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/res/menu/main.xml b/samples/browseable/SwipeRefreshLayoutBasic/res/menu/main.xml
new file mode 100644
index 0000000..b49c2c5
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/res/menu/main.xml
@@ -0,0 +1,21 @@
+<!--
+ 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.
+ -->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/menu_toggle_log"
+ android:showAsAction="always"
+ android:title="@string/sample_show_log" />
+</menu>
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/res/menu/main_menu.xml b/samples/browseable/SwipeRefreshLayoutBasic/res/menu/main_menu.xml
new file mode 100644
index 0000000..de0c5f2
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/res/menu/main_menu.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:id="@+id/menu_refresh"
+ android:title="@string/menu_refresh"
+ android:showAsAction="never" />
+
+</menu>
\ No newline at end of file
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/res/values-sw600dp/template-dimens.xml b/samples/browseable/SwipeRefreshLayoutBasic/res/values-sw600dp/template-dimens.xml
new file mode 100644
index 0000000..22074a2
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/res/values-sw600dp/template-dimens.xml
@@ -0,0 +1,24 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Semantic definitions -->
+
+ <dimen name="horizontal_page_margin">@dimen/margin_huge</dimen>
+ <dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
+
+</resources>
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/res/values-sw600dp/template-styles.xml b/samples/browseable/SwipeRefreshLayoutBasic/res/values-sw600dp/template-styles.xml
new file mode 100644
index 0000000..03d1974
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/res/values-sw600dp/template-styles.xml
@@ -0,0 +1,25 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <style name="Widget.SampleMessage">
+ <item name="android:textAppearance">?android:textAppearanceLarge</item>
+ <item name="android:lineSpacingMultiplier">1.2</item>
+ <item name="android:shadowDy">-6.5</item>
+ </style>
+
+</resources>
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/res/values-v11/template-styles.xml b/samples/browseable/SwipeRefreshLayoutBasic/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/res/values/base-strings.xml b/samples/browseable/SwipeRefreshLayoutBasic/res/values/base-strings.xml
new file mode 100644
index 0000000..665d16f
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/res/values/base-strings.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+
+
+
+<resources>
+ <string name="app_name">SwipeRefreshLayoutBasic</string>
+ <string name="intro_message">
+ <![CDATA[
+
+
+ A basic sample which shows how to use SwipeRefreshLayout to add the \'swipe-to-refresh\'
+ gesture to a View, enabling the ability to trigger a refresh from swiping down on the view.
+ In this sample the View which can be refreshed is a ListView.
+
+
+ ]]>
+ </string>
+</resources>
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/res/values/colors.xml b/samples/browseable/SwipeRefreshLayoutBasic/res/values/colors.xml
new file mode 100644
index 0000000..ae1119e
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/res/values/colors.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <color name="swipe_color_1">#B6DB49</color>
+ <color name="swipe_color_2">#99CC00</color>
+ <color name="swipe_color_3">#8ABD00</color>
+ <color name="swipe_color_4">#7CAF00</color>
+
+</resources>
\ No newline at end of file
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/res/values/strings.xml b/samples/browseable/SwipeRefreshLayoutBasic/res/values/strings.xml
new file mode 100755
index 0000000..7b9d9ec
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/res/values/strings.xml
@@ -0,0 +1,19 @@
+<!--
+ 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.
+-->
+<resources>
+ <string name="sample_show_log">Show Log</string>
+ <string name="sample_hide_log">Hide Log</string>
+</resources>
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/res/values/template-dimens.xml b/samples/browseable/SwipeRefreshLayoutBasic/res/values/template-dimens.xml
new file mode 100644
index 0000000..39e710b
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/res/values/template-dimens.xml
@@ -0,0 +1,32 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Define standard dimensions to comply with Holo-style grids and rhythm. -->
+
+ <dimen name="margin_tiny">4dp</dimen>
+ <dimen name="margin_small">8dp</dimen>
+ <dimen name="margin_medium">16dp</dimen>
+ <dimen name="margin_large">32dp</dimen>
+ <dimen name="margin_huge">64dp</dimen>
+
+ <!-- Semantic definitions -->
+
+ <dimen name="horizontal_page_margin">@dimen/margin_medium</dimen>
+ <dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
+
+</resources>
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/res/values/template-styles.xml b/samples/browseable/SwipeRefreshLayoutBasic/res/values/template-styles.xml
new file mode 100644
index 0000000..6e7d593
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/res/values/template-styles.xml
@@ -0,0 +1,42 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+
+ <style name="Theme.Base" parent="android:Theme.Light" />
+
+ <style name="Theme.Sample" parent="Theme.Base" />
+
+ <style name="AppTheme" parent="Theme.Sample" />
+ <!-- Widget styling -->
+
+ <style name="Widget" />
+
+ <style name="Widget.SampleMessage">
+ <item name="android:textAppearance">?android:textAppearanceMedium</item>
+ <item name="android:lineSpacingMultiplier">1.1</item>
+ </style>
+
+ <style name="Widget.SampleMessageTile">
+ <item name="android:background">@drawable/tile</item>
+ <item name="android:shadowColor">#7F000000</item>
+ <item name="android:shadowDy">-3.5</item>
+ <item name="android:shadowRadius">2</item>
+ </style>
+
+</resources>
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.common/activities/SampleActivityBase.java b/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.common/activities/SampleActivityBase.java
new file mode 100644
index 0000000..3228927
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.common/activities/SampleActivityBase.java
@@ -0,0 +1,52 @@
+/*
+* 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.
+*/
+
+package com.example.android.common.activities;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+
+import com.example.android.common.logger.Log;
+import com.example.android.common.logger.LogWrapper;
+
+/**
+ * Base launcher activity, to handle most of the common plumbing for samples.
+ */
+public class SampleActivityBase extends FragmentActivity {
+
+ public static final String TAG = "SampleActivityBase";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ initializeLogging();
+ }
+
+ /** Set up targets to receive log data */
+ public void initializeLogging() {
+ // Using Log, front-end to the logging chain, emulates android.util.log method signatures.
+ // Wraps Android's native log framework
+ LogWrapper logWrapper = new LogWrapper();
+ Log.setLogNode(logWrapper);
+
+ Log.i(TAG, "Ready");
+ }
+}
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.common/dummydata/Cheeses.java b/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.common/dummydata/Cheeses.java
new file mode 100644
index 0000000..783735c
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.common/dummydata/Cheeses.java
@@ -0,0 +1,186 @@
+/*
+ * 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.
+ */
+
+package com.example.android.common.dummydata;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Random;
+
+/**
+ * Dummy data.
+ */
+public class Cheeses {
+ static final String[] CHEESES = {
+ "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi",
+ "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale",
+ "Aisy Cendre", "Allgauer Emmentaler", "Alverca", "Ambert", "American Cheese",
+ "Ami du Chambertin", "Anejo Enchilado", "Anneau du Vic-Bilh", "Anthoriro", "Appenzell",
+ "Aragon", "Ardi Gasna", "Ardrahan", "Armenian String", "Aromes au Gene de Marc",
+ "Asadero", "Asiago", "Aubisque Pyrenees", "Autun", "Avaxtskyr", "Baby Swiss",
+ "Babybel", "Baguette Laonnaise", "Bakers", "Baladi", "Balaton", "Bandal", "Banon",
+ "Barry's Bay Cheddar", "Basing", "Basket Cheese", "Bath Cheese", "Bavarian Bergkase",
+ "Baylough", "Beaufort", "Beauvoorde", "Beenleigh Blue", "Beer Cheese", "Bel Paese",
+ "Bergader", "Bergere Bleue", "Berkswell", "Beyaz Peynir", "Bierkase", "Bishop Kennedy",
+ "Blarney", "Bleu d'Auvergne", "Bleu de Gex", "Bleu de Laqueuille",
+ "Bleu de Septmoncel", "Bleu Des Causses", "Blue", "Blue Castello", "Blue Rathgore",
+ "Blue Vein (Australian)", "Blue Vein Cheeses", "Bocconcini", "Bocconcini (Australian)",
+ "Boeren Leidenkaas", "Bonchester", "Bosworth", "Bougon", "Boule Du Roves",
+ "Boulette d'Avesnes", "Boursault", "Boursin", "Bouyssou", "Bra", "Braudostur",
+ "Breakfast Cheese", "Brebis du Lavort", "Brebis du Lochois", "Brebis du Puyfaucon",
+ "Bresse Bleu", "Brick", "Brie", "Brie de Meaux", "Brie de Melun", "Brillat-Savarin",
+ "Brin", "Brin d' Amour", "Brin d'Amour", "Brinza (Burduf Brinza)",
+ "Briquette de Brebis", "Briquette du Forez", "Broccio", "Broccio Demi-Affine",
+ "Brousse du Rove", "Bruder Basil", "Brusselae Kaas (Fromage de Bruxelles)", "Bryndza",
+ "Buchette d'Anjou", "Buffalo", "Burgos", "Butte", "Butterkase", "Button (Innes)",
+ "Buxton Blue", "Cabecou", "Caboc", "Cabrales", "Cachaille", "Caciocavallo", "Caciotta",
+ "Caerphilly", "Cairnsmore", "Calenzana", "Cambazola", "Camembert de Normandie",
+ "Canadian Cheddar", "Canestrato", "Cantal", "Caprice des Dieux", "Capricorn Goat",
+ "Capriole Banon", "Carre de l'Est", "Casciotta di Urbino", "Cashel Blue", "Castellano",
+ "Castelleno", "Castelmagno", "Castelo Branco", "Castigliano", "Cathelain",
+ "Celtic Promise", "Cendre d'Olivet", "Cerney", "Chabichou", "Chabichou du Poitou",
+ "Chabis de Gatine", "Chaource", "Charolais", "Chaumes", "Cheddar",
+ "Cheddar Clothbound", "Cheshire", "Chevres", "Chevrotin des Aravis", "Chontaleno",
+ "Civray", "Coeur de Camembert au Calvados", "Coeur de Chevre", "Colby", "Cold Pack",
+ "Comte", "Coolea", "Cooleney", "Coquetdale", "Corleggy", "Cornish Pepper",
+ "Cotherstone", "Cotija", "Cottage Cheese", "Cottage Cheese (Australian)",
+ "Cougar Gold", "Coulommiers", "Coverdale", "Crayeux de Roncq", "Cream Cheese",
+ "Cream Havarti", "Crema Agria", "Crema Mexicana", "Creme Fraiche", "Crescenza",
+ "Croghan", "Crottin de Chavignol", "Crottin du Chavignol", "Crowdie", "Crowley",
+ "Cuajada", "Curd", "Cure Nantais", "Curworthy", "Cwmtawe Pecorino",
+ "Cypress Grove Chevre", "Danablu (Danish Blue)", "Danbo", "Danish Fontina",
+ "Daralagjazsky", "Dauphin", "Delice des Fiouves", "Denhany Dorset Drum", "Derby",
+ "Dessertnyj Belyj", "Devon Blue", "Devon Garland", "Dolcelatte", "Doolin",
+ "Doppelrhamstufel", "Dorset Blue Vinney", "Double Gloucester", "Double Worcester",
+ "Dreux a la Feuille", "Dry Jack", "Duddleswell", "Dunbarra", "Dunlop", "Dunsyre Blue",
+ "Duroblando", "Durrus", "Dutch Mimolette (Commissiekaas)", "Edam", "Edelpilz",
+ "Emental Grand Cru", "Emlett", "Emmental", "Epoisses de Bourgogne", "Esbareich",
+ "Esrom", "Etorki", "Evansdale Farmhouse Brie", "Evora De L'Alentejo", "Exmoor Blue",
+ "Explorateur", "Feta", "Feta (Australian)", "Figue", "Filetta", "Fin-de-Siecle",
+ "Finlandia Swiss", "Finn", "Fiore Sardo", "Fleur du Maquis", "Flor de Guia",
+ "Flower Marie", "Folded", "Folded cheese with mint", "Fondant de Brebis",
+ "Fontainebleau", "Fontal", "Fontina Val d'Aosta", "Formaggio di capra", "Fougerus",
+ "Four Herb Gouda", "Fourme d' Ambert", "Fourme de Haute Loire", "Fourme de Montbrison",
+ "Fresh Jack", "Fresh Mozzarella", "Fresh Ricotta", "Fresh Truffles", "Fribourgeois",
+ "Friesekaas", "Friesian", "Friesla", "Frinault", "Fromage a Raclette", "Fromage Corse",
+ "Fromage de Montagne de Savoie", "Fromage Frais", "Fruit Cream Cheese",
+ "Frying Cheese", "Fynbo", "Gabriel", "Galette du Paludier", "Galette Lyonnaise",
+ "Galloway Goat's Milk Gems", "Gammelost", "Gaperon a l'Ail", "Garrotxa", "Gastanberra",
+ "Geitost", "Gippsland Blue", "Gjetost", "Gloucester", "Golden Cross", "Gorgonzola",
+ "Gornyaltajski", "Gospel Green", "Gouda", "Goutu", "Gowrie", "Grabetto", "Graddost",
+ "Grafton Village Cheddar", "Grana", "Grana Padano", "Grand Vatel",
+ "Grataron d' Areches", "Gratte-Paille", "Graviera", "Greuilh", "Greve",
+ "Gris de Lille", "Gruyere", "Gubbeen", "Guerbigny", "Halloumi",
+ "Halloumy (Australian)", "Haloumi-Style Cheese", "Harbourne Blue", "Havarti",
+ "Heidi Gruyere", "Hereford Hop", "Herrgardsost", "Herriot Farmhouse", "Herve",
+ "Hipi Iti", "Hubbardston Blue Cow", "Hushallsost", "Iberico", "Idaho Goatster",
+ "Idiazabal", "Il Boschetto al Tartufo", "Ile d'Yeu", "Isle of Mull", "Jarlsberg",
+ "Jermi Tortes", "Jibneh Arabieh", "Jindi Brie", "Jubilee Blue", "Juustoleipa",
+ "Kadchgall", "Kaseri", "Kashta", "Kefalotyri", "Kenafa", "Kernhem", "Kervella Affine",
+ "Kikorangi", "King Island Cape Wickham Brie", "King River Gold", "Klosterkaese",
+ "Knockalara", "Kugelkase", "L'Aveyronnais", "L'Ecir de l'Aubrac", "La Taupiniere",
+ "La Vache Qui Rit", "Laguiole", "Lairobell", "Lajta", "Lanark Blue", "Lancashire",
+ "Langres", "Lappi", "Laruns", "Lavistown", "Le Brin", "Le Fium Orbo", "Le Lacandou",
+ "Le Roule", "Leafield", "Lebbene", "Leerdammer", "Leicester", "Leyden", "Limburger",
+ "Lincolnshire Poacher", "Lingot Saint Bousquet d'Orb", "Liptauer", "Little Rydings",
+ "Livarot", "Llanboidy", "Llanglofan Farmhouse", "Loch Arthur Farmhouse",
+ "Loddiswell Avondale", "Longhorn", "Lou Palou", "Lou Pevre", "Lyonnais", "Maasdam",
+ "Macconais", "Mahoe Aged Gouda", "Mahon", "Malvern", "Mamirolle", "Manchego",
+ "Manouri", "Manur", "Marble Cheddar", "Marbled Cheeses", "Maredsous", "Margotin",
+ "Maribo", "Maroilles", "Mascares", "Mascarpone", "Mascarpone (Australian)",
+ "Mascarpone Torta", "Matocq", "Maytag Blue", "Meira", "Menallack Farmhouse",
+ "Menonita", "Meredith Blue", "Mesost", "Metton (Cancoillotte)", "Meyer Vintage Gouda",
+ "Mihalic Peynir", "Milleens", "Mimolette", "Mine-Gabhar", "Mini Baby Bells", "Mixte",
+ "Molbo", "Monastery Cheeses", "Mondseer", "Mont D'or Lyonnais", "Montasio",
+ "Monterey Jack", "Monterey Jack Dry", "Morbier", "Morbier Cru de Montagne",
+ "Mothais a la Feuille", "Mozzarella", "Mozzarella (Australian)",
+ "Mozzarella di Bufala", "Mozzarella Fresh, in water", "Mozzarella Rolls", "Munster",
+ "Murol", "Mycella", "Myzithra", "Naboulsi", "Nantais", "Neufchatel",
+ "Neufchatel (Australian)", "Niolo", "Nokkelost", "Northumberland", "Oaxaca",
+ "Olde York", "Olivet au Foin", "Olivet Bleu", "Olivet Cendre",
+ "Orkney Extra Mature Cheddar", "Orla", "Oschtjepka", "Ossau Fermier", "Ossau-Iraty",
+ "Oszczypek", "Oxford Blue", "P'tit Berrichon", "Palet de Babligny", "Paneer", "Panela",
+ "Pannerone", "Pant ys Gawn", "Parmesan (Parmigiano)", "Parmigiano Reggiano",
+ "Pas de l'Escalette", "Passendale", "Pasteurized Processed", "Pate de Fromage",
+ "Patefine Fort", "Pave d'Affinois", "Pave d'Auge", "Pave de Chirac", "Pave du Berry",
+ "Pecorino", "Pecorino in Walnut Leaves", "Pecorino Romano", "Peekskill Pyramid",
+ "Pelardon des Cevennes", "Pelardon des Corbieres", "Penamellera", "Penbryn",
+ "Pencarreg", "Perail de Brebis", "Petit Morin", "Petit Pardou", "Petit-Suisse",
+ "Picodon de Chevre", "Picos de Europa", "Piora", "Pithtviers au Foin",
+ "Plateau de Herve", "Plymouth Cheese", "Podhalanski", "Poivre d'Ane", "Polkolbin",
+ "Pont l'Eveque", "Port Nicholson", "Port-Salut", "Postel", "Pouligny-Saint-Pierre",
+ "Pourly", "Prastost", "Pressato", "Prince-Jean", "Processed Cheddar", "Provolone",
+ "Provolone (Australian)", "Pyengana Cheddar", "Pyramide", "Quark",
+ "Quark (Australian)", "Quartirolo Lombardo", "Quatre-Vents", "Quercy Petit",
+ "Queso Blanco", "Queso Blanco con Frutas --Pina y Mango", "Queso de Murcia",
+ "Queso del Montsec", "Queso del Tietar", "Queso Fresco", "Queso Fresco (Adobera)",
+ "Queso Iberico", "Queso Jalapeno", "Queso Majorero", "Queso Media Luna",
+ "Queso Para Frier", "Queso Quesadilla", "Rabacal", "Raclette", "Ragusano", "Raschera",
+ "Reblochon", "Red Leicester", "Regal de la Dombes", "Reggianito", "Remedou",
+ "Requeson", "Richelieu", "Ricotta", "Ricotta (Australian)", "Ricotta Salata", "Ridder",
+ "Rigotte", "Rocamadour", "Rollot", "Romano", "Romans Part Dieu", "Roncal", "Roquefort",
+ "Roule", "Rouleau De Beaulieu", "Royalp Tilsit", "Rubens", "Rustinu", "Saaland Pfarr",
+ "Saanenkaese", "Saga", "Sage Derby", "Sainte Maure", "Saint-Marcellin",
+ "Saint-Nectaire", "Saint-Paulin", "Salers", "Samso", "San Simon", "Sancerre",
+ "Sap Sago", "Sardo", "Sardo Egyptian", "Sbrinz", "Scamorza", "Schabzieger", "Schloss",
+ "Selles sur Cher", "Selva", "Serat", "Seriously Strong Cheddar", "Serra da Estrela",
+ "Sharpam", "Shelburne Cheddar", "Shropshire Blue", "Siraz", "Sirene", "Smoked Gouda",
+ "Somerset Brie", "Sonoma Jack", "Sottocenare al Tartufo", "Soumaintrain",
+ "Sourire Lozerien", "Spenwood", "Sraffordshire Organic", "St. Agur Blue Cheese",
+ "Stilton", "Stinking Bishop", "String", "Sussex Slipcote", "Sveciaost", "Swaledale",
+ "Sweet Style Swiss", "Swiss", "Syrian (Armenian String)", "Tala", "Taleggio", "Tamie",
+ "Tasmania Highland Chevre Log", "Taupiniere", "Teifi", "Telemea", "Testouri",
+ "Tete de Moine", "Tetilla", "Texas Goat Cheese", "Tibet", "Tillamook Cheddar",
+ "Tilsit", "Timboon Brie", "Toma", "Tomme Brulee", "Tomme d'Abondance",
+ "Tomme de Chevre", "Tomme de Romans", "Tomme de Savoie", "Tomme des Chouans", "Tommes",
+ "Torta del Casar", "Toscanello", "Touree de L'Aubier", "Tourmalet",
+ "Trappe (Veritable)", "Trois Cornes De Vendee", "Tronchon", "Trou du Cru", "Truffe",
+ "Tupi", "Turunmaa", "Tymsboro", "Tyn Grug", "Tyning", "Ubriaco", "Ulloa",
+ "Vacherin-Fribourgeois", "Valencay", "Vasterbottenost", "Venaco", "Vendomois",
+ "Vieux Corse", "Vignotte", "Vulscombe", "Waimata Farmhouse Blue",
+ "Washed Rind Cheese (Australian)", "Waterloo", "Weichkaese", "Wellington",
+ "Wensleydale", "White Stilton", "Whitestone Farmhouse", "Wigmore", "Woodside Cabecou",
+ "Xanadu", "Xynotyro", "Yarg Cornish", "Yarra Valley Pyramid", "Yorkshire Blue",
+ "Zamorano", "Zanetti Grana Padano", "Zanetti Parmigiano Reggiano"
+ };
+
+ public static ArrayList<String> asList() {
+ ArrayList<String> items = new ArrayList<String>();
+ for (int i = 0, z = CHEESES.length ; i < z ; i++) {
+ items.add(CHEESES[i]);
+ }
+ return items;
+ }
+
+ /**
+ * Return a list of random cheeses.
+ *
+ * @param count the amount of cheeses to return.
+ */
+ public static ArrayList<String> randomList(int count) {
+ Random random = new Random();
+ HashSet<String> items = new HashSet<String>();
+
+ // Make sure that don't infinity loop
+ count = Math.min(count, CHEESES.length);
+
+ while (items.size() < count) {
+ items.add(CHEESES[random.nextInt(CHEESES.length)]);
+ }
+
+ return new ArrayList<String>(items);
+ }
+}
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.common/logger/Log.java b/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.common/logger/Log.java
new file mode 100644
index 0000000..17503c5
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.common/logger/Log.java
@@ -0,0 +1,236 @@
+/*
+ * 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.logger;
+
+/**
+ * Helper class for a list (or tree) of LoggerNodes.
+ *
+ * <p>When this is set as the head of the list,
+ * an instance of it can function as a drop-in replacement for {@link android.util.Log}.
+ * Most of the methods in this class server only to map a method call in Log to its equivalent
+ * in LogNode.</p>
+ */
+public class Log {
+ // Grabbing the native values from Android's native logging facilities,
+ // to make for easy migration and interop.
+ public static final int NONE = -1;
+ public static final int VERBOSE = android.util.Log.VERBOSE;
+ public static final int DEBUG = android.util.Log.DEBUG;
+ public static final int INFO = android.util.Log.INFO;
+ public static final int WARN = android.util.Log.WARN;
+ public static final int ERROR = android.util.Log.ERROR;
+ public static final int ASSERT = android.util.Log.ASSERT;
+
+ // Stores the beginning of the LogNode topology.
+ private static LogNode mLogNode;
+
+ /**
+ * Returns the next LogNode in the linked list.
+ */
+ public static LogNode getLogNode() {
+ return mLogNode;
+ }
+
+ /**
+ * Sets the LogNode data will be sent to.
+ */
+ public static void setLogNode(LogNode node) {
+ mLogNode = node;
+ }
+
+ /**
+ * Instructs the LogNode to print the log data provided. Other LogNodes can
+ * be chained to the end of the LogNode as desired.
+ *
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void println(int priority, String tag, String msg, Throwable tr) {
+ if (mLogNode != null) {
+ mLogNode.println(priority, tag, msg, tr);
+ }
+ }
+
+ /**
+ * Instructs the LogNode to print the log data provided. Other LogNodes can
+ * be chained to the end of the LogNode as desired.
+ *
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ */
+ public static void println(int priority, String tag, String msg) {
+ println(priority, tag, msg, null);
+ }
+
+ /**
+ * Prints a message at VERBOSE priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void v(String tag, String msg, Throwable tr) {
+ println(VERBOSE, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at VERBOSE priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void v(String tag, String msg) {
+ v(tag, msg, null);
+ }
+
+
+ /**
+ * Prints a message at DEBUG priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void d(String tag, String msg, Throwable tr) {
+ println(DEBUG, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at DEBUG priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void d(String tag, String msg) {
+ d(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at INFO priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void i(String tag, String msg, Throwable tr) {
+ println(INFO, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at INFO priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void i(String tag, String msg) {
+ i(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at WARN priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void w(String tag, String msg, Throwable tr) {
+ println(WARN, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at WARN priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void w(String tag, String msg) {
+ w(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at WARN priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void w(String tag, Throwable tr) {
+ w(tag, null, tr);
+ }
+
+ /**
+ * Prints a message at ERROR priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void e(String tag, String msg, Throwable tr) {
+ println(ERROR, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at ERROR priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void e(String tag, String msg) {
+ e(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at ASSERT priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void wtf(String tag, String msg, Throwable tr) {
+ println(ASSERT, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at ASSERT priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void wtf(String tag, String msg) {
+ wtf(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at ASSERT priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void wtf(String tag, Throwable tr) {
+ wtf(tag, null, tr);
+ }
+}
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.common/logger/LogFragment.java b/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.common/logger/LogFragment.java
new file mode 100644
index 0000000..b302acd
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.common/logger/LogFragment.java
@@ -0,0 +1,109 @@
+/*
+* 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 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.logger;
+
+import android.graphics.Typeface;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ScrollView;
+
+/**
+ * Simple fraggment which contains a LogView and uses is to output log data it receives
+ * through the LogNode interface.
+ */
+public class LogFragment extends Fragment {
+
+ private LogView mLogView;
+ private ScrollView mScrollView;
+
+ public LogFragment() {}
+
+ public View inflateViews() {
+ mScrollView = new ScrollView(getActivity());
+ ViewGroup.LayoutParams scrollParams = new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT);
+ mScrollView.setLayoutParams(scrollParams);
+
+ mLogView = new LogView(getActivity());
+ ViewGroup.LayoutParams logParams = new ViewGroup.LayoutParams(scrollParams);
+ logParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+ mLogView.setLayoutParams(logParams);
+ mLogView.setClickable(true);
+ mLogView.setFocusable(true);
+ mLogView.setTypeface(Typeface.MONOSPACE);
+
+ // Want to set padding as 16 dips, setPadding takes pixels. Hooray math!
+ int paddingDips = 16;
+ double scale = getResources().getDisplayMetrics().density;
+ int paddingPixels = (int) ((paddingDips * (scale)) + .5);
+ mLogView.setPadding(paddingPixels, paddingPixels, paddingPixels, paddingPixels);
+ mLogView.setCompoundDrawablePadding(paddingPixels);
+
+ mLogView.setGravity(Gravity.BOTTOM);
+ mLogView.setTextAppearance(getActivity(), android.R.style.TextAppearance_Holo_Medium);
+
+ mScrollView.addView(mLogView);
+ return mScrollView;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+
+ View result = inflateViews();
+
+ mLogView.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {}
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ mScrollView.fullScroll(ScrollView.FOCUS_DOWN);
+ }
+ });
+ return result;
+ }
+
+ public LogView getLogView() {
+ return mLogView;
+ }
+}
\ No newline at end of file
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.common/logger/LogNode.java b/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.common/logger/LogNode.java
new file mode 100644
index 0000000..bc37cab
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.common/logger/LogNode.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012 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.logger;
+
+/**
+ * Basic interface for a logging system that can output to one or more targets.
+ * Note that in addition to classes that will output these logs in some format,
+ * one can also implement this interface over a filter and insert that in the chain,
+ * such that no targets further down see certain data, or see manipulated forms of the data.
+ * You could, for instance, write a "ToHtmlLoggerNode" that just converted all the log data
+ * it received to HTML and sent it along to the next node in the chain, without printing it
+ * anywhere.
+ */
+public interface LogNode {
+
+ /**
+ * Instructs first LogNode in the list to print the log data provided.
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public void println(int priority, String tag, String msg, Throwable tr);
+
+}
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.common/logger/LogView.java b/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.common/logger/LogView.java
new file mode 100644
index 0000000..c01542b
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.common/logger/LogView.java
@@ -0,0 +1,145 @@
+/*
+ * 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.logger;
+
+import android.app.Activity;
+import android.content.Context;
+import android.util.*;
+import android.widget.TextView;
+
+/** Simple TextView which is used to output log data received through the LogNode interface.
+*/
+public class LogView extends TextView implements LogNode {
+
+ public LogView(Context context) {
+ super(context);
+ }
+
+ public LogView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public LogView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ /**
+ * Formats the log data and prints it out to the LogView.
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ @Override
+ public void println(int priority, String tag, String msg, Throwable tr) {
+
+
+ String priorityStr = null;
+
+ // For the purposes of this View, we want to print the priority as readable text.
+ switch(priority) {
+ case android.util.Log.VERBOSE:
+ priorityStr = "VERBOSE";
+ break;
+ case android.util.Log.DEBUG:
+ priorityStr = "DEBUG";
+ break;
+ case android.util.Log.INFO:
+ priorityStr = "INFO";
+ break;
+ case android.util.Log.WARN:
+ priorityStr = "WARN";
+ break;
+ case android.util.Log.ERROR:
+ priorityStr = "ERROR";
+ break;
+ case android.util.Log.ASSERT:
+ priorityStr = "ASSERT";
+ break;
+ default:
+ break;
+ }
+
+ // Handily, the Log class has a facility for converting a stack trace into a usable string.
+ String exceptionStr = null;
+ if (tr != null) {
+ exceptionStr = android.util.Log.getStackTraceString(tr);
+ }
+
+ // Take the priority, tag, message, and exception, and concatenate as necessary
+ // into one usable line of text.
+ final StringBuilder outputBuilder = new StringBuilder();
+
+ String delimiter = "\t";
+ appendIfNotNull(outputBuilder, priorityStr, delimiter);
+ appendIfNotNull(outputBuilder, tag, delimiter);
+ appendIfNotNull(outputBuilder, msg, delimiter);
+ appendIfNotNull(outputBuilder, exceptionStr, delimiter);
+
+ // In case this was originally called from an AsyncTask or some other off-UI thread,
+ // make sure the update occurs within the UI thread.
+ ((Activity) getContext()).runOnUiThread( (new Thread(new Runnable() {
+ @Override
+ public void run() {
+ // Display the text we just generated within the LogView.
+ appendToLog(outputBuilder.toString());
+ }
+ })));
+
+ if (mNext != null) {
+ mNext.println(priority, tag, msg, tr);
+ }
+ }
+
+ public LogNode getNext() {
+ return mNext;
+ }
+
+ public void setNext(LogNode node) {
+ mNext = node;
+ }
+
+ /** Takes a string and adds to it, with a separator, if the bit to be added isn't null. Since
+ * the logger takes so many arguments that might be null, this method helps cut out some of the
+ * agonizing tedium of writing the same 3 lines over and over.
+ * @param source StringBuilder containing the text to append to.
+ * @param addStr The String to append
+ * @param delimiter The String to separate the source and appended strings. A tab or comma,
+ * for instance.
+ * @return The fully concatenated String as a StringBuilder
+ */
+ private StringBuilder appendIfNotNull(StringBuilder source, String addStr, String delimiter) {
+ if (addStr != null) {
+ if (addStr.length() == 0) {
+ delimiter = "";
+ }
+
+ return source.append(addStr).append(delimiter);
+ }
+ return source;
+ }
+
+ // The next LogNode in the chain.
+ LogNode mNext;
+
+ /** Outputs the string as a new line of log data in the LogView. */
+ public void appendToLog(String s) {
+ append("\n" + s);
+ }
+
+
+}
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.common/logger/LogWrapper.java b/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.common/logger/LogWrapper.java
new file mode 100644
index 0000000..16a9e7b
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.common/logger/LogWrapper.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2012 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.logger;
+
+import android.util.Log;
+
+/**
+ * Helper class which wraps Android's native Log utility in the Logger interface. This way
+ * normal DDMS output can be one of the many targets receiving and outputting logs simultaneously.
+ */
+public class LogWrapper implements LogNode {
+
+ // For piping: The next node to receive Log data after this one has done its work.
+ private LogNode mNext;
+
+ /**
+ * Returns the next LogNode in the linked list.
+ */
+ public LogNode getNext() {
+ return mNext;
+ }
+
+ /**
+ * Sets the LogNode data will be sent to..
+ */
+ public void setNext(LogNode node) {
+ mNext = node;
+ }
+
+ /**
+ * Prints data out to the console using Android's native log mechanism.
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ @Override
+ public void println(int priority, String tag, String msg, Throwable tr) {
+ // There actually are log methods that don't take a msg parameter. For now,
+ // if that's the case, just convert null to the empty string and move on.
+ String useMsg = msg;
+ if (useMsg == null) {
+ useMsg = "";
+ }
+
+ // If an exeption was provided, convert that exception to a usable string and attach
+ // it to the end of the msg method.
+ if (tr != null) {
+ msg += "\n" + Log.getStackTraceString(tr);
+ }
+
+ // This is functionally identical to Log.x(tag, useMsg);
+ // For instance, if priority were Log.VERBOSE, this would be the same as Log.v(tag, useMsg)
+ Log.println(priority, tag, useMsg);
+
+ // If this isn't the last node in the chain, move things along.
+ if (mNext != null) {
+ mNext.println(priority, tag, msg, tr);
+ }
+ }
+}
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.common/logger/MessageOnlyLogFilter.java b/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.common/logger/MessageOnlyLogFilter.java
new file mode 100644
index 0000000..19967dc
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.common/logger/MessageOnlyLogFilter.java
@@ -0,0 +1,60 @@
+/*
+ * 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.logger;
+
+/**
+ * Simple {@link LogNode} filter, removes everything except the message.
+ * Useful for situations like on-screen log output where you don't want a lot of metadata displayed,
+ * just easy-to-read message updates as they're happening.
+ */
+public class MessageOnlyLogFilter implements LogNode {
+
+ LogNode mNext;
+
+ /**
+ * Takes the "next" LogNode as a parameter, to simplify chaining.
+ *
+ * @param next The next LogNode in the pipeline.
+ */
+ public MessageOnlyLogFilter(LogNode next) {
+ mNext = next;
+ }
+
+ public MessageOnlyLogFilter() {
+ }
+
+ @Override
+ public void println(int priority, String tag, String msg, Throwable tr) {
+ if (mNext != null) {
+ getNext().println(Log.NONE, null, msg, null);
+ }
+ }
+
+ /**
+ * Returns the next LogNode in the chain.
+ */
+ public LogNode getNext() {
+ return mNext;
+ }
+
+ /**
+ * Sets the LogNode data will be sent to..
+ */
+ public void setNext(LogNode node) {
+ mNext = node;
+ }
+
+}
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.common/view/SlidingTabLayout.java b/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.common/view/SlidingTabLayout.java
new file mode 100644
index 0000000..20049e3
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/src/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/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.common/view/SlidingTabStrip.java b/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.common/view/SlidingTabStrip.java
new file mode 100644
index 0000000..d5bbbae
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/src/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/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.swiperefreshlayoutbasic/MainActivity.java b/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.swiperefreshlayoutbasic/MainActivity.java
new file mode 100644
index 0000000..f90aed1
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.swiperefreshlayoutbasic/MainActivity.java
@@ -0,0 +1,110 @@
+/*
+* 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.
+*/
+
+
+
+
+package com.example.android.swiperefreshlayoutbasic;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentTransaction;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.ViewAnimator;
+
+import com.example.android.common.activities.SampleActivityBase;
+import com.example.android.common.logger.Log;
+import com.example.android.common.logger.LogFragment;
+import com.example.android.common.logger.LogWrapper;
+import com.example.android.common.logger.MessageOnlyLogFilter;
+
+/**
+ * A simple launcher activity containing a summary sample description, sample log and a custom
+ * {@link android.support.v4.app.Fragment} which can display a view.
+ * <p>
+ * For devices with displays with a width of 720dp or greater, the sample log is always visible,
+ * on other devices it's visibility is controlled by an item on the Action Bar.
+ */
+public class MainActivity extends SampleActivityBase {
+
+ public static final String TAG = "MainActivity";
+
+ // Whether the Log Fragment is currently shown
+ private boolean mLogShown;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+ SwipeRefreshLayoutBasicFragment fragment = new SwipeRefreshLayoutBasicFragment();
+ transaction.replace(R.id.sample_content_fragment, fragment);
+ transaction.commit();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.main, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ MenuItem logToggle = menu.findItem(R.id.menu_toggle_log);
+ logToggle.setVisible(findViewById(R.id.sample_output) instanceof ViewAnimator);
+ logToggle.setTitle(mLogShown ? R.string.sample_hide_log : R.string.sample_show_log);
+
+ return super.onPrepareOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch(item.getItemId()) {
+ case R.id.menu_toggle_log:
+ mLogShown = !mLogShown;
+ ViewAnimator output = (ViewAnimator) findViewById(R.id.sample_output);
+ if (mLogShown) {
+ output.setDisplayedChild(1);
+ } else {
+ output.setDisplayedChild(0);
+ }
+ supportInvalidateOptionsMenu();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ /** Create a chain of targets that will receive log data */
+ @Override
+ public void initializeLogging() {
+ // Wraps Android's native log framework.
+ LogWrapper logWrapper = new LogWrapper();
+ // Using Log, front-end to the logging chain, emulates android.util.log method signatures.
+ Log.setLogNode(logWrapper);
+
+ // Filter strips out everything except the message text.
+ MessageOnlyLogFilter msgFilter = new MessageOnlyLogFilter();
+ logWrapper.setNext(msgFilter);
+
+ // On screen logging via a fragment with a TextView.
+ LogFragment logFragment = (LogFragment) getSupportFragmentManager()
+ .findFragmentById(R.id.log_fragment);
+ msgFilter.setNext(logFragment.getLogView());
+
+ Log.i(TAG, "Ready");
+ }
+}
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.swiperefreshlayoutbasic/SwipeRefreshLayoutBasicFragment.java b/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.swiperefreshlayoutbasic/SwipeRefreshLayoutBasicFragment.java
new file mode 100644
index 0000000..13b22f5
--- /dev/null
+++ b/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.swiperefreshlayoutbasic/SwipeRefreshLayoutBasicFragment.java
@@ -0,0 +1,234 @@
+/*
+ * 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.swiperefreshlayoutbasic;
+
+import com.example.android.common.dummydata.Cheeses;
+import com.example.android.common.logger.Log;
+
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.widget.SwipeRefreshLayout;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+import java.util.List;
+
+/**
+ * A basic sample that shows how to use {@link android.support.v4.widget.SwipeRefreshLayout} to add
+ * the 'swipe-to-refresh' gesture to a layout. In this sample, SwipeRefreshLayout contains a
+ * scrollable {@link android.widget.ListView} as its only child.
+ *
+ * <p>To provide an accessible way to trigger the refresh, this app also provides a refresh
+ * action item.
+ *
+ * <p>In this sample app, the refresh updates the ListView with a random set of new items.
+ */
+public class SwipeRefreshLayoutBasicFragment extends Fragment {
+
+ private static final String LOG_TAG = SwipeRefreshLayoutBasicFragment.class.getSimpleName();
+
+ private static final int LIST_ITEM_COUNT = 20;
+
+ /**
+ * The {@link android.support.v4.widget.SwipeRefreshLayout} that detects swipe gestures and
+ * triggers callbacks in the app.
+ */
+ private SwipeRefreshLayout mSwipeRefreshLayout;
+
+ /**
+ * The {@link android.widget.ListView} that displays the content that should be refreshed.
+ */
+ private ListView mListView;
+
+ /**
+ * The {@link android.widget.ListAdapter} used to populate the {@link android.widget.ListView}
+ * defined in the previous statement.
+ */
+ private ArrayAdapter<String> mListAdapter;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Notify the system to allow an options menu for this fragment.
+ setHasOptionsMenu(true);
+ }
+
+ // BEGIN_INCLUDE (inflate_view)
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.fragment_sample, container, false);
+
+ // Retrieve the SwipeRefreshLayout and ListView instances
+ mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swiperefresh);
+
+ // BEGIN_INCLUDE (change_colors)
+ // Set the color scheme of the SwipeRefreshLayout by providing 4 color resource ids
+ mSwipeRefreshLayout.setColorScheme(
+ R.color.swipe_color_1, R.color.swipe_color_2,
+ R.color.swipe_color_3, R.color.swipe_color_4);
+ // END_INCLUDE (change_colors)
+
+ // Retrieve the ListView
+ mListView = (ListView) view.findViewById(android.R.id.list);
+
+ return view;
+ }
+ // END_INCLUDE (inflate_view)
+
+ // BEGIN_INCLUDE (setup_views)
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+
+ /**
+ * Create an ArrayAdapter to contain the data for the ListView. Each item in the ListView
+ * uses the system-defined simple_list_item_1 layout that contains one TextView.
+ */
+ mListAdapter = new ArrayAdapter<String>(
+ getActivity(),
+ android.R.layout.simple_list_item_1,
+ android.R.id.text1,
+ Cheeses.randomList(LIST_ITEM_COUNT));
+
+ // Set the adapter between the ListView and its backing data.
+ mListView.setAdapter(mListAdapter);
+
+ // BEGIN_INCLUDE (setup_refreshlistener)
+ /**
+ * Implement {@link SwipeRefreshLayout.OnRefreshListener}. When users do the "swipe to
+ * refresh" gesture, SwipeRefreshLayout invokes
+ * {@link SwipeRefreshLayout.OnRefreshListener#onRefresh onRefresh()}. In
+ * {@link SwipeRefreshLayout.OnRefreshListener#onRefresh onRefresh()}, call a method that
+ * refreshes the content. Call the same method in response to the Refresh action from the
+ * action bar.
+ */
+ mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
+ @Override
+ public void onRefresh() {
+ Log.i(LOG_TAG, "onRefresh called from SwipeRefreshLayout");
+
+ initiateRefresh();
+ }
+ });
+ // END_INCLUDE (setup_refreshlistener)
+ }
+ // END_INCLUDE (setup_views)
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ inflater.inflate(R.menu.main_menu, menu);
+ }
+
+ // BEGIN_INCLUDE (setup_refresh_menu_listener)
+ /**
+ * Respond to the user's selection of the Refresh action item. Start the SwipeRefreshLayout
+ * progress bar, then initiate the background task that refreshes the content.
+ */
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.menu_refresh:
+ Log.i(LOG_TAG, "Refresh menu item selected");
+
+ // We make sure that the SwipeRefreshLayout is displaying it's refreshing indicator
+ if (!mSwipeRefreshLayout.isRefreshing()) {
+ mSwipeRefreshLayout.setRefreshing(true);
+ }
+
+ // Start our refresh background task
+ initiateRefresh();
+
+ return true;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+ // END_INCLUDE (setup_refresh_menu_listener)
+
+ // BEGIN_INCLUDE (initiate_refresh)
+ /**
+ * By abstracting the refresh process to a single method, the app allows both the
+ * SwipeGestureLayout onRefresh() method and the Refresh action item to refresh the content.
+ */
+ private void initiateRefresh() {
+ Log.i(LOG_TAG, "initiateRefresh");
+
+ /**
+ * Execute the background task, which uses {@link android.os.AsyncTask} to load the data.
+ */
+ new DummyBackgroundTask().execute();
+ }
+ // END_INCLUDE (initiate_refresh)
+
+ // BEGIN_INCLUDE (refresh_complete)
+ /**
+ * When the AsyncTask finishes, it calls onRefreshComplete(), which updates the data in the
+ * ListAdapter and turns off the progress bar.
+ */
+ private void onRefreshComplete(List<String> result) {
+ Log.i(LOG_TAG, "onRefreshComplete");
+
+ // Remove all items from the ListAdapter, and then replace them with the new items
+ mListAdapter.clear();
+ for (String cheese : result) {
+ mListAdapter.add(cheese);
+ }
+
+ // Stop the refreshing indicator
+ mSwipeRefreshLayout.setRefreshing(false);
+ }
+ // END_INCLUDE (refresh_complete)
+
+ /**
+ * Dummy {@link AsyncTask} which simulates a long running task to fetch new cheeses.
+ */
+ private class DummyBackgroundTask extends AsyncTask<Void, Void, List<String>> {
+
+ static final int TASK_DURATION = 3 * 1000; // 3 seconds
+
+ @Override
+ protected List<String> doInBackground(Void... params) {
+ // Sleep for a small amount of time to simulate a background-task
+ try {
+ Thread.sleep(TASK_DURATION);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ // Return a new random list of cheeses
+ return Cheeses.randomList(LIST_ITEM_COUNT);
+ }
+
+ @Override
+ protected void onPostExecute(List<String> result) {
+ super.onPostExecute(result);
+
+ // Tell the Fragment that the refresh has completed
+ onRefreshComplete(result);
+ }
+
+ }
+}
diff --git a/samples/browseable/SwipeRefreshListFragment/AndroidManifest.xml b/samples/browseable/SwipeRefreshListFragment/AndroidManifest.xml
new file mode 100644
index 0000000..be44930
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/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.swiperefreshlistfragment"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <uses-sdk android:minSdkVersion="10" 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/samples/browseable/SwipeRefreshListFragment/_index.jd b/samples/browseable/SwipeRefreshListFragment/_index.jd
new file mode 100644
index 0000000..3a34bb0
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/_index.jd
@@ -0,0 +1,12 @@
+
+
+
+page.tags="SwipeRefreshListFragment"
+sample.group=UI
+@jd:body
+
+<p>This sample demonstrates how to use {@link android.support.v4.widget.SwipeRefreshLayout} within
+{@link android.app.ListFragment} to add the <em>swipe-to-refresh</em> gesture to a
+{@link android.widget.ListView}, which enables you to trigger a refresh by swiping down on that
+view. This functionality is provided by the <code>SwipeRefreshListFragment</code> class, which you
+can reuse.</p>
diff --git a/samples/browseable/SwipeRefreshListFragment/res/drawable-hdpi/ic_launcher.png b/samples/browseable/SwipeRefreshListFragment/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..b10c5c1
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/SwipeRefreshListFragment/res/drawable-hdpi/tile.9.png b/samples/browseable/SwipeRefreshListFragment/res/drawable-hdpi/tile.9.png
new file mode 100644
index 0000000..1358628
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/res/drawable-hdpi/tile.9.png
Binary files differ
diff --git a/samples/browseable/SwipeRefreshListFragment/res/drawable-mdpi/ic_launcher.png b/samples/browseable/SwipeRefreshListFragment/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..001eed9
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/SwipeRefreshListFragment/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/SwipeRefreshListFragment/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..6fe78cc
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/SwipeRefreshListFragment/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/SwipeRefreshListFragment/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..5f89875
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/SwipeRefreshListFragment/res/layout-w720dp/activity_main.xml b/samples/browseable/SwipeRefreshListFragment/res/layout-w720dp/activity_main.xml
new file mode 100755
index 0000000..c9a52f6
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/res/layout-w720dp/activity_main.xml
@@ -0,0 +1,73 @@
+<!--
+ 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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/sample_main_layout">
+
+ <LinearLayout
+ android:id="@+id/sample_output"
+ android:layout_width="0px"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:orientation="vertical">
+
+ <FrameLayout
+ style="@style/Widget.SampleMessageTile"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ style="@style/Widget.SampleMessage"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="@dimen/margin_medium"
+ android:paddingRight="@dimen/margin_medium"
+ android:paddingTop="@dimen/margin_large"
+ android:paddingBottom="@dimen/margin_large"
+ android:text="@string/intro_message" />
+ </FrameLayout>
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:background="@android:color/darker_gray" />
+
+ <fragment
+ android:name="com.example.android.common.logger.LogFragment"
+ android:id="@+id/log_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="0px"
+ android:layout_weight="1" />
+
+ </LinearLayout>
+
+ <View
+ android:layout_width="1dp"
+ android:layout_height="match_parent"
+ android:background="@android:color/darker_gray" />
+
+ <FrameLayout
+ android:id="@+id/sample_content_fragment"
+ android:layout_weight="2"
+ android:layout_width="0px"
+ android:layout_height="match_parent" />
+
+</LinearLayout>
+
+
diff --git a/samples/browseable/SwipeRefreshListFragment/res/layout/activity_main.xml b/samples/browseable/SwipeRefreshListFragment/res/layout/activity_main.xml
new file mode 100755
index 0000000..1ae4f98
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/res/layout/activity_main.xml
@@ -0,0 +1,65 @@
+<!--
+ 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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/sample_main_layout">
+
+ <ViewAnimator
+ android:id="@+id/sample_output"
+ android:layout_width="match_parent"
+ android:layout_height="0px"
+ android:layout_weight="1">
+
+ <ScrollView
+ style="@style/Widget.SampleMessageTile"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <TextView
+ style="@style/Widget.SampleMessage"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="@dimen/horizontal_page_margin"
+ android:paddingRight="@dimen/horizontal_page_margin"
+ android:paddingTop="@dimen/vertical_page_margin"
+ android:paddingBottom="@dimen/vertical_page_margin"
+ android:text="@string/intro_message" />
+ </ScrollView>
+
+ <fragment
+ android:name="com.example.android.common.logger.LogFragment"
+ android:id="@+id/log_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ </ViewAnimator>
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:background="@android:color/darker_gray" />
+
+ <FrameLayout
+ android:id="@+id/sample_content_fragment"
+ android:layout_weight="2"
+ android:layout_width="match_parent"
+ android:layout_height="0px" />
+
+</LinearLayout>
+
diff --git a/samples/browseable/SwipeRefreshListFragment/res/menu/main.xml b/samples/browseable/SwipeRefreshListFragment/res/menu/main.xml
new file mode 100644
index 0000000..b49c2c5
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/res/menu/main.xml
@@ -0,0 +1,21 @@
+<!--
+ 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.
+ -->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/menu_toggle_log"
+ android:showAsAction="always"
+ android:title="@string/sample_show_log" />
+</menu>
diff --git a/samples/browseable/SwipeRefreshListFragment/res/menu/main_menu.xml b/samples/browseable/SwipeRefreshListFragment/res/menu/main_menu.xml
new file mode 100644
index 0000000..c5e8954
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/res/menu/main_menu.xml
@@ -0,0 +1,59 @@
+<?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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <!--
+ A color scheme menu item used for demonstrating the use of SwipeRefreshLayout's color
+ scheme functionality. This kind of menu item should not be incorporated into your app,
+ it just to demonstrate the use of color. Instead you should choose a color scheme based
+ off of your application's branding.
+ -->
+ <item
+ android:id="@+id/menu_color_scheme"
+ android:title="@string/menu_color_scheme"
+ android:showAsAction="ifRoom">
+ <menu>
+ <group android:checkableBehavior="single">
+
+ <item
+ android:id="@+id/menu_color_scheme_1"
+ android:title="@string/menu_color_scheme_1" />
+
+ <item
+ android:id="@+id/menu_color_scheme_2"
+ android:title="@string/menu_color_scheme_2" />
+
+ <item
+ android:id="@+id/menu_color_scheme_3"
+ android:title="@string/menu_color_scheme_3" />
+
+ </group>
+ </menu>
+ </item>
+
+ <!--
+ Refresh action item which should be presented in the Action Bar's overflow area
+ by setting showAsAction='never'. This is so that users which are not using touch input
+ can still perform a refresh.
+ -->
+ <item
+ android:id="@+id/menu_refresh"
+ android:title="@string/menu_refresh"
+ android:showAsAction="never" />
+
+</menu>
\ No newline at end of file
diff --git a/samples/browseable/SwipeRefreshListFragment/res/values-sw600dp/template-dimens.xml b/samples/browseable/SwipeRefreshListFragment/res/values-sw600dp/template-dimens.xml
new file mode 100644
index 0000000..22074a2
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/res/values-sw600dp/template-dimens.xml
@@ -0,0 +1,24 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Semantic definitions -->
+
+ <dimen name="horizontal_page_margin">@dimen/margin_huge</dimen>
+ <dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
+
+</resources>
diff --git a/samples/browseable/SwipeRefreshListFragment/res/values-sw600dp/template-styles.xml b/samples/browseable/SwipeRefreshListFragment/res/values-sw600dp/template-styles.xml
new file mode 100644
index 0000000..03d1974
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/res/values-sw600dp/template-styles.xml
@@ -0,0 +1,25 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <style name="Widget.SampleMessage">
+ <item name="android:textAppearance">?android:textAppearanceLarge</item>
+ <item name="android:lineSpacingMultiplier">1.2</item>
+ <item name="android:shadowDy">-6.5</item>
+ </style>
+
+</resources>
diff --git a/samples/browseable/SwipeRefreshListFragment/res/values-v11/template-styles.xml b/samples/browseable/SwipeRefreshListFragment/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/SwipeRefreshListFragment/res/values/base-strings.xml b/samples/browseable/SwipeRefreshListFragment/res/values/base-strings.xml
new file mode 100644
index 0000000..f84c807
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/res/values/base-strings.xml
@@ -0,0 +1,34 @@
+<?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.
+-->
+
+
+
+<resources>
+ <string name="app_name">SwipeRefreshListFragment</string>
+ <string name="intro_message">
+ <![CDATA[
+
+
+ A sample which shows how to use SwipeRefreshLayout within a ListFragment to add the
+ \'swipe-to-refresh\' gesture to a ListView, enabling the ability to trigger a refresh
+ from swiping down on that view. This is provided through the re-usable
+ SwipeRefreshListFragment class.
+
+
+ ]]>
+ </string>
+</resources>
diff --git a/samples/browseable/SwipeRefreshListFragment/res/values/colors.xml b/samples/browseable/SwipeRefreshListFragment/res/values/colors.xml
new file mode 100644
index 0000000..ae19990
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/res/values/colors.xml
@@ -0,0 +1,44 @@
+<?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>
+
+ <!--
+ These are the different color schemes to be displayed by the SwipeRefreshLayout's loading
+ indicator. It expects exactly four colors.
+
+ Color scheme #1: a selection of holo colors.
+ Color scheme #2: a graduation of holo blue.
+ Color scheme #3: a graduation of holo green.
+ -->
+
+ <color name="color_scheme_1_1">#33B5E5</color>
+ <color name="color_scheme_1_2">#99CC00</color>
+ <color name="color_scheme_1_3">#FFBB33</color>
+ <color name="color_scheme_1_4">#FF4444</color>
+
+ <color name="color_scheme_2_1">#6DCAEC</color>
+ <color name="color_scheme_2_2">#33B5E5</color>
+ <color name="color_scheme_2_3">#24ADDE</color>
+ <color name="color_scheme_2_4">#16A5D7</color>
+
+ <color name="color_scheme_3_1">#B6DB49</color>
+ <color name="color_scheme_3_2">#99CC00</color>
+ <color name="color_scheme_3_3">#8ABD00</color>
+ <color name="color_scheme_3_4">#7CAF00</color>
+
+</resources>
\ No newline at end of file
diff --git a/samples/browseable/SwipeRefreshListFragment/res/values/strings.xml b/samples/browseable/SwipeRefreshListFragment/res/values/strings.xml
new file mode 100755
index 0000000..7b9d9ec
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/res/values/strings.xml
@@ -0,0 +1,19 @@
+<!--
+ 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.
+-->
+<resources>
+ <string name="sample_show_log">Show Log</string>
+ <string name="sample_hide_log">Hide Log</string>
+</resources>
diff --git a/samples/browseable/SwipeRefreshListFragment/res/values/template-dimens.xml b/samples/browseable/SwipeRefreshListFragment/res/values/template-dimens.xml
new file mode 100644
index 0000000..39e710b
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/res/values/template-dimens.xml
@@ -0,0 +1,32 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Define standard dimensions to comply with Holo-style grids and rhythm. -->
+
+ <dimen name="margin_tiny">4dp</dimen>
+ <dimen name="margin_small">8dp</dimen>
+ <dimen name="margin_medium">16dp</dimen>
+ <dimen name="margin_large">32dp</dimen>
+ <dimen name="margin_huge">64dp</dimen>
+
+ <!-- Semantic definitions -->
+
+ <dimen name="horizontal_page_margin">@dimen/margin_medium</dimen>
+ <dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
+
+</resources>
diff --git a/samples/browseable/SwipeRefreshListFragment/res/values/template-styles.xml b/samples/browseable/SwipeRefreshListFragment/res/values/template-styles.xml
new file mode 100644
index 0000000..6e7d593
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/res/values/template-styles.xml
@@ -0,0 +1,42 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+
+ <style name="Theme.Base" parent="android:Theme.Light" />
+
+ <style name="Theme.Sample" parent="Theme.Base" />
+
+ <style name="AppTheme" parent="Theme.Sample" />
+ <!-- Widget styling -->
+
+ <style name="Widget" />
+
+ <style name="Widget.SampleMessage">
+ <item name="android:textAppearance">?android:textAppearanceMedium</item>
+ <item name="android:lineSpacingMultiplier">1.1</item>
+ </style>
+
+ <style name="Widget.SampleMessageTile">
+ <item name="android:background">@drawable/tile</item>
+ <item name="android:shadowColor">#7F000000</item>
+ <item name="android:shadowDy">-3.5</item>
+ <item name="android:shadowRadius">2</item>
+ </style>
+
+</resources>
diff --git a/samples/browseable/SwipeRefreshListFragment/src/com.example.android.common/activities/SampleActivityBase.java b/samples/browseable/SwipeRefreshListFragment/src/com.example.android.common/activities/SampleActivityBase.java
new file mode 100644
index 0000000..3228927
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/src/com.example.android.common/activities/SampleActivityBase.java
@@ -0,0 +1,52 @@
+/*
+* 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.
+*/
+
+package com.example.android.common.activities;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+
+import com.example.android.common.logger.Log;
+import com.example.android.common.logger.LogWrapper;
+
+/**
+ * Base launcher activity, to handle most of the common plumbing for samples.
+ */
+public class SampleActivityBase extends FragmentActivity {
+
+ public static final String TAG = "SampleActivityBase";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ initializeLogging();
+ }
+
+ /** Set up targets to receive log data */
+ public void initializeLogging() {
+ // Using Log, front-end to the logging chain, emulates android.util.log method signatures.
+ // Wraps Android's native log framework
+ LogWrapper logWrapper = new LogWrapper();
+ Log.setLogNode(logWrapper);
+
+ Log.i(TAG, "Ready");
+ }
+}
diff --git a/samples/browseable/SwipeRefreshListFragment/src/com.example.android.common/dummydata/Cheeses.java b/samples/browseable/SwipeRefreshListFragment/src/com.example.android.common/dummydata/Cheeses.java
new file mode 100644
index 0000000..783735c
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/src/com.example.android.common/dummydata/Cheeses.java
@@ -0,0 +1,186 @@
+/*
+ * 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.
+ */
+
+package com.example.android.common.dummydata;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Random;
+
+/**
+ * Dummy data.
+ */
+public class Cheeses {
+ static final String[] CHEESES = {
+ "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi",
+ "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale",
+ "Aisy Cendre", "Allgauer Emmentaler", "Alverca", "Ambert", "American Cheese",
+ "Ami du Chambertin", "Anejo Enchilado", "Anneau du Vic-Bilh", "Anthoriro", "Appenzell",
+ "Aragon", "Ardi Gasna", "Ardrahan", "Armenian String", "Aromes au Gene de Marc",
+ "Asadero", "Asiago", "Aubisque Pyrenees", "Autun", "Avaxtskyr", "Baby Swiss",
+ "Babybel", "Baguette Laonnaise", "Bakers", "Baladi", "Balaton", "Bandal", "Banon",
+ "Barry's Bay Cheddar", "Basing", "Basket Cheese", "Bath Cheese", "Bavarian Bergkase",
+ "Baylough", "Beaufort", "Beauvoorde", "Beenleigh Blue", "Beer Cheese", "Bel Paese",
+ "Bergader", "Bergere Bleue", "Berkswell", "Beyaz Peynir", "Bierkase", "Bishop Kennedy",
+ "Blarney", "Bleu d'Auvergne", "Bleu de Gex", "Bleu de Laqueuille",
+ "Bleu de Septmoncel", "Bleu Des Causses", "Blue", "Blue Castello", "Blue Rathgore",
+ "Blue Vein (Australian)", "Blue Vein Cheeses", "Bocconcini", "Bocconcini (Australian)",
+ "Boeren Leidenkaas", "Bonchester", "Bosworth", "Bougon", "Boule Du Roves",
+ "Boulette d'Avesnes", "Boursault", "Boursin", "Bouyssou", "Bra", "Braudostur",
+ "Breakfast Cheese", "Brebis du Lavort", "Brebis du Lochois", "Brebis du Puyfaucon",
+ "Bresse Bleu", "Brick", "Brie", "Brie de Meaux", "Brie de Melun", "Brillat-Savarin",
+ "Brin", "Brin d' Amour", "Brin d'Amour", "Brinza (Burduf Brinza)",
+ "Briquette de Brebis", "Briquette du Forez", "Broccio", "Broccio Demi-Affine",
+ "Brousse du Rove", "Bruder Basil", "Brusselae Kaas (Fromage de Bruxelles)", "Bryndza",
+ "Buchette d'Anjou", "Buffalo", "Burgos", "Butte", "Butterkase", "Button (Innes)",
+ "Buxton Blue", "Cabecou", "Caboc", "Cabrales", "Cachaille", "Caciocavallo", "Caciotta",
+ "Caerphilly", "Cairnsmore", "Calenzana", "Cambazola", "Camembert de Normandie",
+ "Canadian Cheddar", "Canestrato", "Cantal", "Caprice des Dieux", "Capricorn Goat",
+ "Capriole Banon", "Carre de l'Est", "Casciotta di Urbino", "Cashel Blue", "Castellano",
+ "Castelleno", "Castelmagno", "Castelo Branco", "Castigliano", "Cathelain",
+ "Celtic Promise", "Cendre d'Olivet", "Cerney", "Chabichou", "Chabichou du Poitou",
+ "Chabis de Gatine", "Chaource", "Charolais", "Chaumes", "Cheddar",
+ "Cheddar Clothbound", "Cheshire", "Chevres", "Chevrotin des Aravis", "Chontaleno",
+ "Civray", "Coeur de Camembert au Calvados", "Coeur de Chevre", "Colby", "Cold Pack",
+ "Comte", "Coolea", "Cooleney", "Coquetdale", "Corleggy", "Cornish Pepper",
+ "Cotherstone", "Cotija", "Cottage Cheese", "Cottage Cheese (Australian)",
+ "Cougar Gold", "Coulommiers", "Coverdale", "Crayeux de Roncq", "Cream Cheese",
+ "Cream Havarti", "Crema Agria", "Crema Mexicana", "Creme Fraiche", "Crescenza",
+ "Croghan", "Crottin de Chavignol", "Crottin du Chavignol", "Crowdie", "Crowley",
+ "Cuajada", "Curd", "Cure Nantais", "Curworthy", "Cwmtawe Pecorino",
+ "Cypress Grove Chevre", "Danablu (Danish Blue)", "Danbo", "Danish Fontina",
+ "Daralagjazsky", "Dauphin", "Delice des Fiouves", "Denhany Dorset Drum", "Derby",
+ "Dessertnyj Belyj", "Devon Blue", "Devon Garland", "Dolcelatte", "Doolin",
+ "Doppelrhamstufel", "Dorset Blue Vinney", "Double Gloucester", "Double Worcester",
+ "Dreux a la Feuille", "Dry Jack", "Duddleswell", "Dunbarra", "Dunlop", "Dunsyre Blue",
+ "Duroblando", "Durrus", "Dutch Mimolette (Commissiekaas)", "Edam", "Edelpilz",
+ "Emental Grand Cru", "Emlett", "Emmental", "Epoisses de Bourgogne", "Esbareich",
+ "Esrom", "Etorki", "Evansdale Farmhouse Brie", "Evora De L'Alentejo", "Exmoor Blue",
+ "Explorateur", "Feta", "Feta (Australian)", "Figue", "Filetta", "Fin-de-Siecle",
+ "Finlandia Swiss", "Finn", "Fiore Sardo", "Fleur du Maquis", "Flor de Guia",
+ "Flower Marie", "Folded", "Folded cheese with mint", "Fondant de Brebis",
+ "Fontainebleau", "Fontal", "Fontina Val d'Aosta", "Formaggio di capra", "Fougerus",
+ "Four Herb Gouda", "Fourme d' Ambert", "Fourme de Haute Loire", "Fourme de Montbrison",
+ "Fresh Jack", "Fresh Mozzarella", "Fresh Ricotta", "Fresh Truffles", "Fribourgeois",
+ "Friesekaas", "Friesian", "Friesla", "Frinault", "Fromage a Raclette", "Fromage Corse",
+ "Fromage de Montagne de Savoie", "Fromage Frais", "Fruit Cream Cheese",
+ "Frying Cheese", "Fynbo", "Gabriel", "Galette du Paludier", "Galette Lyonnaise",
+ "Galloway Goat's Milk Gems", "Gammelost", "Gaperon a l'Ail", "Garrotxa", "Gastanberra",
+ "Geitost", "Gippsland Blue", "Gjetost", "Gloucester", "Golden Cross", "Gorgonzola",
+ "Gornyaltajski", "Gospel Green", "Gouda", "Goutu", "Gowrie", "Grabetto", "Graddost",
+ "Grafton Village Cheddar", "Grana", "Grana Padano", "Grand Vatel",
+ "Grataron d' Areches", "Gratte-Paille", "Graviera", "Greuilh", "Greve",
+ "Gris de Lille", "Gruyere", "Gubbeen", "Guerbigny", "Halloumi",
+ "Halloumy (Australian)", "Haloumi-Style Cheese", "Harbourne Blue", "Havarti",
+ "Heidi Gruyere", "Hereford Hop", "Herrgardsost", "Herriot Farmhouse", "Herve",
+ "Hipi Iti", "Hubbardston Blue Cow", "Hushallsost", "Iberico", "Idaho Goatster",
+ "Idiazabal", "Il Boschetto al Tartufo", "Ile d'Yeu", "Isle of Mull", "Jarlsberg",
+ "Jermi Tortes", "Jibneh Arabieh", "Jindi Brie", "Jubilee Blue", "Juustoleipa",
+ "Kadchgall", "Kaseri", "Kashta", "Kefalotyri", "Kenafa", "Kernhem", "Kervella Affine",
+ "Kikorangi", "King Island Cape Wickham Brie", "King River Gold", "Klosterkaese",
+ "Knockalara", "Kugelkase", "L'Aveyronnais", "L'Ecir de l'Aubrac", "La Taupiniere",
+ "La Vache Qui Rit", "Laguiole", "Lairobell", "Lajta", "Lanark Blue", "Lancashire",
+ "Langres", "Lappi", "Laruns", "Lavistown", "Le Brin", "Le Fium Orbo", "Le Lacandou",
+ "Le Roule", "Leafield", "Lebbene", "Leerdammer", "Leicester", "Leyden", "Limburger",
+ "Lincolnshire Poacher", "Lingot Saint Bousquet d'Orb", "Liptauer", "Little Rydings",
+ "Livarot", "Llanboidy", "Llanglofan Farmhouse", "Loch Arthur Farmhouse",
+ "Loddiswell Avondale", "Longhorn", "Lou Palou", "Lou Pevre", "Lyonnais", "Maasdam",
+ "Macconais", "Mahoe Aged Gouda", "Mahon", "Malvern", "Mamirolle", "Manchego",
+ "Manouri", "Manur", "Marble Cheddar", "Marbled Cheeses", "Maredsous", "Margotin",
+ "Maribo", "Maroilles", "Mascares", "Mascarpone", "Mascarpone (Australian)",
+ "Mascarpone Torta", "Matocq", "Maytag Blue", "Meira", "Menallack Farmhouse",
+ "Menonita", "Meredith Blue", "Mesost", "Metton (Cancoillotte)", "Meyer Vintage Gouda",
+ "Mihalic Peynir", "Milleens", "Mimolette", "Mine-Gabhar", "Mini Baby Bells", "Mixte",
+ "Molbo", "Monastery Cheeses", "Mondseer", "Mont D'or Lyonnais", "Montasio",
+ "Monterey Jack", "Monterey Jack Dry", "Morbier", "Morbier Cru de Montagne",
+ "Mothais a la Feuille", "Mozzarella", "Mozzarella (Australian)",
+ "Mozzarella di Bufala", "Mozzarella Fresh, in water", "Mozzarella Rolls", "Munster",
+ "Murol", "Mycella", "Myzithra", "Naboulsi", "Nantais", "Neufchatel",
+ "Neufchatel (Australian)", "Niolo", "Nokkelost", "Northumberland", "Oaxaca",
+ "Olde York", "Olivet au Foin", "Olivet Bleu", "Olivet Cendre",
+ "Orkney Extra Mature Cheddar", "Orla", "Oschtjepka", "Ossau Fermier", "Ossau-Iraty",
+ "Oszczypek", "Oxford Blue", "P'tit Berrichon", "Palet de Babligny", "Paneer", "Panela",
+ "Pannerone", "Pant ys Gawn", "Parmesan (Parmigiano)", "Parmigiano Reggiano",
+ "Pas de l'Escalette", "Passendale", "Pasteurized Processed", "Pate de Fromage",
+ "Patefine Fort", "Pave d'Affinois", "Pave d'Auge", "Pave de Chirac", "Pave du Berry",
+ "Pecorino", "Pecorino in Walnut Leaves", "Pecorino Romano", "Peekskill Pyramid",
+ "Pelardon des Cevennes", "Pelardon des Corbieres", "Penamellera", "Penbryn",
+ "Pencarreg", "Perail de Brebis", "Petit Morin", "Petit Pardou", "Petit-Suisse",
+ "Picodon de Chevre", "Picos de Europa", "Piora", "Pithtviers au Foin",
+ "Plateau de Herve", "Plymouth Cheese", "Podhalanski", "Poivre d'Ane", "Polkolbin",
+ "Pont l'Eveque", "Port Nicholson", "Port-Salut", "Postel", "Pouligny-Saint-Pierre",
+ "Pourly", "Prastost", "Pressato", "Prince-Jean", "Processed Cheddar", "Provolone",
+ "Provolone (Australian)", "Pyengana Cheddar", "Pyramide", "Quark",
+ "Quark (Australian)", "Quartirolo Lombardo", "Quatre-Vents", "Quercy Petit",
+ "Queso Blanco", "Queso Blanco con Frutas --Pina y Mango", "Queso de Murcia",
+ "Queso del Montsec", "Queso del Tietar", "Queso Fresco", "Queso Fresco (Adobera)",
+ "Queso Iberico", "Queso Jalapeno", "Queso Majorero", "Queso Media Luna",
+ "Queso Para Frier", "Queso Quesadilla", "Rabacal", "Raclette", "Ragusano", "Raschera",
+ "Reblochon", "Red Leicester", "Regal de la Dombes", "Reggianito", "Remedou",
+ "Requeson", "Richelieu", "Ricotta", "Ricotta (Australian)", "Ricotta Salata", "Ridder",
+ "Rigotte", "Rocamadour", "Rollot", "Romano", "Romans Part Dieu", "Roncal", "Roquefort",
+ "Roule", "Rouleau De Beaulieu", "Royalp Tilsit", "Rubens", "Rustinu", "Saaland Pfarr",
+ "Saanenkaese", "Saga", "Sage Derby", "Sainte Maure", "Saint-Marcellin",
+ "Saint-Nectaire", "Saint-Paulin", "Salers", "Samso", "San Simon", "Sancerre",
+ "Sap Sago", "Sardo", "Sardo Egyptian", "Sbrinz", "Scamorza", "Schabzieger", "Schloss",
+ "Selles sur Cher", "Selva", "Serat", "Seriously Strong Cheddar", "Serra da Estrela",
+ "Sharpam", "Shelburne Cheddar", "Shropshire Blue", "Siraz", "Sirene", "Smoked Gouda",
+ "Somerset Brie", "Sonoma Jack", "Sottocenare al Tartufo", "Soumaintrain",
+ "Sourire Lozerien", "Spenwood", "Sraffordshire Organic", "St. Agur Blue Cheese",
+ "Stilton", "Stinking Bishop", "String", "Sussex Slipcote", "Sveciaost", "Swaledale",
+ "Sweet Style Swiss", "Swiss", "Syrian (Armenian String)", "Tala", "Taleggio", "Tamie",
+ "Tasmania Highland Chevre Log", "Taupiniere", "Teifi", "Telemea", "Testouri",
+ "Tete de Moine", "Tetilla", "Texas Goat Cheese", "Tibet", "Tillamook Cheddar",
+ "Tilsit", "Timboon Brie", "Toma", "Tomme Brulee", "Tomme d'Abondance",
+ "Tomme de Chevre", "Tomme de Romans", "Tomme de Savoie", "Tomme des Chouans", "Tommes",
+ "Torta del Casar", "Toscanello", "Touree de L'Aubier", "Tourmalet",
+ "Trappe (Veritable)", "Trois Cornes De Vendee", "Tronchon", "Trou du Cru", "Truffe",
+ "Tupi", "Turunmaa", "Tymsboro", "Tyn Grug", "Tyning", "Ubriaco", "Ulloa",
+ "Vacherin-Fribourgeois", "Valencay", "Vasterbottenost", "Venaco", "Vendomois",
+ "Vieux Corse", "Vignotte", "Vulscombe", "Waimata Farmhouse Blue",
+ "Washed Rind Cheese (Australian)", "Waterloo", "Weichkaese", "Wellington",
+ "Wensleydale", "White Stilton", "Whitestone Farmhouse", "Wigmore", "Woodside Cabecou",
+ "Xanadu", "Xynotyro", "Yarg Cornish", "Yarra Valley Pyramid", "Yorkshire Blue",
+ "Zamorano", "Zanetti Grana Padano", "Zanetti Parmigiano Reggiano"
+ };
+
+ public static ArrayList<String> asList() {
+ ArrayList<String> items = new ArrayList<String>();
+ for (int i = 0, z = CHEESES.length ; i < z ; i++) {
+ items.add(CHEESES[i]);
+ }
+ return items;
+ }
+
+ /**
+ * Return a list of random cheeses.
+ *
+ * @param count the amount of cheeses to return.
+ */
+ public static ArrayList<String> randomList(int count) {
+ Random random = new Random();
+ HashSet<String> items = new HashSet<String>();
+
+ // Make sure that don't infinity loop
+ count = Math.min(count, CHEESES.length);
+
+ while (items.size() < count) {
+ items.add(CHEESES[random.nextInt(CHEESES.length)]);
+ }
+
+ return new ArrayList<String>(items);
+ }
+}
diff --git a/samples/browseable/SwipeRefreshListFragment/src/com.example.android.common/logger/Log.java b/samples/browseable/SwipeRefreshListFragment/src/com.example.android.common/logger/Log.java
new file mode 100644
index 0000000..17503c5
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/src/com.example.android.common/logger/Log.java
@@ -0,0 +1,236 @@
+/*
+ * 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.logger;
+
+/**
+ * Helper class for a list (or tree) of LoggerNodes.
+ *
+ * <p>When this is set as the head of the list,
+ * an instance of it can function as a drop-in replacement for {@link android.util.Log}.
+ * Most of the methods in this class server only to map a method call in Log to its equivalent
+ * in LogNode.</p>
+ */
+public class Log {
+ // Grabbing the native values from Android's native logging facilities,
+ // to make for easy migration and interop.
+ public static final int NONE = -1;
+ public static final int VERBOSE = android.util.Log.VERBOSE;
+ public static final int DEBUG = android.util.Log.DEBUG;
+ public static final int INFO = android.util.Log.INFO;
+ public static final int WARN = android.util.Log.WARN;
+ public static final int ERROR = android.util.Log.ERROR;
+ public static final int ASSERT = android.util.Log.ASSERT;
+
+ // Stores the beginning of the LogNode topology.
+ private static LogNode mLogNode;
+
+ /**
+ * Returns the next LogNode in the linked list.
+ */
+ public static LogNode getLogNode() {
+ return mLogNode;
+ }
+
+ /**
+ * Sets the LogNode data will be sent to.
+ */
+ public static void setLogNode(LogNode node) {
+ mLogNode = node;
+ }
+
+ /**
+ * Instructs the LogNode to print the log data provided. Other LogNodes can
+ * be chained to the end of the LogNode as desired.
+ *
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void println(int priority, String tag, String msg, Throwable tr) {
+ if (mLogNode != null) {
+ mLogNode.println(priority, tag, msg, tr);
+ }
+ }
+
+ /**
+ * Instructs the LogNode to print the log data provided. Other LogNodes can
+ * be chained to the end of the LogNode as desired.
+ *
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ */
+ public static void println(int priority, String tag, String msg) {
+ println(priority, tag, msg, null);
+ }
+
+ /**
+ * Prints a message at VERBOSE priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void v(String tag, String msg, Throwable tr) {
+ println(VERBOSE, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at VERBOSE priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void v(String tag, String msg) {
+ v(tag, msg, null);
+ }
+
+
+ /**
+ * Prints a message at DEBUG priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void d(String tag, String msg, Throwable tr) {
+ println(DEBUG, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at DEBUG priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void d(String tag, String msg) {
+ d(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at INFO priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void i(String tag, String msg, Throwable tr) {
+ println(INFO, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at INFO priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void i(String tag, String msg) {
+ i(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at WARN priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void w(String tag, String msg, Throwable tr) {
+ println(WARN, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at WARN priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void w(String tag, String msg) {
+ w(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at WARN priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void w(String tag, Throwable tr) {
+ w(tag, null, tr);
+ }
+
+ /**
+ * Prints a message at ERROR priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void e(String tag, String msg, Throwable tr) {
+ println(ERROR, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at ERROR priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void e(String tag, String msg) {
+ e(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at ASSERT priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void wtf(String tag, String msg, Throwable tr) {
+ println(ASSERT, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at ASSERT priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void wtf(String tag, String msg) {
+ wtf(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at ASSERT priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void wtf(String tag, Throwable tr) {
+ wtf(tag, null, tr);
+ }
+}
diff --git a/samples/browseable/SwipeRefreshListFragment/src/com.example.android.common/logger/LogFragment.java b/samples/browseable/SwipeRefreshListFragment/src/com.example.android.common/logger/LogFragment.java
new file mode 100644
index 0000000..b302acd
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/src/com.example.android.common/logger/LogFragment.java
@@ -0,0 +1,109 @@
+/*
+* 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 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.logger;
+
+import android.graphics.Typeface;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ScrollView;
+
+/**
+ * Simple fraggment which contains a LogView and uses is to output log data it receives
+ * through the LogNode interface.
+ */
+public class LogFragment extends Fragment {
+
+ private LogView mLogView;
+ private ScrollView mScrollView;
+
+ public LogFragment() {}
+
+ public View inflateViews() {
+ mScrollView = new ScrollView(getActivity());
+ ViewGroup.LayoutParams scrollParams = new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT);
+ mScrollView.setLayoutParams(scrollParams);
+
+ mLogView = new LogView(getActivity());
+ ViewGroup.LayoutParams logParams = new ViewGroup.LayoutParams(scrollParams);
+ logParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+ mLogView.setLayoutParams(logParams);
+ mLogView.setClickable(true);
+ mLogView.setFocusable(true);
+ mLogView.setTypeface(Typeface.MONOSPACE);
+
+ // Want to set padding as 16 dips, setPadding takes pixels. Hooray math!
+ int paddingDips = 16;
+ double scale = getResources().getDisplayMetrics().density;
+ int paddingPixels = (int) ((paddingDips * (scale)) + .5);
+ mLogView.setPadding(paddingPixels, paddingPixels, paddingPixels, paddingPixels);
+ mLogView.setCompoundDrawablePadding(paddingPixels);
+
+ mLogView.setGravity(Gravity.BOTTOM);
+ mLogView.setTextAppearance(getActivity(), android.R.style.TextAppearance_Holo_Medium);
+
+ mScrollView.addView(mLogView);
+ return mScrollView;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+
+ View result = inflateViews();
+
+ mLogView.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {}
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ mScrollView.fullScroll(ScrollView.FOCUS_DOWN);
+ }
+ });
+ return result;
+ }
+
+ public LogView getLogView() {
+ return mLogView;
+ }
+}
\ No newline at end of file
diff --git a/samples/browseable/SwipeRefreshListFragment/src/com.example.android.common/logger/LogNode.java b/samples/browseable/SwipeRefreshListFragment/src/com.example.android.common/logger/LogNode.java
new file mode 100644
index 0000000..bc37cab
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/src/com.example.android.common/logger/LogNode.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012 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.logger;
+
+/**
+ * Basic interface for a logging system that can output to one or more targets.
+ * Note that in addition to classes that will output these logs in some format,
+ * one can also implement this interface over a filter and insert that in the chain,
+ * such that no targets further down see certain data, or see manipulated forms of the data.
+ * You could, for instance, write a "ToHtmlLoggerNode" that just converted all the log data
+ * it received to HTML and sent it along to the next node in the chain, without printing it
+ * anywhere.
+ */
+public interface LogNode {
+
+ /**
+ * Instructs first LogNode in the list to print the log data provided.
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public void println(int priority, String tag, String msg, Throwable tr);
+
+}
diff --git a/samples/browseable/SwipeRefreshListFragment/src/com.example.android.common/logger/LogView.java b/samples/browseable/SwipeRefreshListFragment/src/com.example.android.common/logger/LogView.java
new file mode 100644
index 0000000..c01542b
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/src/com.example.android.common/logger/LogView.java
@@ -0,0 +1,145 @@
+/*
+ * 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.logger;
+
+import android.app.Activity;
+import android.content.Context;
+import android.util.*;
+import android.widget.TextView;
+
+/** Simple TextView which is used to output log data received through the LogNode interface.
+*/
+public class LogView extends TextView implements LogNode {
+
+ public LogView(Context context) {
+ super(context);
+ }
+
+ public LogView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public LogView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ /**
+ * Formats the log data and prints it out to the LogView.
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ @Override
+ public void println(int priority, String tag, String msg, Throwable tr) {
+
+
+ String priorityStr = null;
+
+ // For the purposes of this View, we want to print the priority as readable text.
+ switch(priority) {
+ case android.util.Log.VERBOSE:
+ priorityStr = "VERBOSE";
+ break;
+ case android.util.Log.DEBUG:
+ priorityStr = "DEBUG";
+ break;
+ case android.util.Log.INFO:
+ priorityStr = "INFO";
+ break;
+ case android.util.Log.WARN:
+ priorityStr = "WARN";
+ break;
+ case android.util.Log.ERROR:
+ priorityStr = "ERROR";
+ break;
+ case android.util.Log.ASSERT:
+ priorityStr = "ASSERT";
+ break;
+ default:
+ break;
+ }
+
+ // Handily, the Log class has a facility for converting a stack trace into a usable string.
+ String exceptionStr = null;
+ if (tr != null) {
+ exceptionStr = android.util.Log.getStackTraceString(tr);
+ }
+
+ // Take the priority, tag, message, and exception, and concatenate as necessary
+ // into one usable line of text.
+ final StringBuilder outputBuilder = new StringBuilder();
+
+ String delimiter = "\t";
+ appendIfNotNull(outputBuilder, priorityStr, delimiter);
+ appendIfNotNull(outputBuilder, tag, delimiter);
+ appendIfNotNull(outputBuilder, msg, delimiter);
+ appendIfNotNull(outputBuilder, exceptionStr, delimiter);
+
+ // In case this was originally called from an AsyncTask or some other off-UI thread,
+ // make sure the update occurs within the UI thread.
+ ((Activity) getContext()).runOnUiThread( (new Thread(new Runnable() {
+ @Override
+ public void run() {
+ // Display the text we just generated within the LogView.
+ appendToLog(outputBuilder.toString());
+ }
+ })));
+
+ if (mNext != null) {
+ mNext.println(priority, tag, msg, tr);
+ }
+ }
+
+ public LogNode getNext() {
+ return mNext;
+ }
+
+ public void setNext(LogNode node) {
+ mNext = node;
+ }
+
+ /** Takes a string and adds to it, with a separator, if the bit to be added isn't null. Since
+ * the logger takes so many arguments that might be null, this method helps cut out some of the
+ * agonizing tedium of writing the same 3 lines over and over.
+ * @param source StringBuilder containing the text to append to.
+ * @param addStr The String to append
+ * @param delimiter The String to separate the source and appended strings. A tab or comma,
+ * for instance.
+ * @return The fully concatenated String as a StringBuilder
+ */
+ private StringBuilder appendIfNotNull(StringBuilder source, String addStr, String delimiter) {
+ if (addStr != null) {
+ if (addStr.length() == 0) {
+ delimiter = "";
+ }
+
+ return source.append(addStr).append(delimiter);
+ }
+ return source;
+ }
+
+ // The next LogNode in the chain.
+ LogNode mNext;
+
+ /** Outputs the string as a new line of log data in the LogView. */
+ public void appendToLog(String s) {
+ append("\n" + s);
+ }
+
+
+}
diff --git a/samples/browseable/SwipeRefreshListFragment/src/com.example.android.common/logger/LogWrapper.java b/samples/browseable/SwipeRefreshListFragment/src/com.example.android.common/logger/LogWrapper.java
new file mode 100644
index 0000000..16a9e7b
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/src/com.example.android.common/logger/LogWrapper.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2012 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.logger;
+
+import android.util.Log;
+
+/**
+ * Helper class which wraps Android's native Log utility in the Logger interface. This way
+ * normal DDMS output can be one of the many targets receiving and outputting logs simultaneously.
+ */
+public class LogWrapper implements LogNode {
+
+ // For piping: The next node to receive Log data after this one has done its work.
+ private LogNode mNext;
+
+ /**
+ * Returns the next LogNode in the linked list.
+ */
+ public LogNode getNext() {
+ return mNext;
+ }
+
+ /**
+ * Sets the LogNode data will be sent to..
+ */
+ public void setNext(LogNode node) {
+ mNext = node;
+ }
+
+ /**
+ * Prints data out to the console using Android's native log mechanism.
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ @Override
+ public void println(int priority, String tag, String msg, Throwable tr) {
+ // There actually are log methods that don't take a msg parameter. For now,
+ // if that's the case, just convert null to the empty string and move on.
+ String useMsg = msg;
+ if (useMsg == null) {
+ useMsg = "";
+ }
+
+ // If an exeption was provided, convert that exception to a usable string and attach
+ // it to the end of the msg method.
+ if (tr != null) {
+ msg += "\n" + Log.getStackTraceString(tr);
+ }
+
+ // This is functionally identical to Log.x(tag, useMsg);
+ // For instance, if priority were Log.VERBOSE, this would be the same as Log.v(tag, useMsg)
+ Log.println(priority, tag, useMsg);
+
+ // If this isn't the last node in the chain, move things along.
+ if (mNext != null) {
+ mNext.println(priority, tag, msg, tr);
+ }
+ }
+}
diff --git a/samples/browseable/SwipeRefreshListFragment/src/com.example.android.common/logger/MessageOnlyLogFilter.java b/samples/browseable/SwipeRefreshListFragment/src/com.example.android.common/logger/MessageOnlyLogFilter.java
new file mode 100644
index 0000000..19967dc
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/src/com.example.android.common/logger/MessageOnlyLogFilter.java
@@ -0,0 +1,60 @@
+/*
+ * 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.logger;
+
+/**
+ * Simple {@link LogNode} filter, removes everything except the message.
+ * Useful for situations like on-screen log output where you don't want a lot of metadata displayed,
+ * just easy-to-read message updates as they're happening.
+ */
+public class MessageOnlyLogFilter implements LogNode {
+
+ LogNode mNext;
+
+ /**
+ * Takes the "next" LogNode as a parameter, to simplify chaining.
+ *
+ * @param next The next LogNode in the pipeline.
+ */
+ public MessageOnlyLogFilter(LogNode next) {
+ mNext = next;
+ }
+
+ public MessageOnlyLogFilter() {
+ }
+
+ @Override
+ public void println(int priority, String tag, String msg, Throwable tr) {
+ if (mNext != null) {
+ getNext().println(Log.NONE, null, msg, null);
+ }
+ }
+
+ /**
+ * Returns the next LogNode in the chain.
+ */
+ public LogNode getNext() {
+ return mNext;
+ }
+
+ /**
+ * Sets the LogNode data will be sent to..
+ */
+ public void setNext(LogNode node) {
+ mNext = node;
+ }
+
+}
diff --git a/samples/browseable/SwipeRefreshListFragment/src/com.example.android.common/view/SlidingTabLayout.java b/samples/browseable/SwipeRefreshListFragment/src/com.example.android.common/view/SlidingTabLayout.java
new file mode 100644
index 0000000..20049e3
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/src/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/samples/browseable/SwipeRefreshListFragment/src/com.example.android.common/view/SlidingTabStrip.java b/samples/browseable/SwipeRefreshListFragment/src/com.example.android.common/view/SlidingTabStrip.java
new file mode 100644
index 0000000..d5bbbae
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/src/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/samples/browseable/SwipeRefreshListFragment/src/com.example.android.swiperefreshlistfragment/MainActivity.java b/samples/browseable/SwipeRefreshListFragment/src/com.example.android.swiperefreshlistfragment/MainActivity.java
new file mode 100644
index 0000000..7f7a7c8
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/src/com.example.android.swiperefreshlistfragment/MainActivity.java
@@ -0,0 +1,110 @@
+/*
+* 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.
+*/
+
+
+
+
+package com.example.android.swiperefreshlistfragment;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentTransaction;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.ViewAnimator;
+
+import com.example.android.common.activities.SampleActivityBase;
+import com.example.android.common.logger.Log;
+import com.example.android.common.logger.LogFragment;
+import com.example.android.common.logger.LogWrapper;
+import com.example.android.common.logger.MessageOnlyLogFilter;
+
+/**
+ * A simple launcher activity containing a summary sample description, sample log and a custom
+ * {@link android.support.v4.app.Fragment} which can display a view.
+ * <p>
+ * For devices with displays with a width of 720dp or greater, the sample log is always visible,
+ * on other devices it's visibility is controlled by an item on the Action Bar.
+ */
+public class MainActivity extends SampleActivityBase {
+
+ public static final String TAG = "MainActivity";
+
+ // Whether the Log Fragment is currently shown
+ private boolean mLogShown;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+ SwipeRefreshListFragmentFragment fragment = new SwipeRefreshListFragmentFragment();
+ transaction.replace(R.id.sample_content_fragment, fragment);
+ transaction.commit();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.main, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ MenuItem logToggle = menu.findItem(R.id.menu_toggle_log);
+ logToggle.setVisible(findViewById(R.id.sample_output) instanceof ViewAnimator);
+ logToggle.setTitle(mLogShown ? R.string.sample_hide_log : R.string.sample_show_log);
+
+ return super.onPrepareOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch(item.getItemId()) {
+ case R.id.menu_toggle_log:
+ mLogShown = !mLogShown;
+ ViewAnimator output = (ViewAnimator) findViewById(R.id.sample_output);
+ if (mLogShown) {
+ output.setDisplayedChild(1);
+ } else {
+ output.setDisplayedChild(0);
+ }
+ supportInvalidateOptionsMenu();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ /** Create a chain of targets that will receive log data */
+ @Override
+ public void initializeLogging() {
+ // Wraps Android's native log framework.
+ LogWrapper logWrapper = new LogWrapper();
+ // Using Log, front-end to the logging chain, emulates android.util.log method signatures.
+ Log.setLogNode(logWrapper);
+
+ // Filter strips out everything except the message text.
+ MessageOnlyLogFilter msgFilter = new MessageOnlyLogFilter();
+ logWrapper.setNext(msgFilter);
+
+ // On screen logging via a fragment with a TextView.
+ LogFragment logFragment = (LogFragment) getSupportFragmentManager()
+ .findFragmentById(R.id.log_fragment);
+ msgFilter.setNext(logFragment.getLogView());
+
+ Log.i(TAG, "Ready");
+ }
+}
diff --git a/samples/browseable/SwipeRefreshListFragment/src/com.example.android.swiperefreshlistfragment/SwipeRefreshListFragment.java b/samples/browseable/SwipeRefreshListFragment/src/com.example.android.swiperefreshlistfragment/SwipeRefreshListFragment.java
new file mode 100644
index 0000000..5796976
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/src/com.example.android.swiperefreshlistfragment/SwipeRefreshListFragment.java
@@ -0,0 +1,166 @@
+/*
+ * 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.swiperefreshlistfragment;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v4.app.ListFragment;
+import android.support.v4.view.ViewCompat;
+import android.support.v4.widget.SwipeRefreshLayout;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ListView;
+
+/**
+ * Subclass of {@link android.support.v4.app.ListFragment} which provides automatic support for
+ * providing the 'swipe-to-refresh' UX gesture by wrapping the the content view in a
+ * {@link android.support.v4.widget.SwipeRefreshLayout}.
+ */
+public class SwipeRefreshListFragment extends ListFragment {
+
+ private SwipeRefreshLayout mSwipeRefreshLayout;
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+
+ // Create the list fragment's content view by calling the super method
+ final View listFragmentView = super.onCreateView(inflater, container, savedInstanceState);
+
+ // Now create a SwipeRefreshLayout to wrap the fragment's content view
+ mSwipeRefreshLayout = new ListFragmentSwipeRefreshLayout(container.getContext());
+
+ // Add the list fragment's content view to the SwipeRefreshLayout, making sure that it fills
+ // the SwipeRefreshLayout
+ mSwipeRefreshLayout.addView(listFragmentView,
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+
+ // Make sure that the SwipeRefreshLayout will fill the fragment
+ mSwipeRefreshLayout.setLayoutParams(
+ new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT));
+
+ // Now return the SwipeRefreshLayout as this fragment's content view
+ return mSwipeRefreshLayout;
+ }
+
+ /**
+ * Set the {@link android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener} to listen for
+ * initiated refreshes.
+ *
+ * @see android.support.v4.widget.SwipeRefreshLayout#setOnRefreshListener(android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener)
+ */
+ public void setOnRefreshListener(SwipeRefreshLayout.OnRefreshListener listener) {
+ mSwipeRefreshLayout.setOnRefreshListener(listener);
+ }
+
+ /**
+ * Returns whether the {@link android.support.v4.widget.SwipeRefreshLayout} is currently
+ * refreshing or not.
+ *
+ * @see android.support.v4.widget.SwipeRefreshLayout#isRefreshing()
+ */
+ public boolean isRefreshing() {
+ return mSwipeRefreshLayout.isRefreshing();
+ }
+
+ /**
+ * Set whether the {@link android.support.v4.widget.SwipeRefreshLayout} should be displaying
+ * that it is refreshing or not.
+ *
+ * @see android.support.v4.widget.SwipeRefreshLayout#setRefreshing(boolean)
+ */
+ public void setRefreshing(boolean refreshing) {
+ mSwipeRefreshLayout.setRefreshing(refreshing);
+ }
+
+ /**
+ * Set the color scheme for the {@link android.support.v4.widget.SwipeRefreshLayout}.
+ *
+ * @see android.support.v4.widget.SwipeRefreshLayout#setColorScheme(int, int, int, int)
+ */
+ public void setColorScheme(int colorRes1, int colorRes2, int colorRes3, int colorRes4) {
+ mSwipeRefreshLayout.setColorScheme(colorRes1, colorRes2, colorRes3, colorRes4);
+ }
+
+ /**
+ * @return the fragment's {@link android.support.v4.widget.SwipeRefreshLayout} widget.
+ */
+ public SwipeRefreshLayout getSwipeRefreshLayout() {
+ return mSwipeRefreshLayout;
+ }
+
+ /**
+ * Sub-class of {@link android.support.v4.widget.SwipeRefreshLayout} for use in this
+ * {@link android.support.v4.app.ListFragment}. The reason that this is needed is because
+ * {@link android.support.v4.widget.SwipeRefreshLayout} only supports a single child, which it
+ * expects to be the one which triggers refreshes. In our case the layout's child is the content
+ * view returned from
+ * {@link android.support.v4.app.ListFragment#onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle)}
+ * which is a {@link android.view.ViewGroup}.
+ *
+ * <p>To enable 'swipe-to-refresh' support via the {@link android.widget.ListView} we need to
+ * override the default behavior and properly signal when a gesture is possible. This is done by
+ * overriding {@link #canChildScrollUp()}.
+ */
+ private class ListFragmentSwipeRefreshLayout extends SwipeRefreshLayout {
+
+ public ListFragmentSwipeRefreshLayout(Context context) {
+ super(context);
+ }
+
+ /**
+ * As mentioned above, we need to override this method to properly signal when a
+ * 'swipe-to-refresh' is possible.
+ *
+ * @return true if the {@link android.widget.ListView} is visible and can scroll up.
+ */
+ @Override
+ public boolean canChildScrollUp() {
+ final ListView listView = getListView();
+ if (listView.getVisibility() == View.VISIBLE) {
+ return canListViewScrollUp(listView);
+ } else {
+ return false;
+ }
+ }
+
+ }
+
+ // BEGIN_INCLUDE (check_list_can_scroll)
+ /**
+ * Utility method to check whether a {@link ListView} can scroll up from it's current position.
+ * Handles platform version differences, providing backwards compatible functionality where
+ * needed.
+ */
+ private static boolean canListViewScrollUp(ListView listView) {
+ if (android.os.Build.VERSION.SDK_INT >= 14) {
+ // For ICS and above we can call canScrollVertically() to determine this
+ return ViewCompat.canScrollVertically(listView, -1);
+ } else {
+ // Pre-ICS we need to manually check the first visible item and the child view's top
+ // value
+ return listView.getChildCount() > 0 &&
+ (listView.getFirstVisiblePosition() > 0
+ || listView.getChildAt(0).getTop() < listView.getPaddingTop());
+ }
+ }
+ // END_INCLUDE (check_list_can_scroll)
+
+}
diff --git a/samples/browseable/SwipeRefreshListFragment/src/com.example.android.swiperefreshlistfragment/SwipeRefreshListFragmentFragment.java b/samples/browseable/SwipeRefreshListFragment/src/com.example.android.swiperefreshlistfragment/SwipeRefreshListFragmentFragment.java
new file mode 100644
index 0000000..1147ea8
--- /dev/null
+++ b/samples/browseable/SwipeRefreshListFragment/src/com.example.android.swiperefreshlistfragment/SwipeRefreshListFragmentFragment.java
@@ -0,0 +1,232 @@
+/*
+ * 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.swiperefreshlistfragment;
+
+import com.example.android.common.dummydata.Cheeses;
+import com.example.android.common.logger.Log;
+
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.support.v4.widget.SwipeRefreshLayout;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.ArrayAdapter;
+import android.widget.ListAdapter;
+
+import java.util.List;
+
+/**
+ * A sample which shows how to use {@link android.support.v4.widget.SwipeRefreshLayout} within a
+ * {@link android.support.v4.app.ListFragment} to add the 'swipe-to-refresh' gesture to a
+ * {@link android.widget.ListView}. This is provided through the provided re-usable
+ * {@link SwipeRefreshListFragment} class.
+ *
+ * <p>To provide an accessible way to trigger the refresh, this app also provides a refresh
+ * action item. This item should be displayed in the Action Bar's overflow item.
+ *
+ * <p>In this sample app, the refresh updates the ListView with a random set of new items.
+ *
+ * <p>This sample also provides the functionality to change the colors displayed in the
+ * {@link android.support.v4.widget.SwipeRefreshLayout} through the options menu. This is meant to
+ * showcase the use of color rather than being something that should be integrated into apps.
+ */
+public class SwipeRefreshListFragmentFragment extends SwipeRefreshListFragment {
+
+ private static final String LOG_TAG = SwipeRefreshListFragmentFragment.class.getSimpleName();
+
+ private static final int LIST_ITEM_COUNT = 20;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Notify the system to allow an options menu for this fragment.
+ setHasOptionsMenu(true);
+ }
+
+ // BEGIN_INCLUDE (setup_views)
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+
+ /**
+ * Create an ArrayAdapter to contain the data for the ListView. Each item in the ListView
+ * uses the system-defined simple_list_item_1 layout that contains one TextView.
+ */
+ ListAdapter adapter = new ArrayAdapter<String>(
+ getActivity(),
+ android.R.layout.simple_list_item_1,
+ android.R.id.text1,
+ Cheeses.randomList(LIST_ITEM_COUNT));
+
+ // Set the adapter between the ListView and its backing data.
+ setListAdapter(adapter);
+
+ // BEGIN_INCLUDE (setup_refreshlistener)
+ /**
+ * Implement {@link SwipeRefreshLayout.OnRefreshListener}. When users do the "swipe to
+ * refresh" gesture, SwipeRefreshLayout invokes
+ * {@link SwipeRefreshLayout.OnRefreshListener#onRefresh onRefresh()}. In
+ * {@link SwipeRefreshLayout.OnRefreshListener#onRefresh onRefresh()}, call a method that
+ * refreshes the content. Call the same method in response to the Refresh action from the
+ * action bar.
+ */
+ setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
+ @Override
+ public void onRefresh() {
+ Log.i(LOG_TAG, "onRefresh called from SwipeRefreshLayout");
+
+ initiateRefresh();
+ }
+ });
+ // END_INCLUDE (setup_refreshlistener)
+ }
+ // END_INCLUDE (setup_views)
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ inflater.inflate(R.menu.main_menu, menu);
+ }
+
+ // BEGIN_INCLUDE (setup_refresh_menu_listener)
+ /**
+ * Respond to the user's selection of the Refresh action item. Start the SwipeRefreshLayout
+ * progress bar, then initiate the background task that refreshes the content.
+ *
+ * <p>A color scheme menu item used for demonstrating the use of SwipeRefreshLayout's color
+ * scheme functionality. This kind of menu item should not be incorporated into your app,
+ * it just to demonstrate the use of color. Instead you should choose a color scheme based
+ * off of your application's branding.
+ */
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.menu_refresh:
+ Log.i(LOG_TAG, "Refresh menu item selected");
+
+ // We make sure that the SwipeRefreshLayout is displaying it's refreshing indicator
+ if (!isRefreshing()) {
+ setRefreshing(true);
+ }
+
+ // Start our refresh background task
+ initiateRefresh();
+ return true;
+
+ case R.id.menu_color_scheme_1:
+ Log.i(LOG_TAG, "setColorScheme #1");
+ item.setChecked(true);
+
+ // Change the colors displayed by the SwipeRefreshLayout by providing it with 4
+ // color resource ids
+ setColorScheme(R.color.color_scheme_1_1, R.color.color_scheme_1_2,
+ R.color.color_scheme_1_3, R.color.color_scheme_1_4);
+ return true;
+
+ case R.id.menu_color_scheme_2:
+ Log.i(LOG_TAG, "setColorScheme #2");
+ item.setChecked(true);
+
+ // Change the colors displayed by the SwipeRefreshLayout by providing it with 4
+ // color resource ids
+ setColorScheme(R.color.color_scheme_2_1, R.color.color_scheme_2_2,
+ R.color.color_scheme_2_3, R.color.color_scheme_2_4);
+ return true;
+
+ case R.id.menu_color_scheme_3:
+ Log.i(LOG_TAG, "setColorScheme #3");
+ item.setChecked(true);
+
+ // Change the colors displayed by the SwipeRefreshLayout by providing it with 4
+ // color resource ids
+ setColorScheme(R.color.color_scheme_3_1, R.color.color_scheme_3_2,
+ R.color.color_scheme_3_3, R.color.color_scheme_3_4);
+ return true;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+ // END_INCLUDE (setup_refresh_menu_listener)
+
+ // BEGIN_INCLUDE (initiate_refresh)
+ /**
+ * By abstracting the refresh process to a single method, the app allows both the
+ * SwipeGestureLayout onRefresh() method and the Refresh action item to refresh the content.
+ */
+ private void initiateRefresh() {
+ Log.i(LOG_TAG, "initiateRefresh");
+
+ /**
+ * Execute the background task, which uses {@link android.os.AsyncTask} to load the data.
+ */
+ new DummyBackgroundTask().execute();
+ }
+ // END_INCLUDE (initiate_refresh)
+
+ // BEGIN_INCLUDE (refresh_complete)
+ /**
+ * When the AsyncTask finishes, it calls onRefreshComplete(), which updates the data in the
+ * ListAdapter and turns off the progress bar.
+ */
+ private void onRefreshComplete(List<String> result) {
+ Log.i(LOG_TAG, "onRefreshComplete");
+
+ // Remove all items from the ListAdapter, and then replace them with the new items
+ ArrayAdapter<String> adapter = (ArrayAdapter<String>) getListAdapter();
+ adapter.clear();
+ for (String cheese : result) {
+ adapter.add(cheese);
+ }
+
+ // Stop the refreshing indicator
+ setRefreshing(false);
+ }
+ // END_INCLUDE (refresh_complete)
+
+ /**
+ * Dummy {@link AsyncTask} which simulates a long running task to fetch new cheeses.
+ */
+ private class DummyBackgroundTask extends AsyncTask<Void, Void, List<String>> {
+
+ static final int TASK_DURATION = 3 * 1000; // 3 seconds
+
+ @Override
+ protected List<String> doInBackground(Void... params) {
+ // Sleep for a small amount of time to simulate a background-task
+ try {
+ Thread.sleep(TASK_DURATION);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ // Return a new random list of cheeses
+ return Cheeses.randomList(LIST_ITEM_COUNT);
+ }
+
+ @Override
+ protected void onPostExecute(List<String> result) {
+ super.onPostExecute(result);
+
+ // Tell the Fragment that the refresh has completed
+ onRefreshComplete(result);
+ }
+
+ }
+
+}
diff --git a/samples/browseable/SwipeRefreshMultipleViews/AndroidManifest.xml b/samples/browseable/SwipeRefreshMultipleViews/AndroidManifest.xml
new file mode 100644
index 0000000..aba15e0
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/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.swiperefreshmultipleviews"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <uses-sdk android:minSdkVersion="10" 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/samples/browseable/SwipeRefreshMultipleViews/_index.jd b/samples/browseable/SwipeRefreshMultipleViews/_index.jd
new file mode 100644
index 0000000..70ff8ea
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/_index.jd
@@ -0,0 +1,12 @@
+
+
+
+page.tags="SwipeRefreshMultipleViews"
+sample.group=UI
+@jd:body
+
+<p>This sample demonstrates how to use {@link android.support.v4.widget.SwipeRefreshLayout} to add
+the <em>swipe-to-refresh</em> gesture to a layout with multiple children, which enables you to
+trigger a refresh by swiping down on the view. In this sample
+{@link android.support.v4.widget.SwipeRefreshLayout} contains a scrollable
+{@link android.widget.GridView} with an empty {@link android.widget.TextView}.</p>
diff --git a/samples/browseable/SwipeRefreshMultipleViews/res/drawable-hdpi/ic_launcher.png b/samples/browseable/SwipeRefreshMultipleViews/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..9fbf7ab
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/SwipeRefreshMultipleViews/res/drawable-hdpi/tile.9.png b/samples/browseable/SwipeRefreshMultipleViews/res/drawable-hdpi/tile.9.png
new file mode 100644
index 0000000..1358628
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/res/drawable-hdpi/tile.9.png
Binary files differ
diff --git a/samples/browseable/SwipeRefreshMultipleViews/res/drawable-mdpi/ic_launcher.png b/samples/browseable/SwipeRefreshMultipleViews/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..f834108
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/SwipeRefreshMultipleViews/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/SwipeRefreshMultipleViews/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..3197133
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/SwipeRefreshMultipleViews/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/SwipeRefreshMultipleViews/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..d19455c
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/SwipeRefreshMultipleViews/res/layout-w720dp/activity_main.xml b/samples/browseable/SwipeRefreshMultipleViews/res/layout-w720dp/activity_main.xml
new file mode 100755
index 0000000..c9a52f6
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/res/layout-w720dp/activity_main.xml
@@ -0,0 +1,73 @@
+<!--
+ 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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/sample_main_layout">
+
+ <LinearLayout
+ android:id="@+id/sample_output"
+ android:layout_width="0px"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:orientation="vertical">
+
+ <FrameLayout
+ style="@style/Widget.SampleMessageTile"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ style="@style/Widget.SampleMessage"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="@dimen/margin_medium"
+ android:paddingRight="@dimen/margin_medium"
+ android:paddingTop="@dimen/margin_large"
+ android:paddingBottom="@dimen/margin_large"
+ android:text="@string/intro_message" />
+ </FrameLayout>
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:background="@android:color/darker_gray" />
+
+ <fragment
+ android:name="com.example.android.common.logger.LogFragment"
+ android:id="@+id/log_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="0px"
+ android:layout_weight="1" />
+
+ </LinearLayout>
+
+ <View
+ android:layout_width="1dp"
+ android:layout_height="match_parent"
+ android:background="@android:color/darker_gray" />
+
+ <FrameLayout
+ android:id="@+id/sample_content_fragment"
+ android:layout_weight="2"
+ android:layout_width="0px"
+ android:layout_height="match_parent" />
+
+</LinearLayout>
+
+
diff --git a/samples/browseable/SwipeRefreshMultipleViews/res/layout/activity_main.xml b/samples/browseable/SwipeRefreshMultipleViews/res/layout/activity_main.xml
new file mode 100755
index 0000000..1ae4f98
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/res/layout/activity_main.xml
@@ -0,0 +1,65 @@
+<!--
+ 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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/sample_main_layout">
+
+ <ViewAnimator
+ android:id="@+id/sample_output"
+ android:layout_width="match_parent"
+ android:layout_height="0px"
+ android:layout_weight="1">
+
+ <ScrollView
+ style="@style/Widget.SampleMessageTile"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <TextView
+ style="@style/Widget.SampleMessage"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="@dimen/horizontal_page_margin"
+ android:paddingRight="@dimen/horizontal_page_margin"
+ android:paddingTop="@dimen/vertical_page_margin"
+ android:paddingBottom="@dimen/vertical_page_margin"
+ android:text="@string/intro_message" />
+ </ScrollView>
+
+ <fragment
+ android:name="com.example.android.common.logger.LogFragment"
+ android:id="@+id/log_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ </ViewAnimator>
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:background="@android:color/darker_gray" />
+
+ <FrameLayout
+ android:id="@+id/sample_content_fragment"
+ android:layout_weight="2"
+ android:layout_width="match_parent"
+ android:layout_height="0px" />
+
+</LinearLayout>
+
diff --git a/samples/browseable/SwipeRefreshMultipleViews/res/layout/fragment_sample.xml b/samples/browseable/SwipeRefreshMultipleViews/res/layout/fragment_sample.xml
new file mode 100644
index 0000000..077f3f1
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/res/layout/fragment_sample.xml
@@ -0,0 +1,43 @@
+<?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.
+-->
+
+<com.example.android.swiperefreshmultipleviews.MultiSwipeRefreshLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/swiperefresh"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <GridView
+ android:id="@android:id/list"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:numColumns="2" />
+
+ <TextView
+ android:id="@android:id/empty"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/empty_text"
+ android:layout_gravity="center"/>
+
+ </FrameLayout>
+
+</com.example.android.swiperefreshmultipleviews.MultiSwipeRefreshLayout>
\ No newline at end of file
diff --git a/samples/browseable/SwipeRefreshMultipleViews/res/menu/main.xml b/samples/browseable/SwipeRefreshMultipleViews/res/menu/main.xml
new file mode 100644
index 0000000..b49c2c5
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/res/menu/main.xml
@@ -0,0 +1,21 @@
+<!--
+ 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.
+ -->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/menu_toggle_log"
+ android:showAsAction="always"
+ android:title="@string/sample_show_log" />
+</menu>
diff --git a/samples/browseable/SwipeRefreshMultipleViews/res/menu/main_menu.xml b/samples/browseable/SwipeRefreshMultipleViews/res/menu/main_menu.xml
new file mode 100644
index 0000000..d8fa6e6
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/res/menu/main_menu.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:id="@+id/menu_clear"
+ android:title="@string/menu_clear"
+ android:showAsAction="never" />
+
+ <item
+ android:id="@+id/menu_refresh"
+ android:title="@string/menu_refresh"
+ android:showAsAction="never" />
+
+</menu>
\ No newline at end of file
diff --git a/samples/browseable/SwipeRefreshMultipleViews/res/values-sw600dp/template-dimens.xml b/samples/browseable/SwipeRefreshMultipleViews/res/values-sw600dp/template-dimens.xml
new file mode 100644
index 0000000..22074a2
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/res/values-sw600dp/template-dimens.xml
@@ -0,0 +1,24 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Semantic definitions -->
+
+ <dimen name="horizontal_page_margin">@dimen/margin_huge</dimen>
+ <dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
+
+</resources>
diff --git a/samples/browseable/SwipeRefreshMultipleViews/res/values-sw600dp/template-styles.xml b/samples/browseable/SwipeRefreshMultipleViews/res/values-sw600dp/template-styles.xml
new file mode 100644
index 0000000..03d1974
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/res/values-sw600dp/template-styles.xml
@@ -0,0 +1,25 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <style name="Widget.SampleMessage">
+ <item name="android:textAppearance">?android:textAppearanceLarge</item>
+ <item name="android:lineSpacingMultiplier">1.2</item>
+ <item name="android:shadowDy">-6.5</item>
+ </style>
+
+</resources>
diff --git a/samples/browseable/SwipeRefreshMultipleViews/res/values-v11/template-styles.xml b/samples/browseable/SwipeRefreshMultipleViews/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/SwipeRefreshMultipleViews/res/values/base-strings.xml b/samples/browseable/SwipeRefreshMultipleViews/res/values/base-strings.xml
new file mode 100644
index 0000000..d7c1c9e
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/res/values/base-strings.xml
@@ -0,0 +1,34 @@
+<?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.
+-->
+
+
+
+<resources>
+ <string name="app_name">SwipeRefreshMultipleViews</string>
+ <string name="intro_message">
+ <![CDATA[
+
+
+ A sample which shows how to use SwipeRefreshLayout to add the \'swipe-to-refresh\'
+ gesture to a layout with multiple children, enabling the ability to trigger a
+ refresh from swiping down on the visible view. In this sample, SwipeRefreshLayout
+ contains a scrollable GridView, along with a TextView empty view.
+
+
+ ]]>
+ </string>
+</resources>
diff --git a/samples/browseable/SwipeRefreshMultipleViews/res/values/color.xml b/samples/browseable/SwipeRefreshMultipleViews/res/values/color.xml
new file mode 100644
index 0000000..48039b0
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/res/values/color.xml
@@ -0,0 +1,25 @@
+<?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>
+
+ <color name="swipe_color_1">#B6DB49</color>
+ <color name="swipe_color_2">#99CC00</color>
+ <color name="swipe_color_3">#8ABD00</color>
+ <color name="swipe_color_4">#7CAF00</color>
+
+</resources>
\ No newline at end of file
diff --git a/samples/browseable/SwipeRefreshMultipleViews/res/values/strings.xml b/samples/browseable/SwipeRefreshMultipleViews/res/values/strings.xml
new file mode 100755
index 0000000..7b9d9ec
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/res/values/strings.xml
@@ -0,0 +1,19 @@
+<!--
+ 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.
+-->
+<resources>
+ <string name="sample_show_log">Show Log</string>
+ <string name="sample_hide_log">Hide Log</string>
+</resources>
diff --git a/samples/browseable/SwipeRefreshMultipleViews/res/values/template-dimens.xml b/samples/browseable/SwipeRefreshMultipleViews/res/values/template-dimens.xml
new file mode 100644
index 0000000..39e710b
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/res/values/template-dimens.xml
@@ -0,0 +1,32 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Define standard dimensions to comply with Holo-style grids and rhythm. -->
+
+ <dimen name="margin_tiny">4dp</dimen>
+ <dimen name="margin_small">8dp</dimen>
+ <dimen name="margin_medium">16dp</dimen>
+ <dimen name="margin_large">32dp</dimen>
+ <dimen name="margin_huge">64dp</dimen>
+
+ <!-- Semantic definitions -->
+
+ <dimen name="horizontal_page_margin">@dimen/margin_medium</dimen>
+ <dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
+
+</resources>
diff --git a/samples/browseable/SwipeRefreshMultipleViews/res/values/template-styles.xml b/samples/browseable/SwipeRefreshMultipleViews/res/values/template-styles.xml
new file mode 100644
index 0000000..6e7d593
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/res/values/template-styles.xml
@@ -0,0 +1,42 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+
+ <style name="Theme.Base" parent="android:Theme.Light" />
+
+ <style name="Theme.Sample" parent="Theme.Base" />
+
+ <style name="AppTheme" parent="Theme.Sample" />
+ <!-- Widget styling -->
+
+ <style name="Widget" />
+
+ <style name="Widget.SampleMessage">
+ <item name="android:textAppearance">?android:textAppearanceMedium</item>
+ <item name="android:lineSpacingMultiplier">1.1</item>
+ </style>
+
+ <style name="Widget.SampleMessageTile">
+ <item name="android:background">@drawable/tile</item>
+ <item name="android:shadowColor">#7F000000</item>
+ <item name="android:shadowDy">-3.5</item>
+ <item name="android:shadowRadius">2</item>
+ </style>
+
+</resources>
diff --git a/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.common/activities/SampleActivityBase.java b/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.common/activities/SampleActivityBase.java
new file mode 100644
index 0000000..3228927
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.common/activities/SampleActivityBase.java
@@ -0,0 +1,52 @@
+/*
+* 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.
+*/
+
+package com.example.android.common.activities;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+
+import com.example.android.common.logger.Log;
+import com.example.android.common.logger.LogWrapper;
+
+/**
+ * Base launcher activity, to handle most of the common plumbing for samples.
+ */
+public class SampleActivityBase extends FragmentActivity {
+
+ public static final String TAG = "SampleActivityBase";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ initializeLogging();
+ }
+
+ /** Set up targets to receive log data */
+ public void initializeLogging() {
+ // Using Log, front-end to the logging chain, emulates android.util.log method signatures.
+ // Wraps Android's native log framework
+ LogWrapper logWrapper = new LogWrapper();
+ Log.setLogNode(logWrapper);
+
+ Log.i(TAG, "Ready");
+ }
+}
diff --git a/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.common/dummydata/Cheeses.java b/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.common/dummydata/Cheeses.java
new file mode 100644
index 0000000..783735c
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.common/dummydata/Cheeses.java
@@ -0,0 +1,186 @@
+/*
+ * 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.
+ */
+
+package com.example.android.common.dummydata;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Random;
+
+/**
+ * Dummy data.
+ */
+public class Cheeses {
+ static final String[] CHEESES = {
+ "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi",
+ "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale",
+ "Aisy Cendre", "Allgauer Emmentaler", "Alverca", "Ambert", "American Cheese",
+ "Ami du Chambertin", "Anejo Enchilado", "Anneau du Vic-Bilh", "Anthoriro", "Appenzell",
+ "Aragon", "Ardi Gasna", "Ardrahan", "Armenian String", "Aromes au Gene de Marc",
+ "Asadero", "Asiago", "Aubisque Pyrenees", "Autun", "Avaxtskyr", "Baby Swiss",
+ "Babybel", "Baguette Laonnaise", "Bakers", "Baladi", "Balaton", "Bandal", "Banon",
+ "Barry's Bay Cheddar", "Basing", "Basket Cheese", "Bath Cheese", "Bavarian Bergkase",
+ "Baylough", "Beaufort", "Beauvoorde", "Beenleigh Blue", "Beer Cheese", "Bel Paese",
+ "Bergader", "Bergere Bleue", "Berkswell", "Beyaz Peynir", "Bierkase", "Bishop Kennedy",
+ "Blarney", "Bleu d'Auvergne", "Bleu de Gex", "Bleu de Laqueuille",
+ "Bleu de Septmoncel", "Bleu Des Causses", "Blue", "Blue Castello", "Blue Rathgore",
+ "Blue Vein (Australian)", "Blue Vein Cheeses", "Bocconcini", "Bocconcini (Australian)",
+ "Boeren Leidenkaas", "Bonchester", "Bosworth", "Bougon", "Boule Du Roves",
+ "Boulette d'Avesnes", "Boursault", "Boursin", "Bouyssou", "Bra", "Braudostur",
+ "Breakfast Cheese", "Brebis du Lavort", "Brebis du Lochois", "Brebis du Puyfaucon",
+ "Bresse Bleu", "Brick", "Brie", "Brie de Meaux", "Brie de Melun", "Brillat-Savarin",
+ "Brin", "Brin d' Amour", "Brin d'Amour", "Brinza (Burduf Brinza)",
+ "Briquette de Brebis", "Briquette du Forez", "Broccio", "Broccio Demi-Affine",
+ "Brousse du Rove", "Bruder Basil", "Brusselae Kaas (Fromage de Bruxelles)", "Bryndza",
+ "Buchette d'Anjou", "Buffalo", "Burgos", "Butte", "Butterkase", "Button (Innes)",
+ "Buxton Blue", "Cabecou", "Caboc", "Cabrales", "Cachaille", "Caciocavallo", "Caciotta",
+ "Caerphilly", "Cairnsmore", "Calenzana", "Cambazola", "Camembert de Normandie",
+ "Canadian Cheddar", "Canestrato", "Cantal", "Caprice des Dieux", "Capricorn Goat",
+ "Capriole Banon", "Carre de l'Est", "Casciotta di Urbino", "Cashel Blue", "Castellano",
+ "Castelleno", "Castelmagno", "Castelo Branco", "Castigliano", "Cathelain",
+ "Celtic Promise", "Cendre d'Olivet", "Cerney", "Chabichou", "Chabichou du Poitou",
+ "Chabis de Gatine", "Chaource", "Charolais", "Chaumes", "Cheddar",
+ "Cheddar Clothbound", "Cheshire", "Chevres", "Chevrotin des Aravis", "Chontaleno",
+ "Civray", "Coeur de Camembert au Calvados", "Coeur de Chevre", "Colby", "Cold Pack",
+ "Comte", "Coolea", "Cooleney", "Coquetdale", "Corleggy", "Cornish Pepper",
+ "Cotherstone", "Cotija", "Cottage Cheese", "Cottage Cheese (Australian)",
+ "Cougar Gold", "Coulommiers", "Coverdale", "Crayeux de Roncq", "Cream Cheese",
+ "Cream Havarti", "Crema Agria", "Crema Mexicana", "Creme Fraiche", "Crescenza",
+ "Croghan", "Crottin de Chavignol", "Crottin du Chavignol", "Crowdie", "Crowley",
+ "Cuajada", "Curd", "Cure Nantais", "Curworthy", "Cwmtawe Pecorino",
+ "Cypress Grove Chevre", "Danablu (Danish Blue)", "Danbo", "Danish Fontina",
+ "Daralagjazsky", "Dauphin", "Delice des Fiouves", "Denhany Dorset Drum", "Derby",
+ "Dessertnyj Belyj", "Devon Blue", "Devon Garland", "Dolcelatte", "Doolin",
+ "Doppelrhamstufel", "Dorset Blue Vinney", "Double Gloucester", "Double Worcester",
+ "Dreux a la Feuille", "Dry Jack", "Duddleswell", "Dunbarra", "Dunlop", "Dunsyre Blue",
+ "Duroblando", "Durrus", "Dutch Mimolette (Commissiekaas)", "Edam", "Edelpilz",
+ "Emental Grand Cru", "Emlett", "Emmental", "Epoisses de Bourgogne", "Esbareich",
+ "Esrom", "Etorki", "Evansdale Farmhouse Brie", "Evora De L'Alentejo", "Exmoor Blue",
+ "Explorateur", "Feta", "Feta (Australian)", "Figue", "Filetta", "Fin-de-Siecle",
+ "Finlandia Swiss", "Finn", "Fiore Sardo", "Fleur du Maquis", "Flor de Guia",
+ "Flower Marie", "Folded", "Folded cheese with mint", "Fondant de Brebis",
+ "Fontainebleau", "Fontal", "Fontina Val d'Aosta", "Formaggio di capra", "Fougerus",
+ "Four Herb Gouda", "Fourme d' Ambert", "Fourme de Haute Loire", "Fourme de Montbrison",
+ "Fresh Jack", "Fresh Mozzarella", "Fresh Ricotta", "Fresh Truffles", "Fribourgeois",
+ "Friesekaas", "Friesian", "Friesla", "Frinault", "Fromage a Raclette", "Fromage Corse",
+ "Fromage de Montagne de Savoie", "Fromage Frais", "Fruit Cream Cheese",
+ "Frying Cheese", "Fynbo", "Gabriel", "Galette du Paludier", "Galette Lyonnaise",
+ "Galloway Goat's Milk Gems", "Gammelost", "Gaperon a l'Ail", "Garrotxa", "Gastanberra",
+ "Geitost", "Gippsland Blue", "Gjetost", "Gloucester", "Golden Cross", "Gorgonzola",
+ "Gornyaltajski", "Gospel Green", "Gouda", "Goutu", "Gowrie", "Grabetto", "Graddost",
+ "Grafton Village Cheddar", "Grana", "Grana Padano", "Grand Vatel",
+ "Grataron d' Areches", "Gratte-Paille", "Graviera", "Greuilh", "Greve",
+ "Gris de Lille", "Gruyere", "Gubbeen", "Guerbigny", "Halloumi",
+ "Halloumy (Australian)", "Haloumi-Style Cheese", "Harbourne Blue", "Havarti",
+ "Heidi Gruyere", "Hereford Hop", "Herrgardsost", "Herriot Farmhouse", "Herve",
+ "Hipi Iti", "Hubbardston Blue Cow", "Hushallsost", "Iberico", "Idaho Goatster",
+ "Idiazabal", "Il Boschetto al Tartufo", "Ile d'Yeu", "Isle of Mull", "Jarlsberg",
+ "Jermi Tortes", "Jibneh Arabieh", "Jindi Brie", "Jubilee Blue", "Juustoleipa",
+ "Kadchgall", "Kaseri", "Kashta", "Kefalotyri", "Kenafa", "Kernhem", "Kervella Affine",
+ "Kikorangi", "King Island Cape Wickham Brie", "King River Gold", "Klosterkaese",
+ "Knockalara", "Kugelkase", "L'Aveyronnais", "L'Ecir de l'Aubrac", "La Taupiniere",
+ "La Vache Qui Rit", "Laguiole", "Lairobell", "Lajta", "Lanark Blue", "Lancashire",
+ "Langres", "Lappi", "Laruns", "Lavistown", "Le Brin", "Le Fium Orbo", "Le Lacandou",
+ "Le Roule", "Leafield", "Lebbene", "Leerdammer", "Leicester", "Leyden", "Limburger",
+ "Lincolnshire Poacher", "Lingot Saint Bousquet d'Orb", "Liptauer", "Little Rydings",
+ "Livarot", "Llanboidy", "Llanglofan Farmhouse", "Loch Arthur Farmhouse",
+ "Loddiswell Avondale", "Longhorn", "Lou Palou", "Lou Pevre", "Lyonnais", "Maasdam",
+ "Macconais", "Mahoe Aged Gouda", "Mahon", "Malvern", "Mamirolle", "Manchego",
+ "Manouri", "Manur", "Marble Cheddar", "Marbled Cheeses", "Maredsous", "Margotin",
+ "Maribo", "Maroilles", "Mascares", "Mascarpone", "Mascarpone (Australian)",
+ "Mascarpone Torta", "Matocq", "Maytag Blue", "Meira", "Menallack Farmhouse",
+ "Menonita", "Meredith Blue", "Mesost", "Metton (Cancoillotte)", "Meyer Vintage Gouda",
+ "Mihalic Peynir", "Milleens", "Mimolette", "Mine-Gabhar", "Mini Baby Bells", "Mixte",
+ "Molbo", "Monastery Cheeses", "Mondseer", "Mont D'or Lyonnais", "Montasio",
+ "Monterey Jack", "Monterey Jack Dry", "Morbier", "Morbier Cru de Montagne",
+ "Mothais a la Feuille", "Mozzarella", "Mozzarella (Australian)",
+ "Mozzarella di Bufala", "Mozzarella Fresh, in water", "Mozzarella Rolls", "Munster",
+ "Murol", "Mycella", "Myzithra", "Naboulsi", "Nantais", "Neufchatel",
+ "Neufchatel (Australian)", "Niolo", "Nokkelost", "Northumberland", "Oaxaca",
+ "Olde York", "Olivet au Foin", "Olivet Bleu", "Olivet Cendre",
+ "Orkney Extra Mature Cheddar", "Orla", "Oschtjepka", "Ossau Fermier", "Ossau-Iraty",
+ "Oszczypek", "Oxford Blue", "P'tit Berrichon", "Palet de Babligny", "Paneer", "Panela",
+ "Pannerone", "Pant ys Gawn", "Parmesan (Parmigiano)", "Parmigiano Reggiano",
+ "Pas de l'Escalette", "Passendale", "Pasteurized Processed", "Pate de Fromage",
+ "Patefine Fort", "Pave d'Affinois", "Pave d'Auge", "Pave de Chirac", "Pave du Berry",
+ "Pecorino", "Pecorino in Walnut Leaves", "Pecorino Romano", "Peekskill Pyramid",
+ "Pelardon des Cevennes", "Pelardon des Corbieres", "Penamellera", "Penbryn",
+ "Pencarreg", "Perail de Brebis", "Petit Morin", "Petit Pardou", "Petit-Suisse",
+ "Picodon de Chevre", "Picos de Europa", "Piora", "Pithtviers au Foin",
+ "Plateau de Herve", "Plymouth Cheese", "Podhalanski", "Poivre d'Ane", "Polkolbin",
+ "Pont l'Eveque", "Port Nicholson", "Port-Salut", "Postel", "Pouligny-Saint-Pierre",
+ "Pourly", "Prastost", "Pressato", "Prince-Jean", "Processed Cheddar", "Provolone",
+ "Provolone (Australian)", "Pyengana Cheddar", "Pyramide", "Quark",
+ "Quark (Australian)", "Quartirolo Lombardo", "Quatre-Vents", "Quercy Petit",
+ "Queso Blanco", "Queso Blanco con Frutas --Pina y Mango", "Queso de Murcia",
+ "Queso del Montsec", "Queso del Tietar", "Queso Fresco", "Queso Fresco (Adobera)",
+ "Queso Iberico", "Queso Jalapeno", "Queso Majorero", "Queso Media Luna",
+ "Queso Para Frier", "Queso Quesadilla", "Rabacal", "Raclette", "Ragusano", "Raschera",
+ "Reblochon", "Red Leicester", "Regal de la Dombes", "Reggianito", "Remedou",
+ "Requeson", "Richelieu", "Ricotta", "Ricotta (Australian)", "Ricotta Salata", "Ridder",
+ "Rigotte", "Rocamadour", "Rollot", "Romano", "Romans Part Dieu", "Roncal", "Roquefort",
+ "Roule", "Rouleau De Beaulieu", "Royalp Tilsit", "Rubens", "Rustinu", "Saaland Pfarr",
+ "Saanenkaese", "Saga", "Sage Derby", "Sainte Maure", "Saint-Marcellin",
+ "Saint-Nectaire", "Saint-Paulin", "Salers", "Samso", "San Simon", "Sancerre",
+ "Sap Sago", "Sardo", "Sardo Egyptian", "Sbrinz", "Scamorza", "Schabzieger", "Schloss",
+ "Selles sur Cher", "Selva", "Serat", "Seriously Strong Cheddar", "Serra da Estrela",
+ "Sharpam", "Shelburne Cheddar", "Shropshire Blue", "Siraz", "Sirene", "Smoked Gouda",
+ "Somerset Brie", "Sonoma Jack", "Sottocenare al Tartufo", "Soumaintrain",
+ "Sourire Lozerien", "Spenwood", "Sraffordshire Organic", "St. Agur Blue Cheese",
+ "Stilton", "Stinking Bishop", "String", "Sussex Slipcote", "Sveciaost", "Swaledale",
+ "Sweet Style Swiss", "Swiss", "Syrian (Armenian String)", "Tala", "Taleggio", "Tamie",
+ "Tasmania Highland Chevre Log", "Taupiniere", "Teifi", "Telemea", "Testouri",
+ "Tete de Moine", "Tetilla", "Texas Goat Cheese", "Tibet", "Tillamook Cheddar",
+ "Tilsit", "Timboon Brie", "Toma", "Tomme Brulee", "Tomme d'Abondance",
+ "Tomme de Chevre", "Tomme de Romans", "Tomme de Savoie", "Tomme des Chouans", "Tommes",
+ "Torta del Casar", "Toscanello", "Touree de L'Aubier", "Tourmalet",
+ "Trappe (Veritable)", "Trois Cornes De Vendee", "Tronchon", "Trou du Cru", "Truffe",
+ "Tupi", "Turunmaa", "Tymsboro", "Tyn Grug", "Tyning", "Ubriaco", "Ulloa",
+ "Vacherin-Fribourgeois", "Valencay", "Vasterbottenost", "Venaco", "Vendomois",
+ "Vieux Corse", "Vignotte", "Vulscombe", "Waimata Farmhouse Blue",
+ "Washed Rind Cheese (Australian)", "Waterloo", "Weichkaese", "Wellington",
+ "Wensleydale", "White Stilton", "Whitestone Farmhouse", "Wigmore", "Woodside Cabecou",
+ "Xanadu", "Xynotyro", "Yarg Cornish", "Yarra Valley Pyramid", "Yorkshire Blue",
+ "Zamorano", "Zanetti Grana Padano", "Zanetti Parmigiano Reggiano"
+ };
+
+ public static ArrayList<String> asList() {
+ ArrayList<String> items = new ArrayList<String>();
+ for (int i = 0, z = CHEESES.length ; i < z ; i++) {
+ items.add(CHEESES[i]);
+ }
+ return items;
+ }
+
+ /**
+ * Return a list of random cheeses.
+ *
+ * @param count the amount of cheeses to return.
+ */
+ public static ArrayList<String> randomList(int count) {
+ Random random = new Random();
+ HashSet<String> items = new HashSet<String>();
+
+ // Make sure that don't infinity loop
+ count = Math.min(count, CHEESES.length);
+
+ while (items.size() < count) {
+ items.add(CHEESES[random.nextInt(CHEESES.length)]);
+ }
+
+ return new ArrayList<String>(items);
+ }
+}
diff --git a/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.common/logger/Log.java b/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.common/logger/Log.java
new file mode 100644
index 0000000..17503c5
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.common/logger/Log.java
@@ -0,0 +1,236 @@
+/*
+ * 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.logger;
+
+/**
+ * Helper class for a list (or tree) of LoggerNodes.
+ *
+ * <p>When this is set as the head of the list,
+ * an instance of it can function as a drop-in replacement for {@link android.util.Log}.
+ * Most of the methods in this class server only to map a method call in Log to its equivalent
+ * in LogNode.</p>
+ */
+public class Log {
+ // Grabbing the native values from Android's native logging facilities,
+ // to make for easy migration and interop.
+ public static final int NONE = -1;
+ public static final int VERBOSE = android.util.Log.VERBOSE;
+ public static final int DEBUG = android.util.Log.DEBUG;
+ public static final int INFO = android.util.Log.INFO;
+ public static final int WARN = android.util.Log.WARN;
+ public static final int ERROR = android.util.Log.ERROR;
+ public static final int ASSERT = android.util.Log.ASSERT;
+
+ // Stores the beginning of the LogNode topology.
+ private static LogNode mLogNode;
+
+ /**
+ * Returns the next LogNode in the linked list.
+ */
+ public static LogNode getLogNode() {
+ return mLogNode;
+ }
+
+ /**
+ * Sets the LogNode data will be sent to.
+ */
+ public static void setLogNode(LogNode node) {
+ mLogNode = node;
+ }
+
+ /**
+ * Instructs the LogNode to print the log data provided. Other LogNodes can
+ * be chained to the end of the LogNode as desired.
+ *
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void println(int priority, String tag, String msg, Throwable tr) {
+ if (mLogNode != null) {
+ mLogNode.println(priority, tag, msg, tr);
+ }
+ }
+
+ /**
+ * Instructs the LogNode to print the log data provided. Other LogNodes can
+ * be chained to the end of the LogNode as desired.
+ *
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ */
+ public static void println(int priority, String tag, String msg) {
+ println(priority, tag, msg, null);
+ }
+
+ /**
+ * Prints a message at VERBOSE priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void v(String tag, String msg, Throwable tr) {
+ println(VERBOSE, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at VERBOSE priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void v(String tag, String msg) {
+ v(tag, msg, null);
+ }
+
+
+ /**
+ * Prints a message at DEBUG priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void d(String tag, String msg, Throwable tr) {
+ println(DEBUG, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at DEBUG priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void d(String tag, String msg) {
+ d(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at INFO priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void i(String tag, String msg, Throwable tr) {
+ println(INFO, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at INFO priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void i(String tag, String msg) {
+ i(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at WARN priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void w(String tag, String msg, Throwable tr) {
+ println(WARN, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at WARN priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void w(String tag, String msg) {
+ w(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at WARN priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void w(String tag, Throwable tr) {
+ w(tag, null, tr);
+ }
+
+ /**
+ * Prints a message at ERROR priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void e(String tag, String msg, Throwable tr) {
+ println(ERROR, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at ERROR priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void e(String tag, String msg) {
+ e(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at ASSERT priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void wtf(String tag, String msg, Throwable tr) {
+ println(ASSERT, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at ASSERT priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void wtf(String tag, String msg) {
+ wtf(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at ASSERT priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void wtf(String tag, Throwable tr) {
+ wtf(tag, null, tr);
+ }
+}
diff --git a/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.common/logger/LogFragment.java b/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.common/logger/LogFragment.java
new file mode 100644
index 0000000..b302acd
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.common/logger/LogFragment.java
@@ -0,0 +1,109 @@
+/*
+* 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 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.logger;
+
+import android.graphics.Typeface;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ScrollView;
+
+/**
+ * Simple fraggment which contains a LogView and uses is to output log data it receives
+ * through the LogNode interface.
+ */
+public class LogFragment extends Fragment {
+
+ private LogView mLogView;
+ private ScrollView mScrollView;
+
+ public LogFragment() {}
+
+ public View inflateViews() {
+ mScrollView = new ScrollView(getActivity());
+ ViewGroup.LayoutParams scrollParams = new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT);
+ mScrollView.setLayoutParams(scrollParams);
+
+ mLogView = new LogView(getActivity());
+ ViewGroup.LayoutParams logParams = new ViewGroup.LayoutParams(scrollParams);
+ logParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+ mLogView.setLayoutParams(logParams);
+ mLogView.setClickable(true);
+ mLogView.setFocusable(true);
+ mLogView.setTypeface(Typeface.MONOSPACE);
+
+ // Want to set padding as 16 dips, setPadding takes pixels. Hooray math!
+ int paddingDips = 16;
+ double scale = getResources().getDisplayMetrics().density;
+ int paddingPixels = (int) ((paddingDips * (scale)) + .5);
+ mLogView.setPadding(paddingPixels, paddingPixels, paddingPixels, paddingPixels);
+ mLogView.setCompoundDrawablePadding(paddingPixels);
+
+ mLogView.setGravity(Gravity.BOTTOM);
+ mLogView.setTextAppearance(getActivity(), android.R.style.TextAppearance_Holo_Medium);
+
+ mScrollView.addView(mLogView);
+ return mScrollView;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+
+ View result = inflateViews();
+
+ mLogView.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {}
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ mScrollView.fullScroll(ScrollView.FOCUS_DOWN);
+ }
+ });
+ return result;
+ }
+
+ public LogView getLogView() {
+ return mLogView;
+ }
+}
\ No newline at end of file
diff --git a/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.common/logger/LogNode.java b/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.common/logger/LogNode.java
new file mode 100644
index 0000000..bc37cab
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.common/logger/LogNode.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012 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.logger;
+
+/**
+ * Basic interface for a logging system that can output to one or more targets.
+ * Note that in addition to classes that will output these logs in some format,
+ * one can also implement this interface over a filter and insert that in the chain,
+ * such that no targets further down see certain data, or see manipulated forms of the data.
+ * You could, for instance, write a "ToHtmlLoggerNode" that just converted all the log data
+ * it received to HTML and sent it along to the next node in the chain, without printing it
+ * anywhere.
+ */
+public interface LogNode {
+
+ /**
+ * Instructs first LogNode in the list to print the log data provided.
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public void println(int priority, String tag, String msg, Throwable tr);
+
+}
diff --git a/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.common/logger/LogView.java b/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.common/logger/LogView.java
new file mode 100644
index 0000000..c01542b
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.common/logger/LogView.java
@@ -0,0 +1,145 @@
+/*
+ * 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.logger;
+
+import android.app.Activity;
+import android.content.Context;
+import android.util.*;
+import android.widget.TextView;
+
+/** Simple TextView which is used to output log data received through the LogNode interface.
+*/
+public class LogView extends TextView implements LogNode {
+
+ public LogView(Context context) {
+ super(context);
+ }
+
+ public LogView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public LogView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ /**
+ * Formats the log data and prints it out to the LogView.
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ @Override
+ public void println(int priority, String tag, String msg, Throwable tr) {
+
+
+ String priorityStr = null;
+
+ // For the purposes of this View, we want to print the priority as readable text.
+ switch(priority) {
+ case android.util.Log.VERBOSE:
+ priorityStr = "VERBOSE";
+ break;
+ case android.util.Log.DEBUG:
+ priorityStr = "DEBUG";
+ break;
+ case android.util.Log.INFO:
+ priorityStr = "INFO";
+ break;
+ case android.util.Log.WARN:
+ priorityStr = "WARN";
+ break;
+ case android.util.Log.ERROR:
+ priorityStr = "ERROR";
+ break;
+ case android.util.Log.ASSERT:
+ priorityStr = "ASSERT";
+ break;
+ default:
+ break;
+ }
+
+ // Handily, the Log class has a facility for converting a stack trace into a usable string.
+ String exceptionStr = null;
+ if (tr != null) {
+ exceptionStr = android.util.Log.getStackTraceString(tr);
+ }
+
+ // Take the priority, tag, message, and exception, and concatenate as necessary
+ // into one usable line of text.
+ final StringBuilder outputBuilder = new StringBuilder();
+
+ String delimiter = "\t";
+ appendIfNotNull(outputBuilder, priorityStr, delimiter);
+ appendIfNotNull(outputBuilder, tag, delimiter);
+ appendIfNotNull(outputBuilder, msg, delimiter);
+ appendIfNotNull(outputBuilder, exceptionStr, delimiter);
+
+ // In case this was originally called from an AsyncTask or some other off-UI thread,
+ // make sure the update occurs within the UI thread.
+ ((Activity) getContext()).runOnUiThread( (new Thread(new Runnable() {
+ @Override
+ public void run() {
+ // Display the text we just generated within the LogView.
+ appendToLog(outputBuilder.toString());
+ }
+ })));
+
+ if (mNext != null) {
+ mNext.println(priority, tag, msg, tr);
+ }
+ }
+
+ public LogNode getNext() {
+ return mNext;
+ }
+
+ public void setNext(LogNode node) {
+ mNext = node;
+ }
+
+ /** Takes a string and adds to it, with a separator, if the bit to be added isn't null. Since
+ * the logger takes so many arguments that might be null, this method helps cut out some of the
+ * agonizing tedium of writing the same 3 lines over and over.
+ * @param source StringBuilder containing the text to append to.
+ * @param addStr The String to append
+ * @param delimiter The String to separate the source and appended strings. A tab or comma,
+ * for instance.
+ * @return The fully concatenated String as a StringBuilder
+ */
+ private StringBuilder appendIfNotNull(StringBuilder source, String addStr, String delimiter) {
+ if (addStr != null) {
+ if (addStr.length() == 0) {
+ delimiter = "";
+ }
+
+ return source.append(addStr).append(delimiter);
+ }
+ return source;
+ }
+
+ // The next LogNode in the chain.
+ LogNode mNext;
+
+ /** Outputs the string as a new line of log data in the LogView. */
+ public void appendToLog(String s) {
+ append("\n" + s);
+ }
+
+
+}
diff --git a/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.common/logger/LogWrapper.java b/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.common/logger/LogWrapper.java
new file mode 100644
index 0000000..16a9e7b
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.common/logger/LogWrapper.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2012 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.logger;
+
+import android.util.Log;
+
+/**
+ * Helper class which wraps Android's native Log utility in the Logger interface. This way
+ * normal DDMS output can be one of the many targets receiving and outputting logs simultaneously.
+ */
+public class LogWrapper implements LogNode {
+
+ // For piping: The next node to receive Log data after this one has done its work.
+ private LogNode mNext;
+
+ /**
+ * Returns the next LogNode in the linked list.
+ */
+ public LogNode getNext() {
+ return mNext;
+ }
+
+ /**
+ * Sets the LogNode data will be sent to..
+ */
+ public void setNext(LogNode node) {
+ mNext = node;
+ }
+
+ /**
+ * Prints data out to the console using Android's native log mechanism.
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ @Override
+ public void println(int priority, String tag, String msg, Throwable tr) {
+ // There actually are log methods that don't take a msg parameter. For now,
+ // if that's the case, just convert null to the empty string and move on.
+ String useMsg = msg;
+ if (useMsg == null) {
+ useMsg = "";
+ }
+
+ // If an exeption was provided, convert that exception to a usable string and attach
+ // it to the end of the msg method.
+ if (tr != null) {
+ msg += "\n" + Log.getStackTraceString(tr);
+ }
+
+ // This is functionally identical to Log.x(tag, useMsg);
+ // For instance, if priority were Log.VERBOSE, this would be the same as Log.v(tag, useMsg)
+ Log.println(priority, tag, useMsg);
+
+ // If this isn't the last node in the chain, move things along.
+ if (mNext != null) {
+ mNext.println(priority, tag, msg, tr);
+ }
+ }
+}
diff --git a/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.common/logger/MessageOnlyLogFilter.java b/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.common/logger/MessageOnlyLogFilter.java
new file mode 100644
index 0000000..19967dc
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.common/logger/MessageOnlyLogFilter.java
@@ -0,0 +1,60 @@
+/*
+ * 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.logger;
+
+/**
+ * Simple {@link LogNode} filter, removes everything except the message.
+ * Useful for situations like on-screen log output where you don't want a lot of metadata displayed,
+ * just easy-to-read message updates as they're happening.
+ */
+public class MessageOnlyLogFilter implements LogNode {
+
+ LogNode mNext;
+
+ /**
+ * Takes the "next" LogNode as a parameter, to simplify chaining.
+ *
+ * @param next The next LogNode in the pipeline.
+ */
+ public MessageOnlyLogFilter(LogNode next) {
+ mNext = next;
+ }
+
+ public MessageOnlyLogFilter() {
+ }
+
+ @Override
+ public void println(int priority, String tag, String msg, Throwable tr) {
+ if (mNext != null) {
+ getNext().println(Log.NONE, null, msg, null);
+ }
+ }
+
+ /**
+ * Returns the next LogNode in the chain.
+ */
+ public LogNode getNext() {
+ return mNext;
+ }
+
+ /**
+ * Sets the LogNode data will be sent to..
+ */
+ public void setNext(LogNode node) {
+ mNext = node;
+ }
+
+}
diff --git a/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.common/view/SlidingTabLayout.java b/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.common/view/SlidingTabLayout.java
new file mode 100644
index 0000000..20049e3
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/src/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/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.common/view/SlidingTabStrip.java b/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.common/view/SlidingTabStrip.java
new file mode 100644
index 0000000..d5bbbae
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/src/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/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.swiperefreshmultipleviews/MainActivity.java b/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.swiperefreshmultipleviews/MainActivity.java
new file mode 100644
index 0000000..0191d87
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.swiperefreshmultipleviews/MainActivity.java
@@ -0,0 +1,110 @@
+/*
+* 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.
+*/
+
+
+
+
+package com.example.android.swiperefreshmultipleviews;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentTransaction;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.ViewAnimator;
+
+import com.example.android.common.activities.SampleActivityBase;
+import com.example.android.common.logger.Log;
+import com.example.android.common.logger.LogFragment;
+import com.example.android.common.logger.LogWrapper;
+import com.example.android.common.logger.MessageOnlyLogFilter;
+
+/**
+ * A simple launcher activity containing a summary sample description, sample log and a custom
+ * {@link android.support.v4.app.Fragment} which can display a view.
+ * <p>
+ * For devices with displays with a width of 720dp or greater, the sample log is always visible,
+ * on other devices it's visibility is controlled by an item on the Action Bar.
+ */
+public class MainActivity extends SampleActivityBase {
+
+ public static final String TAG = "MainActivity";
+
+ // Whether the Log Fragment is currently shown
+ private boolean mLogShown;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+ SwipeRefreshMultipleViewsFragment fragment = new SwipeRefreshMultipleViewsFragment();
+ transaction.replace(R.id.sample_content_fragment, fragment);
+ transaction.commit();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.main, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ MenuItem logToggle = menu.findItem(R.id.menu_toggle_log);
+ logToggle.setVisible(findViewById(R.id.sample_output) instanceof ViewAnimator);
+ logToggle.setTitle(mLogShown ? R.string.sample_hide_log : R.string.sample_show_log);
+
+ return super.onPrepareOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch(item.getItemId()) {
+ case R.id.menu_toggle_log:
+ mLogShown = !mLogShown;
+ ViewAnimator output = (ViewAnimator) findViewById(R.id.sample_output);
+ if (mLogShown) {
+ output.setDisplayedChild(1);
+ } else {
+ output.setDisplayedChild(0);
+ }
+ supportInvalidateOptionsMenu();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ /** Create a chain of targets that will receive log data */
+ @Override
+ public void initializeLogging() {
+ // Wraps Android's native log framework.
+ LogWrapper logWrapper = new LogWrapper();
+ // Using Log, front-end to the logging chain, emulates android.util.log method signatures.
+ Log.setLogNode(logWrapper);
+
+ // Filter strips out everything except the message text.
+ MessageOnlyLogFilter msgFilter = new MessageOnlyLogFilter();
+ logWrapper.setNext(msgFilter);
+
+ // On screen logging via a fragment with a TextView.
+ LogFragment logFragment = (LogFragment) getSupportFragmentManager()
+ .findFragmentById(R.id.log_fragment);
+ msgFilter.setNext(logFragment.getLogView());
+
+ Log.i(TAG, "Ready");
+ }
+}
diff --git a/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.swiperefreshmultipleviews/MultiSwipeRefreshLayout.java b/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.swiperefreshmultipleviews/MultiSwipeRefreshLayout.java
new file mode 100644
index 0000000..4e50145
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.swiperefreshmultipleviews/MultiSwipeRefreshLayout.java
@@ -0,0 +1,107 @@
+/*
+ * 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.swiperefreshmultipleviews;
+
+import android.content.Context;
+import android.support.v4.view.ViewCompat;
+import android.support.v4.widget.SwipeRefreshLayout;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.AbsListView;
+
+/**
+ * A descendant of {@link android.support.v4.widget.SwipeRefreshLayout} which supports multiple
+ * child views triggering a refresh gesture. You set the views which can trigger the gesture via
+ * {@link #setSwipeableChildren(int...)}, providing it the child ids.
+ */
+public class MultiSwipeRefreshLayout extends SwipeRefreshLayout {
+
+ private View[] mSwipeableChildren;
+
+ public MultiSwipeRefreshLayout(Context context) {
+ super(context);
+ }
+
+ public MultiSwipeRefreshLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ /**
+ * Set the children which can trigger a refresh by swiping down when they are visible. These
+ * views need to be a descendant of this view.
+ */
+ public void setSwipeableChildren(final int... ids) {
+ assert ids != null;
+
+ // Iterate through the ids and find the Views
+ mSwipeableChildren = new View[ids.length];
+ for (int i = 0; i < ids.length; i++) {
+ mSwipeableChildren[i] = findViewById(ids[i]);
+ }
+ }
+
+ // BEGIN_INCLUDE(can_child_scroll_up)
+ /**
+ * This method controls when the swipe-to-refresh gesture is triggered. By returning false here
+ * we are signifying that the view is in a state where a refresh gesture can start.
+ *
+ * <p>As {@link android.support.v4.widget.SwipeRefreshLayout} only supports one direct child by
+ * default, we need to manually iterate through our swipeable children to see if any are in a
+ * state to trigger the gesture. If so we return false to start the gesture.
+ */
+ @Override
+ public boolean canChildScrollUp() {
+ if (mSwipeableChildren != null && mSwipeableChildren.length > 0) {
+ // Iterate through the scrollable children and check if any of them can not scroll up
+ for (View view : mSwipeableChildren) {
+ if (view != null && view.isShown() && !canViewScrollUp(view)) {
+ // If the view is shown, and can not scroll upwards, return false and start the
+ // gesture.
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+ // END_INCLUDE(can_child_scroll_up)
+
+ // BEGIN_INCLUDE(can_view_scroll_up)
+ /**
+ * Utility method to check whether a {@link View} can scroll up from it's current position.
+ * Handles platform version differences, providing backwards compatible functionality where
+ * needed.
+ */
+ private static boolean canViewScrollUp(View view) {
+ if (android.os.Build.VERSION.SDK_INT >= 14) {
+ // For ICS and above we can call canScrollVertically() to determine this
+ return ViewCompat.canScrollVertically(view, -1);
+ } else {
+ if (view instanceof AbsListView) {
+ // Pre-ICS we need to manually check the first visible item and the child view's top
+ // value
+ final AbsListView listView = (AbsListView) view;
+ return listView.getChildCount() > 0 &&
+ (listView.getFirstVisiblePosition() > 0
+ || listView.getChildAt(0).getTop() < listView.getPaddingTop());
+ } else {
+ // For all other view types we just check the getScrollY() value
+ return view.getScrollY() > 0;
+ }
+ }
+ }
+ // END_INCLUDE(can_view_scroll_up)
+}
diff --git a/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.swiperefreshmultipleviews/SwipeRefreshMultipleViewsFragment.java b/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.swiperefreshmultipleviews/SwipeRefreshMultipleViewsFragment.java
new file mode 100644
index 0000000..e2b83d3
--- /dev/null
+++ b/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.swiperefreshmultipleviews/SwipeRefreshMultipleViewsFragment.java
@@ -0,0 +1,256 @@
+/*
+ * 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.swiperefreshmultipleviews;
+
+import com.example.android.common.dummydata.Cheeses;
+import com.example.android.common.logger.Log;
+
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.widget.SwipeRefreshLayout;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.GridView;
+
+import java.util.List;
+
+/**
+ * A sample which shows how to use {@link android.support.v4.widget.SwipeRefreshLayout} to add
+ * the 'swipe-to-refresh' gesture to a layout with multiple children. In this sample,
+ * SwipeRefreshLayout contains a scrollable {@link android.widget.GridView}, along with a
+ * {@link android.widget.TextView} empty view.
+ *
+ * <p>To provide an accessible way to trigger the refresh, this app also provides a refresh
+ * action item.
+ *
+ * <p>In this sample app, the refresh updates the GridView with a random set of new items.
+ */
+public class SwipeRefreshMultipleViewsFragment extends Fragment {
+
+ private static final String LOG_TAG = SwipeRefreshMultipleViewsFragment.class.getSimpleName();
+
+ private static final int LIST_ITEM_COUNT = 40;
+
+ /**
+ * The {@link MultiSwipeRefreshLayout} that detects swipe gestures and triggers callbacks in
+ * the app.
+ */
+ private MultiSwipeRefreshLayout mSwipeRefreshLayout;
+
+ /**
+ * The {@link android.widget.GridView} that displays the content that should be refreshed.
+ */
+ private GridView mGridView;
+
+ /**
+ * The {@link android.widget.ListAdapter} used to populate the {@link android.widget.GridView}
+ * defined in the previous statement.
+ */
+ private ArrayAdapter<String> mListAdapter;
+
+ /**
+ * The {@link View} which is displayed when the GridView is empty.
+ */
+ private View mEmptyView;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Notify the system to allow an options menu for this fragment.
+ setHasOptionsMenu(true);
+ }
+
+ // BEGIN_INCLUDE (inflate_view)
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.fragment_sample, container, false);
+
+ // Retrieve the SwipeRefreshLayout and GridView instances
+ mSwipeRefreshLayout = (MultiSwipeRefreshLayout) view.findViewById(R.id.swiperefresh);
+
+ // BEGIN_INCLUDE (change_colors)
+ // Set the color scheme of the SwipeRefreshLayout by providing 4 color resource ids
+ mSwipeRefreshLayout.setColorScheme(
+ R.color.swipe_color_1, R.color.swipe_color_2,
+ R.color.swipe_color_3, R.color.swipe_color_4);
+ // END_INCLUDE (change_colors)
+
+ // Retrieve the GridView
+ mGridView = (GridView) view.findViewById(android.R.id.list);
+
+ // Retrieve the empty view
+ mEmptyView = view.findViewById(android.R.id.empty);
+
+ return view;
+ }
+ // END_INCLUDE (inflate_view)
+
+ // BEGIN_INCLUDE (setup_views)
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+
+ /**
+ * Create an ArrayAdapter to contain the data for the GridView. Each item in the GridView
+ * uses the system-defined simple_list_item_1 layout that contains one TextView. Initially
+ */
+ mListAdapter = new ArrayAdapter<String>(
+ getActivity(),
+ android.R.layout.simple_list_item_1,
+ android.R.id.text1);
+
+ // Set the adapter between the GridView and its backing data.
+ mGridView.setAdapter(mListAdapter);
+
+ // Set the empty view so that it is displayed as needed
+ mGridView.setEmptyView(mEmptyView);
+
+ // BEGIN_INCLUDE (setup_swipeable_children)
+ // Tell the MultiSwipeRefreshLayout which views are swipeable. In this case, the GridView
+ // and empty view.
+ mSwipeRefreshLayout.setSwipeableChildren(android.R.id.list, android.R.id.empty);
+ // END_INCLUDE (setup_swipeable_children)
+
+ // BEGIN_INCLUDE (setup_refreshlistener)
+ /**
+ * Implement {@link SwipeRefreshLayout.OnRefreshListener}. When users do the "swipe to
+ * refresh" gesture, SwipeRefreshLayout invokes
+ * {@link SwipeRefreshLayout.OnRefreshListener#onRefresh onRefresh()}. In
+ * {@link SwipeRefreshLayout.OnRefreshListener#onRefresh onRefresh()}, call a method that
+ * refreshes the content. Call the same method in response to the Refresh action from the
+ * action bar.
+ */
+ mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
+ @Override
+ public void onRefresh() {
+ Log.i(LOG_TAG, "onRefresh called from SwipeRefreshLayout");
+
+ initiateRefresh();
+ }
+ });
+ // END_INCLUDE (setup_refreshlistener)
+ }
+ // END_INCLUDE (setup_views)
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ inflater.inflate(R.menu.main_menu, menu);
+ }
+
+ // BEGIN_INCLUDE (setup_refresh_menu_listener)
+ /**
+ * Respond to the user's selection of the Refresh action item. Start the SwipeRefreshLayout
+ * progress bar, then initiate the background task that refreshes the content.
+ */
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.menu_clear:
+ Log.i(LOG_TAG, "Clear menu item selected");
+ mListAdapter.clear();
+ return true;
+
+ case R.id.menu_refresh:
+ Log.i(LOG_TAG, "Refresh menu item selected");
+
+ // We make sure that the SwipeRefreshLayout is displaying it's refreshing indicator
+ if (!mSwipeRefreshLayout.isRefreshing()) {
+ mSwipeRefreshLayout.setRefreshing(true);
+ }
+
+ // Start our refresh background task
+ initiateRefresh();
+
+ return true;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+ // END_INCLUDE (setup_refresh_menu_listener)
+
+ // BEGIN_INCLUDE (initiate_refresh)
+ /**
+ * By abstracting the refresh process to a single method, the app allows both the
+ * SwipeGestureLayout onRefresh() method and the Refresh action item to refresh the content.
+ */
+ private void initiateRefresh() {
+ Log.i(LOG_TAG, "initiateRefresh");
+
+ /**
+ * Execute the background task, which uses {@link android.os.AsyncTask} to load the data.
+ */
+ new DummyBackgroundTask().execute();
+ }
+ // END_INCLUDE (initiate_refresh)
+
+ // BEGIN_INCLUDE (refresh_complete)
+ /**
+ * When the AsyncTask finishes, it calls onRefreshComplete(), which updates the data in the
+ * ListAdapter and turns off the progress bar.
+ */
+ private void onRefreshComplete(List<String> result) {
+ Log.i(LOG_TAG, "onRefreshComplete");
+
+ // Remove all items from the ListAdapter, and then replace them with the new items
+ mListAdapter.clear();
+ for (String cheese : result) {
+ mListAdapter.add(cheese);
+ }
+
+ // Stop the refreshing indicator
+ mSwipeRefreshLayout.setRefreshing(false);
+ }
+ // END_INCLUDE (refresh_complete)
+
+ /**
+ * Dummy {@link AsyncTask} which simulates a long running task to fetch new cheeses.
+ */
+ private class DummyBackgroundTask extends AsyncTask<Void, Void, List<String>> {
+
+ static final int TASK_DURATION = 3 * 1000; // 3 seconds
+
+ @Override
+ protected List<String> doInBackground(Void... params) {
+ // Sleep for a small amount of time to simulate a background-task
+ try {
+ Thread.sleep(TASK_DURATION);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ // Return a new random list of cheeses
+ return Cheeses.randomList(LIST_ITEM_COUNT);
+ }
+
+ @Override
+ protected void onPostExecute(List<String> result) {
+ super.onPostExecute(result);
+
+ // Tell the Fragment that the refresh has completed
+ onRefreshComplete(result);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/samples/browseable/TextLinkify/res/values-v11/template-styles.xml b/samples/browseable/TextLinkify/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/TextLinkify/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/TextLinkify/res/values/template-styles.xml b/samples/browseable/TextLinkify/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/TextLinkify/res/values/template-styles.xml
+++ b/samples/browseable/TextLinkify/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/browseable/TextSwitcher/res/values-v11/template-styles.xml b/samples/browseable/TextSwitcher/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/TextSwitcher/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/TextSwitcher/res/values/template-styles.xml b/samples/browseable/TextSwitcher/res/values/template-styles.xml
index 404623e..6e7d593 100644
--- a/samples/browseable/TextSwitcher/res/values/template-styles.xml
+++ b/samples/browseable/TextSwitcher/res/values/template-styles.xml
@@ -18,7 +18,7 @@
<!-- Activity themes -->
- <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+ <style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
diff --git a/samples/samples_source.prop_template b/samples/samples_source.prop_template
index 315be08..d3cdfd5 100644
--- a/samples/samples_source.prop_template
+++ b/samples/samples_source.prop_template
@@ -1,4 +1,4 @@
Pkg.UserSrc=false
-Pkg.Revision=4
+Pkg.Revision=1
AndroidVersion.ApiLevel=${PLATFORM_SDK_VERSION}
AndroidVersion.CodeName=${PLATFORM_VERSION_CODENAME}
diff --git a/scripts/app_engine_server/redirects.yaml b/scripts/app_engine_server/redirects.yaml
index b7a90a5..c37ac00 100644
--- a/scripts/app_engine_server/redirects.yaml
+++ b/scripts/app_engine_server/redirects.yaml
@@ -77,6 +77,14 @@
type: permanent
comment: Redirect sdk reference to new location
+- src: /sdk/exploring.html
+ dst: /sdk/tools/help/sdk-manager.html
+ type: permanent
+
+- src: /sdk/installing/bundle.html
+ dst: /sdk/installing/index.html?pkg=adt
+ type: permanent
+
- src: /sdk/compatibility-library.html
dst: /tools/support-library/index.html
type: permanent
diff --git a/sdk/build_tools_source.prop_template b/sdk/build_tools_source.prop_template
index c9bfc2f..5d62307 100644
--- a/sdk/build_tools_source.prop_template
+++ b/sdk/build_tools_source.prop_template
@@ -1,3 +1,3 @@
Pkg.UserSrc=false
-Pkg.Revision=${PLATFORM_SDK_VERSION}.0.2
+Pkg.Revision=${PLATFORM_SDK_VERSION}.0.0
diff --git a/sdk/doc_source.prop_template b/sdk/doc_source.prop_template
index 523d6bd..d3cdfd5 100644
--- a/sdk/doc_source.prop_template
+++ b/sdk/doc_source.prop_template
@@ -1,4 +1,4 @@
Pkg.UserSrc=false
-Pkg.Revision=2
+Pkg.Revision=1
AndroidVersion.ApiLevel=${PLATFORM_SDK_VERSION}
AndroidVersion.CodeName=${PLATFORM_VERSION_CODENAME}
diff --git a/sdk/plat_tools_source.prop_template b/sdk/plat_tools_source.prop_template
index b83af7f..5d62307 100644
--- a/sdk/plat_tools_source.prop_template
+++ b/sdk/plat_tools_source.prop_template
@@ -1,3 +1,3 @@
Pkg.UserSrc=false
-Pkg.Revision=${PLATFORM_SDK_VERSION}.0.1
+Pkg.Revision=${PLATFORM_SDK_VERSION}.0.0
diff --git a/sdk/platform_source.prop_template b/sdk/platform_source.prop_template
index 09a2d81..7ecb1e2 100644
--- a/sdk/platform_source.prop_template
+++ b/sdk/platform_source.prop_template
@@ -2,7 +2,7 @@
Pkg.UserSrc=false
Platform.Version=${PLATFORM_VERSION}
Platform.CodeName=KitKat
-Pkg.Revision=2
+Pkg.Revision=1
AndroidVersion.ApiLevel=${PLATFORM_SDK_VERSION}
AndroidVersion.CodeName=${PLATFORM_VERSION_CODENAME}
Layoutlib.Api=10
diff --git a/sdk/source_source.prop_template b/sdk/source_source.prop_template
index 523d6bd..d3cdfd5 100644
--- a/sdk/source_source.prop_template
+++ b/sdk/source_source.prop_template
@@ -1,4 +1,4 @@
Pkg.UserSrc=false
-Pkg.Revision=2
+Pkg.Revision=1
AndroidVersion.ApiLevel=${PLATFORM_SDK_VERSION}
AndroidVersion.CodeName=${PLATFORM_VERSION_CODENAME}
diff --git a/sdk/support_source.prop_template b/sdk/support_source.prop_template
index f897712..f5b217e 100644
--- a/sdk/support_source.prop_template
+++ b/sdk/support_source.prop_template
@@ -1,5 +1,5 @@
Pkg.UserSrc=false
-Pkg.Revision=${PLATFORM_SDK_VERSION}.0.1
+Pkg.Revision=${PLATFORM_SDK_VERSION}.0.0
Extra.Vendor=android
Extra.VendorId=android
Extra.VendorDisplay=Android
diff --git a/sys-img/images_armeabi-v7a_source.prop_template b/sys-img/images_armeabi-v7a_source.prop_template
index 7d13fce..9c7a332 100644
--- a/sys-img/images_armeabi-v7a_source.prop_template
+++ b/sys-img/images_armeabi-v7a_source.prop_template
@@ -1,6 +1,6 @@
Pkg.Desc=Android SDK Platform ${PLATFORM_VERSION}
Pkg.UserSrc=false
-Pkg.Revision=2
+Pkg.Revision=1
AndroidVersion.ApiLevel=${PLATFORM_SDK_VERSION}
AndroidVersion.CodeName=${PLATFORM_VERSION_CODENAME}
SystemImage.Abi=armeabi-v7a
diff --git a/sys-img/images_armeabi_source.prop_template b/sys-img/images_armeabi_source.prop_template
index ef17ea6..91e9d21 100644
--- a/sys-img/images_armeabi_source.prop_template
+++ b/sys-img/images_armeabi_source.prop_template
@@ -1,6 +1,6 @@
Pkg.Desc=Android SDK Platform ${PLATFORM_VERSION}
Pkg.UserSrc=false
-Pkg.Revision=2
+Pkg.Revision=1
AndroidVersion.ApiLevel=${PLATFORM_SDK_VERSION}
AndroidVersion.CodeName=${PLATFORM_VERSION_CODENAME}
SystemImage.Abi=armeabi
diff --git a/sys-img/images_x86_source.prop_template b/sys-img/images_x86_source.prop_template
index d5f5610..1a18cf8 100644
--- a/sys-img/images_x86_source.prop_template
+++ b/sys-img/images_x86_source.prop_template
@@ -1,6 +1,6 @@
Pkg.Desc=Android SDK Platform ${PLATFORM_VERSION}
Pkg.UserSrc=false
-Pkg.Revision=2
+Pkg.Revision=1
AndroidVersion.ApiLevel=${PLATFORM_SDK_VERSION}
AndroidVersion.CodeName=${PLATFORM_VERSION_CODENAME}
SystemImage.Abi=${TARGET_CPU_ABI}
diff --git a/tools/emulator/test-apps/SmokeTests/Android.mk b/tools/emulator/test-apps/ConnectivityTest/Android.mk
similarity index 80%
copy from tools/emulator/test-apps/SmokeTests/Android.mk
copy to tools/emulator/test-apps/ConnectivityTest/Android.mk
index 41951dd..ca20d57 100644
--- a/tools/emulator/test-apps/SmokeTests/Android.mk
+++ b/tools/emulator/test-apps/ConnectivityTest/Android.mk
@@ -1,4 +1,4 @@
-# Copyright (C) 2014 The Android Open Source Project
+# Copyright (C) 2011 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.
@@ -15,18 +15,18 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_STATIC_JAVA_LIBRARIES := android-test-lib
-
LOCAL_MODULE_TAGS := optional
# Only compile source java files in this apk.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_PACKAGE_NAME := EmulatorSmokeTests
+LOCAL_PACKAGE_NAME := ConnectivityTest
LOCAL_SDK_VERSION := 4
LOCAL_PROGUARD_ENABLED := disabled
-
include $(BUILD_PACKAGE)
+
+# Use the following include to make our test apk.
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tools/emulator/test-apps/SmokeTests/AndroidManifest.xml b/tools/emulator/test-apps/ConnectivityTest/AndroidManifest.xml
similarity index 70%
rename from tools/emulator/test-apps/SmokeTests/AndroidManifest.xml
rename to tools/emulator/test-apps/ConnectivityTest/AndroidManifest.xml
index 7066ca6..80f65cf 100644
--- a/tools/emulator/test-apps/SmokeTests/AndroidManifest.xml
+++ b/tools/emulator/test-apps/ConnectivityTest/AndroidManifest.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2011 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.
@@ -14,15 +14,14 @@
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.emulator.smoketests">
- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ package="com.android.emulator.connectivity.test"
+ android:versionCode="1"
+ android:versionName="1.0">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
- <uses-permission android:name="android.permission.READ_SMS" />
<uses-sdk android:minSdkVersion="4" />
- <instrumentation android:targetPackage="com.android.emulator.smoketests"
- android:name="com.android.test.runner.AndroidJUnitRunner" />
- <application android:label="Emulator Smoke Tests">
+ <instrumentation android:targetPackage="com.android.emulator.connectivity.test" android:name="android.test.InstrumentationTestRunner" />
+ <application android:label="Connectivity Test">
+ <uses-library android:name="android.test.runner" />
</application>
-</manifest>
-
+</manifest>
\ No newline at end of file
diff --git a/tools/emulator/test-apps/SmokeTests/src/com/android/emulator/smoketests/connectivity/ConnectivityTest.java b/tools/emulator/test-apps/ConnectivityTest/src/com/android/emulator/connectivity/test/ConnectivityTest.java
similarity index 97%
rename from tools/emulator/test-apps/SmokeTests/src/com/android/emulator/smoketests/connectivity/ConnectivityTest.java
rename to tools/emulator/test-apps/ConnectivityTest/src/com/android/emulator/connectivity/test/ConnectivityTest.java
index 9fe1ebe..9931eb8 100644
--- a/tools/emulator/test-apps/SmokeTests/src/com/android/emulator/smoketests/connectivity/ConnectivityTest.java
+++ b/tools/emulator/test-apps/ConnectivityTest/src/com/android/emulator/connectivity/test/ConnectivityTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.emulator.smoketests.connectivity;
+package com.android.emulator.connectivity.test;
import java.io.IOException;
import java.net.URL;
diff --git a/tools/emulator/test-apps/SmokeTests/Android.mk b/tools/emulator/test-apps/GpsLocationTest/Android.mk
similarity index 80%
rename from tools/emulator/test-apps/SmokeTests/Android.mk
rename to tools/emulator/test-apps/GpsLocationTest/Android.mk
index 41951dd..5f90f3a 100644
--- a/tools/emulator/test-apps/SmokeTests/Android.mk
+++ b/tools/emulator/test-apps/GpsLocationTest/Android.mk
@@ -1,4 +1,4 @@
-# Copyright (C) 2014 The Android Open Source Project
+# Copyright (C) 2011 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.
@@ -15,18 +15,18 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_STATIC_JAVA_LIBRARIES := android-test-lib
-
LOCAL_MODULE_TAGS := optional
# Only compile source java files in this apk.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_PACKAGE_NAME := EmulatorSmokeTests
+LOCAL_PACKAGE_NAME := GpsLocationTest
LOCAL_SDK_VERSION := 4
LOCAL_PROGUARD_ENABLED := disabled
-
include $(BUILD_PACKAGE)
+
+# Use the following include to make our test apk.
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tools/emulator/test-apps/SmokeTests/AndroidManifest.xml b/tools/emulator/test-apps/GpsLocationTest/AndroidManifest.xml
similarity index 65%
copy from tools/emulator/test-apps/SmokeTests/AndroidManifest.xml
copy to tools/emulator/test-apps/GpsLocationTest/AndroidManifest.xml
index 7066ca6..901855e 100644
--- a/tools/emulator/test-apps/SmokeTests/AndroidManifest.xml
+++ b/tools/emulator/test-apps/GpsLocationTest/AndroidManifest.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2011 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.
@@ -14,15 +14,14 @@
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.emulator.smoketests">
+ package="com.android.emulator.gps.test"
+ android:versionCode="1"
+ android:versionName="1.0">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
- <uses-permission android:name="android.permission.INTERNET" />
- <uses-permission android:name="android.permission.READ_SMS" />
<uses-sdk android:minSdkVersion="4" />
- <instrumentation android:targetPackage="com.android.emulator.smoketests"
- android:name="com.android.test.runner.AndroidJUnitRunner" />
- <application android:label="Emulator Smoke Tests">
+ <instrumentation android:targetPackage="com.android.emulator.gps.test"
+ android:name="android.test.InstrumentationTestRunner" />
+ <application android:label="GPS Location Test">
+ <uses-library android:name="android.test.runner" />
</application>
-</manifest>
-
+</manifest>
\ No newline at end of file
diff --git a/tools/emulator/test-apps/SmokeTests/src/com/android/emulator/smoketests/gps/GpsLocationTest.java b/tools/emulator/test-apps/GpsLocationTest/src/com/android/emulator/gps/test/GpsLocationTest.java
similarity index 98%
rename from tools/emulator/test-apps/SmokeTests/src/com/android/emulator/smoketests/gps/GpsLocationTest.java
rename to tools/emulator/test-apps/GpsLocationTest/src/com/android/emulator/gps/test/GpsLocationTest.java
index 1e0258c..6eb3834 100644
--- a/tools/emulator/test-apps/SmokeTests/src/com/android/emulator/smoketests/gps/GpsLocationTest.java
+++ b/tools/emulator/test-apps/GpsLocationTest/src/com/android/emulator/gps/test/GpsLocationTest.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.emulator.smoketests.gps;
+package com.android.emulator.gps.test;
import android.content.Context;
import android.location.Location;
diff --git a/tools/emulator/test-apps/SmokeTests/src/com/android/emulator/smoketests/sms/SmsTest.java b/tools/emulator/test-apps/SmokeTests/src/com/android/emulator/smoketests/sms/SmsTest.java
deleted file mode 100644
index bb1ce20..0000000
--- a/tools/emulator/test-apps/SmokeTests/src/com/android/emulator/smoketests/sms/SmsTest.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 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.android.emulator.smoketests.sms;
-
-import android.content.Context;
-import android.content.ContentResolver;
-import android.net.Uri;
-import android.database.Cursor;
-import android.os.Bundle;
-import android.os.HandlerThread;
-import com.android.test.InjectContext;
-
-import org.junit.Assert;
-import static junit.framework.Assert.assertEquals;
-
-import org.junit.Test;
-/**
- * Sms Test
- *
- * Test that an SMS message has been received
- */
-public class SmsTest {
-
- /**
- * Prior to running this test an sms must be sent
- * via DDMS
- */
- public final static String NUMBER = "5551212";
- public final static String BODY = "test sms";
- private final static int SMS_POLL_TIME_MS = 10 * 1000;
- private final static int SIXY_SECONDS_OF_LOOPS = 6;
- @InjectContext
- public Context mContext;
-
- /**
- * Verify that an SMS has been received with the correct number and body
- */
- @Test
- public void testReceivedSms() throws java.lang.InterruptedException {
- Cursor c = getSmsCursor();
- c.moveToFirst();
-
- String number = c.getString(c.getColumnIndexOrThrow("address"));
- String body = c.getString(c.getColumnIndexOrThrow("body"));
-
- c.close();
-
- assertEquals(NUMBER, number);
- assertEquals(BODY, body);
- }
-
- private Cursor getSmsCursor() throws java.lang.InterruptedException {
- ContentResolver r = mContext.getContentResolver();
- Uri message = Uri.parse("content://sms/");
- Cursor c;
-
- for(int i = 0; i < SIXY_SECONDS_OF_LOOPS; i++) {
- c = r.query(message,null,null,null,null);
-
- if(c.getCount() != 0) {
- return c;
- }
-
- c.close();
- Thread.sleep(SMS_POLL_TIME_MS);
- }
- Assert.fail("Did not find any SMS messages. Giving up");
- // necessary for compilation
- return null;
- }
-
-}