diff options
370 files changed, 15189 insertions, 225 deletions
diff --git a/build/Android.mk b/build/Android.mk index f8578d289..117e3e0ef 100644 --- a/build/Android.mk +++ b/build/Android.mk @@ -139,11 +139,14 @@ $(eval _psm_packaging_target :=) 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 91442becf..dbc8a0c60 100644 --- a/build/sdk.atree +++ b/build/sdk.atree @@ -170,8 +170,7 @@ docs/widgets.txt platforms/${PLATFORM_NAME}/data/widget 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/BatchStepSensor sam 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_source.properties 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 @@ development/samples/Support7Demos # 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 0c655cef8..0b21bb27c 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 895e633d4..472667089 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 0e43e3d44..ca8310fea 100644 --- a/samples/Support7Demos/Android.mk +++ b/samples/Support7Demos/Android.mk @@ -26,7 +26,8 @@ LOCAL_STATIC_JAVA_LIBRARIES := \ 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 4735433c5..6f9b2373e 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 000000000..d671c7356 --- /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 000000000..188a1548b --- /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 000000000..65a23ccc4 --- /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 1b136233f..7e4e03c1a 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 000000000..a66b1d69d --- /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 000000000..83cf4d3b0 --- /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 000000000..8c2caa9ee --- /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 000000000..baecf86a3 --- /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 000000000..a12e79d26 --- /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 000000000..4d5d2083a --- /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 000000000..41424a709 --- /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 000000000..ee0707d19 --- /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 Binary files differnew file mode 100644 index 000000000..96a442e5b --- /dev/null +++ b/samples/SupportLeanbackDemos/res/drawable-hdpi/ic_launcher.png diff --git a/samples/SupportLeanbackDemos/res/drawable-ldpi/ic_launcher.png b/samples/SupportLeanbackDemos/res/drawable-ldpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..99238729d --- /dev/null +++ b/samples/SupportLeanbackDemos/res/drawable-ldpi/ic_launcher.png diff --git a/samples/SupportLeanbackDemos/res/drawable-mdpi/ic_launcher.png b/samples/SupportLeanbackDemos/res/drawable-mdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..359047dfa --- /dev/null +++ b/samples/SupportLeanbackDemos/res/drawable-mdpi/ic_launcher.png diff --git a/samples/SupportLeanbackDemos/res/drawable-xhdpi/grid_bg.png b/samples/SupportLeanbackDemos/res/drawable-xhdpi/grid_bg.png Binary files differnew file mode 100644 index 000000000..476c698ec --- /dev/null +++ b/samples/SupportLeanbackDemos/res/drawable-xhdpi/grid_bg.png diff --git a/samples/SupportLeanbackDemos/res/drawable-xhdpi/ic_launcher.png b/samples/SupportLeanbackDemos/res/drawable-xhdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..71c6d760f --- /dev/null +++ b/samples/SupportLeanbackDemos/res/drawable-xhdpi/ic_launcher.png diff --git a/samples/SupportLeanbackDemos/res/drawable/details_img.png b/samples/SupportLeanbackDemos/res/drawable/details_img.png Binary files differnew file mode 100644 index 000000000..7ea688b64 --- /dev/null +++ b/samples/SupportLeanbackDemos/res/drawable/details_img.png diff --git a/samples/SupportLeanbackDemos/res/drawable/ic_action_a.png b/samples/SupportLeanbackDemos/res/drawable/ic_action_a.png Binary files differnew file mode 100644 index 000000000..3d555efa5 --- /dev/null +++ b/samples/SupportLeanbackDemos/res/drawable/ic_action_a.png diff --git a/samples/SupportLeanbackDemos/res/drawable/ic_title.png b/samples/SupportLeanbackDemos/res/drawable/ic_title.png Binary files differnew file mode 100644 index 000000000..1c62b2e18 --- /dev/null +++ b/samples/SupportLeanbackDemos/res/drawable/ic_title.png diff --git a/samples/SupportLeanbackDemos/res/drawable/text_bg.xml b/samples/SupportLeanbackDemos/res/drawable/text_bg.xml new file mode 100644 index 000000000..c67924c5b --- /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 000000000..4af4e6a1e --- /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 000000000..b6b08b3b5 --- /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 000000000..b65600ca5 --- /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 000000000..1007042c4 --- /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 000000000..e8840436b --- /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 000000000..2345ed09b --- /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 000000000..502c77aea --- /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 000000000..082b134f5 --- /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 000000000..6d376f0aa --- /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 000000000..c9a85f39f --- /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 000000000..74e7fb216 --- /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 000000000..437bd7267 --- /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 000000000..0489196b0 --- /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 000000000..5c80e0be4 --- /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 000000000..c5262b99d --- /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 000000000..495bebeb5 --- /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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 2a51b1133..10057b8e7 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 @@ limitations under the License. <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 000000000..8c1ea66f2 --- /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 63fc81644..000000000 --- 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 353c67e0a..ee0c4bd59 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 a0171a705..000000000 --- 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 404623e3d..6e7d593dd 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 525ed4035..a9498189e 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.AbsListView; 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 @@ public class AdapterTransitionFragment extends Fragment implements Transition.Tr 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 @@ public class AdapterTransitionFragment extends Fragment implements Transition.Tr } @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 @@ public class AdapterTransitionFragment extends Fragment implements Transition.Tr 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 @@ public class AdapterTransitionFragment extends Fragment implements Transition.Tr } /** + * 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 @@ public class AdapterTransitionFragment extends Fragment implements Transition.Tr // 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 c7630cedf..dea443584 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 @@ public class MeatAdapter extends BaseAdapter { 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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 000000000..8c1ea66f2 --- /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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 000000000..653454bb2 --- /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 000000000..f6f41579c --- /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 bc5a57591..6f41369cf 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 03d197418..b6ea1a086 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 000000000..8c1ea66f2 --- /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 154780760..de4a39f82 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 @@ public class MainActivity extends SampleActivityBase { 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 000000000..653454bb2 --- /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 000000000..f6f41579c --- /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 bc5a57591..6f41369cf 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 03d197418..b6ea1a086 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 000000000..8c1ea66f2 --- /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 83e8f0eca..0c1bcefed 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 @@ public class MainActivity extends SampleActivityBase { 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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 000000000..cf043d141 --- /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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 06246dab2..a4cac0f9a 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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 b8a123e2b..63f129787 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 24bffebf2..5deb6f5bb 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 bf66150d1..7ca967720 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 7f759fc7a..da7444870 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 2011f9c04..afbda8acf 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 463af5c55..a6b917bc0 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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 aab0fc388..467c427aa 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.os.Bundle; 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 bb1f9a168..5e4f7e3e7 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 android.view.Menu; 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 index fb885c7d6..a3723e80c 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.Button; 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 index ea37e6601..01c7094fb 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 index 821527505..ce20f7f36 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 index 5de985223..70cc5dd41 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 index a22ddd7d4..de06cf658 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 index 9f8b7cb4f..5388cd9ce 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.HashMap; 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 index aeab77080..5e4ba158a 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.LinearLayout; 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 index 08432a9a5..57ba177ab 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 index 19ef43bb9..21e54d3a0 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 index f02411057..90ba21e03 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 index 7cd7f2baa..51d5428a3 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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 000000000..b3328f19a --- /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 000000000..c68a76201 --- /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 Binary files differnew file mode 100644 index 000000000..846a7feb9 --- /dev/null +++ b/samples/browseable/CustomTransition/res/drawable-hdpi/ic_launcher.png diff --git a/samples/browseable/CustomTransition/res/drawable-hdpi/tile.9.png b/samples/browseable/CustomTransition/res/drawable-hdpi/tile.9.png Binary files differnew file mode 100644 index 000000000..135862883 --- /dev/null +++ b/samples/browseable/CustomTransition/res/drawable-hdpi/tile.9.png diff --git a/samples/browseable/CustomTransition/res/drawable-mdpi/ic_launcher.png b/samples/browseable/CustomTransition/res/drawable-mdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..7a21d0699 --- /dev/null +++ b/samples/browseable/CustomTransition/res/drawable-mdpi/ic_launcher.png diff --git a/samples/browseable/CustomTransition/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/CustomTransition/res/drawable-xhdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..71734d736 --- /dev/null +++ b/samples/browseable/CustomTransition/res/drawable-xhdpi/ic_launcher.png diff --git a/samples/browseable/CustomTransition/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/CustomTransition/res/drawable-xxhdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..d6d9b26f7 --- /dev/null +++ b/samples/browseable/CustomTransition/res/drawable-xxhdpi/ic_launcher.png 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 000000000..c9a52f621 --- /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 000000000..1ae4f981e --- /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 000000000..c48f2701a --- /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 000000000..e686ff73a --- /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 000000000..e37e8b030 --- /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 000000000..e95fc3c50 --- /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 000000000..b49c2c526 --- /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 000000000..22074a2bd --- /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 000000000..03d197418 --- /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 000000000..8c1ea66f2 --- /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 000000000..68c9c4146 --- /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 000000000..7b9d9ec4f --- /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 000000000..39e710b5c --- /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 000000000..6e7d593dd --- /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 000000000..3228927b7 --- /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 000000000..17503c568 --- /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 000000000..b302acd4b --- /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 000000000..bc37cabc0 --- /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 000000000..c01542b91 --- /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 000000000..16a9e7ba2 --- /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 000000000..19967dcd4 --- /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 000000000..d36cfb40c --- /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 000000000..8ef695aa5 --- /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 000000000..04c4e4d9b --- /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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 000000000..8c1ea66f2 --- /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 000000000..8d02eb0a4 --- /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 000000000..f0efe32fd --- /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 Binary files differnew file mode 100644 index 000000000..dfa1b4580 --- /dev/null +++ b/samples/browseable/FragmentTransition/res/drawable-hdpi/ic_launcher.png diff --git a/samples/browseable/FragmentTransition/res/drawable-hdpi/tile.9.png b/samples/browseable/FragmentTransition/res/drawable-hdpi/tile.9.png Binary files differnew file mode 100644 index 000000000..135862883 --- /dev/null +++ b/samples/browseable/FragmentTransition/res/drawable-hdpi/tile.9.png diff --git a/samples/browseable/FragmentTransition/res/drawable-mdpi/ic_launcher.png b/samples/browseable/FragmentTransition/res/drawable-mdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..5f4ae7b56 --- /dev/null +++ b/samples/browseable/FragmentTransition/res/drawable-mdpi/ic_launcher.png diff --git a/samples/browseable/FragmentTransition/res/drawable-nodpi/p1.jpg b/samples/browseable/FragmentTransition/res/drawable-nodpi/p1.jpg Binary files differnew file mode 100644 index 000000000..10f07acf1 --- /dev/null +++ b/samples/browseable/FragmentTransition/res/drawable-nodpi/p1.jpg diff --git a/samples/browseable/FragmentTransition/res/drawable-nodpi/p10.jpg b/samples/browseable/FragmentTransition/res/drawable-nodpi/p10.jpg Binary files differnew file mode 100644 index 000000000..4272f4cc0 --- /dev/null +++ b/samples/browseable/FragmentTransition/res/drawable-nodpi/p10.jpg diff --git a/samples/browseable/FragmentTransition/res/drawable-nodpi/p11.jpg b/samples/browseable/FragmentTransition/res/drawable-nodpi/p11.jpg Binary files differnew file mode 100644 index 000000000..c5722b229 --- /dev/null +++ b/samples/browseable/FragmentTransition/res/drawable-nodpi/p11.jpg diff --git a/samples/browseable/FragmentTransition/res/drawable-nodpi/p2.jpg b/samples/browseable/FragmentTransition/res/drawable-nodpi/p2.jpg Binary files differnew file mode 100644 index 000000000..ca380ae4e --- /dev/null +++ b/samples/browseable/FragmentTransition/res/drawable-nodpi/p2.jpg diff --git a/samples/browseable/FragmentTransition/res/drawable-nodpi/p3.jpg b/samples/browseable/FragmentTransition/res/drawable-nodpi/p3.jpg Binary files differnew file mode 100644 index 000000000..6fc71e765 --- /dev/null +++ b/samples/browseable/FragmentTransition/res/drawable-nodpi/p3.jpg diff --git a/samples/browseable/FragmentTransition/res/drawable-nodpi/p4.jpg b/samples/browseable/FragmentTransition/res/drawable-nodpi/p4.jpg Binary files differnew file mode 100644 index 000000000..153c1ffe8 --- /dev/null +++ b/samples/browseable/FragmentTransition/res/drawable-nodpi/p4.jpg diff --git a/samples/browseable/FragmentTransition/res/drawable-nodpi/p5.jpg b/samples/browseable/FragmentTransition/res/drawable-nodpi/p5.jpg Binary files differnew file mode 100644 index 000000000..46d6a13df --- /dev/null +++ b/samples/browseable/FragmentTransition/res/drawable-nodpi/p5.jpg diff --git a/samples/browseable/FragmentTransition/res/drawable-nodpi/p6.jpg b/samples/browseable/FragmentTransition/res/drawable-nodpi/p6.jpg Binary files differnew file mode 100644 index 000000000..89ccb8329 --- /dev/null +++ b/samples/browseable/FragmentTransition/res/drawable-nodpi/p6.jpg diff --git a/samples/browseable/FragmentTransition/res/drawable-nodpi/p7.jpg b/samples/browseable/FragmentTransition/res/drawable-nodpi/p7.jpg Binary files differnew file mode 100644 index 000000000..7e9546dde --- /dev/null +++ b/samples/browseable/FragmentTransition/res/drawable-nodpi/p7.jpg diff --git a/samples/browseable/FragmentTransition/res/drawable-nodpi/p8.jpg b/samples/browseable/FragmentTransition/res/drawable-nodpi/p8.jpg Binary files differnew file mode 100644 index 000000000..21e25ba17 --- /dev/null +++ b/samples/browseable/FragmentTransition/res/drawable-nodpi/p8.jpg diff --git a/samples/browseable/FragmentTransition/res/drawable-nodpi/p9.jpg b/samples/browseable/FragmentTransition/res/drawable-nodpi/p9.jpg Binary files differnew file mode 100644 index 000000000..79854cb64 --- /dev/null +++ b/samples/browseable/FragmentTransition/res/drawable-nodpi/p9.jpg diff --git a/samples/browseable/FragmentTransition/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/FragmentTransition/res/drawable-xhdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..5e00f33f8 --- /dev/null +++ b/samples/browseable/FragmentTransition/res/drawable-xhdpi/ic_launcher.png diff --git a/samples/browseable/FragmentTransition/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/FragmentTransition/res/drawable-xxhdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..e061498e0 --- /dev/null +++ b/samples/browseable/FragmentTransition/res/drawable-xxhdpi/ic_launcher.png 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 000000000..c9a52f621 --- /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 000000000..1ae4f981e --- /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 000000000..d94256f03 --- /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 000000000..206846005 --- /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 000000000..6e1c7a1d2 --- /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 000000000..df34883d2 --- /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 000000000..b49c2c526 --- /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 000000000..22074a2bd --- /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 000000000..03d197418 --- /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 000000000..8c1ea66f2 --- /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 000000000..933e1f28e --- /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 000000000..7b9d9ec4f --- /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 000000000..39e710b5c --- /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 000000000..6e7d593dd --- /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 000000000..3228927b7 --- /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 000000000..17503c568 --- /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 000000000..b302acd4b --- /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 000000000..bc37cabc0 --- /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 000000000..c01542b91 --- /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 000000000..16a9e7ba2 --- /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 000000000..19967dcd4 --- /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 000000000..20049e335 --- /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 000000000..d5bbbae59 --- /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 000000000..81e7b46d3 --- /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 000000000..c072eb997 --- /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 000000000..7d6ca6f4d --- /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 000000000..2f2fdfa44 --- /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 000000000..307fd85fa --- /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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 000000000..653454bb2 --- /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 000000000..f6f41579c --- /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 bc5a57591..6f41369cf 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 03d197418..b6ea1a086 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 000000000..8c1ea66f2 --- /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 fd0211275..8fb6e345c 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 @@ public class MainActivity extends SampleActivityBase { 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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 000000000..653454bb2 --- /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 000000000..f6f41579c --- /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 bc5a57591..6f41369cf 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 03d197418..b6ea1a086 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 000000000..8c1ea66f2 --- /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 2d2a6aaad..147f5761a 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 @@ public class MainActivity extends SampleActivityBase { 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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 000000000..653454bb2 --- /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 000000000..f6f41579c --- /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 bc5a57591..6f41369cf 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 03d197418..b6ea1a086 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 000000000..8c1ea66f2 --- /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 69c75eb9c..106f26b6f 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 @@ public class MainActivity extends SampleActivityBase { 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 000000000..653454bb2 --- /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 000000000..f6f41579c --- /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 bc5a57591..6f41369cf 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 03d197418..b6ea1a086 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 000000000..8c1ea66f2 --- /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 5f04a62b9..3108c1f50 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 @@ public class MainActivity extends SampleActivityBase { 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 000000000..fa754537a --- /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 000000000..bfbaddbbb --- /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 Binary files differnew file mode 100644 index 000000000..da15ae2b9 --- /dev/null +++ b/samples/browseable/SwipeRefreshLayoutBasic/res/drawable-hdpi/ic_launcher.png diff --git a/samples/browseable/SwipeRefreshLayoutBasic/res/drawable-hdpi/tile.9.png b/samples/browseable/SwipeRefreshLayoutBasic/res/drawable-hdpi/tile.9.png Binary files differnew file mode 100644 index 000000000..135862883 --- /dev/null +++ b/samples/browseable/SwipeRefreshLayoutBasic/res/drawable-hdpi/tile.9.png diff --git a/samples/browseable/SwipeRefreshLayoutBasic/res/drawable-mdpi/ic_launcher.png b/samples/browseable/SwipeRefreshLayoutBasic/res/drawable-mdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..34c3f1ca6 --- /dev/null +++ b/samples/browseable/SwipeRefreshLayoutBasic/res/drawable-mdpi/ic_launcher.png diff --git a/samples/browseable/SwipeRefreshLayoutBasic/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/SwipeRefreshLayoutBasic/res/drawable-xhdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..83ac28610 --- /dev/null +++ b/samples/browseable/SwipeRefreshLayoutBasic/res/drawable-xhdpi/ic_launcher.png diff --git a/samples/browseable/SwipeRefreshLayoutBasic/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/SwipeRefreshLayoutBasic/res/drawable-xxhdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..02802a3e4 --- /dev/null +++ b/samples/browseable/SwipeRefreshLayoutBasic/res/drawable-xxhdpi/ic_launcher.png 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 000000000..c9a52f621 --- /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 000000000..1ae4f981e --- /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 000000000..8900f82ac --- /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 000000000..b49c2c526 --- /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 000000000..de0c5f2f7 --- /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 000000000..22074a2bd --- /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 000000000..03d197418 --- /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 000000000..8c1ea66f2 --- /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 000000000..665d16fed --- /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 000000000..ae1119e57 --- /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 000000000..7b9d9ec4f --- /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 000000000..39e710b5c --- /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 000000000..6e7d593dd --- /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 000000000..3228927b7 --- /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 000000000..783735ce3 --- /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 000000000..17503c568 --- /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 000000000..b302acd4b --- /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 000000000..bc37cabc0 --- /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 000000000..c01542b91 --- /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 000000000..16a9e7ba2 --- /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 000000000..19967dcd4 --- /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 000000000..20049e335 --- /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 000000000..d5bbbae59 --- /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 000000000..f90aed1fc --- /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 000000000..13b22f5ca --- /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 000000000..be449304e --- /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 000000000..3a34bb032 --- /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 Binary files differnew file mode 100644 index 000000000..b10c5c1b6 --- /dev/null +++ b/samples/browseable/SwipeRefreshListFragment/res/drawable-hdpi/ic_launcher.png diff --git a/samples/browseable/SwipeRefreshListFragment/res/drawable-hdpi/tile.9.png b/samples/browseable/SwipeRefreshListFragment/res/drawable-hdpi/tile.9.png Binary files differnew file mode 100644 index 000000000..135862883 --- /dev/null +++ b/samples/browseable/SwipeRefreshListFragment/res/drawable-hdpi/tile.9.png diff --git a/samples/browseable/SwipeRefreshListFragment/res/drawable-mdpi/ic_launcher.png b/samples/browseable/SwipeRefreshListFragment/res/drawable-mdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..001eed961 --- /dev/null +++ b/samples/browseable/SwipeRefreshListFragment/res/drawable-mdpi/ic_launcher.png diff --git a/samples/browseable/SwipeRefreshListFragment/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/SwipeRefreshListFragment/res/drawable-xhdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..6fe78cc59 --- /dev/null +++ b/samples/browseable/SwipeRefreshListFragment/res/drawable-xhdpi/ic_launcher.png diff --git a/samples/browseable/SwipeRefreshListFragment/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/SwipeRefreshListFragment/res/drawable-xxhdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..5f8987504 --- /dev/null +++ b/samples/browseable/SwipeRefreshListFragment/res/drawable-xxhdpi/ic_launcher.png 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 000000000..c9a52f621 --- /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 000000000..1ae4f981e --- /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 000000000..b49c2c526 --- /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 000000000..c5e895486 --- /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 000000000..22074a2bd --- /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 000000000..03d197418 --- /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 000000000..8c1ea66f2 --- /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 000000000..f84c807b3 --- /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 000000000..ae1999086 --- /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 000000000..7b9d9ec4f --- /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 000000000..39e710b5c --- /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 000000000..6e7d593dd --- /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 000000000..3228927b7 --- /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 000000000..783735ce3 --- /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 000000000..17503c568 --- /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 000000000..b302acd4b --- /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 000000000..bc37cabc0 --- /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 000000000..c01542b91 --- /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 000000000..16a9e7ba2 --- /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 000000000..19967dcd4 --- /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 000000000..20049e335 --- /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 000000000..d5bbbae59 --- /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 000000000..7f7a7c8f4 --- /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 000000000..57969760d --- /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 000000000..1147ea819 --- /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 000000000..aba15e066 --- /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 000000000..70ff8ea89 --- /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 Binary files differnew file mode 100644 index 000000000..9fbf7ab58 --- /dev/null +++ b/samples/browseable/SwipeRefreshMultipleViews/res/drawable-hdpi/ic_launcher.png diff --git a/samples/browseable/SwipeRefreshMultipleViews/res/drawable-hdpi/tile.9.png b/samples/browseable/SwipeRefreshMultipleViews/res/drawable-hdpi/tile.9.png Binary files differnew file mode 100644 index 000000000..135862883 --- /dev/null +++ b/samples/browseable/SwipeRefreshMultipleViews/res/drawable-hdpi/tile.9.png diff --git a/samples/browseable/SwipeRefreshMultipleViews/res/drawable-mdpi/ic_launcher.png b/samples/browseable/SwipeRefreshMultipleViews/res/drawable-mdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..f83410865 --- /dev/null +++ b/samples/browseable/SwipeRefreshMultipleViews/res/drawable-mdpi/ic_launcher.png diff --git a/samples/browseable/SwipeRefreshMultipleViews/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/SwipeRefreshMultipleViews/res/drawable-xhdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..3197133ee --- /dev/null +++ b/samples/browseable/SwipeRefreshMultipleViews/res/drawable-xhdpi/ic_launcher.png diff --git a/samples/browseable/SwipeRefreshMultipleViews/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/SwipeRefreshMultipleViews/res/drawable-xxhdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..d19455cfd --- /dev/null +++ b/samples/browseable/SwipeRefreshMultipleViews/res/drawable-xxhdpi/ic_launcher.png 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 000000000..c9a52f621 --- /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 000000000..1ae4f981e --- /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 000000000..077f3f13f --- /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 000000000..b49c2c526 --- /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 000000000..d8fa6e6e9 --- /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 000000000..22074a2bd --- /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 000000000..03d197418 --- /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 000000000..8c1ea66f2 --- /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 000000000..d7c1c9eb3 --- /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 000000000..48039b0e6 --- /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 000000000..7b9d9ec4f --- /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 000000000..39e710b5c --- /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 000000000..6e7d593dd --- /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 000000000..3228927b7 --- /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 000000000..783735ce3 --- /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 000000000..17503c568 --- /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 000000000..b302acd4b --- /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 000000000..bc37cabc0 --- /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 000000000..c01542b91 --- /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 000000000..16a9e7ba2 --- /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 000000000..19967dcd4 --- /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 000000000..20049e335 --- /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 000000000..d5bbbae59 --- /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 000000000..0191d87de --- /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 000000000..4e5014554 --- /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 000000000..e2b83d355 --- /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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 000000000..8c1ea66f2 --- /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 404623e3d..6e7d593dd 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 315be08d3..d3cdfd5ee 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 b7a90a575..c37ac0037 100644 --- a/scripts/app_engine_server/redirects.yaml +++ b/scripts/app_engine_server/redirects.yaml @@ -77,6 +77,14 @@ redirects: 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 c9bfc2fe9..5d623074d 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 523d6bda8..d3cdfd5ee 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 b83af7f4b..5d623074d 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 09a2d810d..7ecb1e273 100644 --- a/sdk/platform_source.prop_template +++ b/sdk/platform_source.prop_template @@ -2,7 +2,7 @@ Pkg.Desc=Android SDK Platform ${PLATFORM_VERSION} 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 523d6bda8..d3cdfd5ee 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 f89771291..f5b217eec 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 7d13fcecd..9c7a332a5 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 ef17ea652..91e9d212f 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 d5f561093..1a18cf874 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/ConnectivityTest/Android.mk b/tools/emulator/test-apps/ConnectivityTest/Android.mk new file mode 100644 index 000000000..ca20d574a --- /dev/null +++ b/tools/emulator/test-apps/ConnectivityTest/Android.mk @@ -0,0 +1,32 @@ +# 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. + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +# Only compile source java files in this apk. +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +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 index 7066ca66f..80f65cf80 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 index 9fe1ebe77..9931eb849 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 index 41951ddfd..5f90f3a5b 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/GpsLocationTest/AndroidManifest.xml b/tools/emulator/test-apps/GpsLocationTest/AndroidManifest.xml new file mode 100644 index 000000000..901855e8a --- /dev/null +++ b/tools/emulator/test-apps/GpsLocationTest/AndroidManifest.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.emulator.gps.test" + android:versionCode="1" + android:versionName="1.0"> + <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> + <uses-sdk android:minSdkVersion="4" /> + <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>
\ 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 index 1e0258c29..6eb38349a 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 bb1ce2087..000000000 --- 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; - } - -} |