diff options
author | Tom Taylor <tomtaylor@google.com> | 2013-06-17 15:40:51 -0700 |
---|---|---|
committer | Tom Taylor <tomtaylor@google.com> | 2013-06-17 15:40:51 -0700 |
commit | 7064b96091b83ef79810aa58e898c5d731f575e7 (patch) | |
tree | b94a9dea6edec0a8f3f8f935c899415dd5060e46 /actionbarsherlock-samples/fragments/src | |
parent | 21c7a6546d24bedeab8f1491cf90e2c4c2862cf9 (diff) | |
download | actionbarsherlock-7064b96091b83ef79810aa58e898c5d731f575e7.tar.gz |
Replace ActionBarSherlock version 4.2.0 with 4.3.1
Change-Id: Ib385b4a6b60a0fee65af55e3c6cd590747256bc1
Diffstat (limited to 'actionbarsherlock-samples/fragments/src')
25 files changed, 4158 insertions, 0 deletions
diff --git a/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/CheckableFrameLayout.java b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/CheckableFrameLayout.java new file mode 100755 index 0000000..cb6b7a4 --- /dev/null +++ b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/CheckableFrameLayout.java @@ -0,0 +1,49 @@ +/* + * 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.actionbarsherlock.sample.fragments; + +import android.content.Context; +import android.graphics.drawable.ColorDrawable; +import android.util.AttributeSet; +import android.widget.Checkable; +import android.widget.FrameLayout; + +public class CheckableFrameLayout extends FrameLayout implements Checkable { + private boolean mChecked; + + public CheckableFrameLayout(Context context) { + super(context); + } + + public CheckableFrameLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public void setChecked(boolean checked) { + mChecked = checked; + setBackgroundDrawable(checked ? new ColorDrawable(0xff0000a0) : null); + } + + public boolean isChecked() { + return mChecked; + } + + public void toggle() { + setChecked(!mChecked); + } + +} diff --git a/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/Cheeses.java b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/Cheeses.java new file mode 100755 index 0000000..cc288bc --- /dev/null +++ b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/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.actionbarsherlock.sample.fragments; + +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/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentAlertDialogSupport.java b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentAlertDialogSupport.java new file mode 100755 index 0000000..6c6abef --- /dev/null +++ b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentAlertDialogSupport.java @@ -0,0 +1,109 @@ +/* + * 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.actionbarsherlock.sample.fragments; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.util.Log; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.TextView; +import com.actionbarsherlock.app.SherlockDialogFragment; +import com.actionbarsherlock.app.SherlockFragmentActivity; + +/** + * Demonstrates how to show an AlertDialog that is managed by a Fragment. + */ +public class FragmentAlertDialogSupport extends SherlockFragmentActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + setTheme(SampleList.THEME); //Used for theme switching in samples + super.onCreate(savedInstanceState); + setContentView(R.layout.fragment_dialog); + + View tv = findViewById(R.id.text); + ((TextView)tv).setText("Example of displaying an alert dialog with a DialogFragment"); + + // Watch for button clicks. + Button button = (Button)findViewById(R.id.show); + button.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + showDialog(); + } + }); + } + + + void showDialog() { + DialogFragment newFragment = MyAlertDialogFragment.newInstance( + R.string.alert_dialog_two_buttons_title); + newFragment.show(getSupportFragmentManager(), "dialog"); + } + + public void doPositiveClick() { + // Do stuff here. + Log.i("FragmentAlertDialog", "Positive click!"); + } + + public void doNegativeClick() { + // Do stuff here. + Log.i("FragmentAlertDialog", "Negative click!"); + } + + + + public static class MyAlertDialogFragment extends SherlockDialogFragment { + + public static MyAlertDialogFragment newInstance(int title) { + MyAlertDialogFragment frag = new MyAlertDialogFragment(); + Bundle args = new Bundle(); + args.putInt("title", title); + frag.setArguments(args); + return frag; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + int title = getArguments().getInt("title"); + + return new AlertDialog.Builder(getActivity()) + .setIcon(R.drawable.alert_dialog_icon) + .setTitle(title) + .setPositiveButton(R.string.alert_dialog_ok, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + ((FragmentAlertDialogSupport)getActivity()).doPositiveClick(); + } + } + ) + .setNegativeButton(R.string.alert_dialog_cancel, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + ((FragmentAlertDialogSupport)getActivity()).doNegativeClick(); + } + } + ) + .create(); + } + } + +} diff --git a/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentArgumentsSupport.java b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentArgumentsSupport.java new file mode 100755 index 0000000..3310e0b --- /dev/null +++ b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentArgumentsSupport.java @@ -0,0 +1,112 @@ +/* + * 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.actionbarsherlock.sample.fragments; + +import android.app.Activity; +import android.content.res.TypedArray; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentTransaction; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; +import com.actionbarsherlock.app.SherlockFragment; +import com.actionbarsherlock.app.SherlockFragmentActivity; + +/** + * Demonstrates a fragment that can be configured through both Bundle arguments + * and layout attributes. + */ +public class FragmentArgumentsSupport extends SherlockFragmentActivity { + + @Override protected void onCreate(Bundle savedInstanceState) { + setTheme(SampleList.THEME); //Used for theme switching in samples + super.onCreate(savedInstanceState); + setContentView(R.layout.fragment_arguments_support); + + if (savedInstanceState == null) { + // First-time init; create fragment to embed in activity. + FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); + Fragment newFragment = MyFragment.newInstance("From Arguments"); + ft.add(R.id.created, newFragment); + ft.commit(); + } + } + + + + public static class MyFragment extends SherlockFragment { + CharSequence mLabel; + + /** + * Create a new instance of MyFragment that will be initialized + * with the given arguments. + */ + static MyFragment newInstance(CharSequence label) { + MyFragment f = new MyFragment(); + Bundle b = new Bundle(); + b.putCharSequence("label", label); + f.setArguments(b); + return f; + } + + /** + * Parse attributes during inflation from a view hierarchy into the + * arguments we handle. + */ + @Override public void onInflate(Activity activity, AttributeSet attrs, + Bundle savedInstanceState) { + super.onInflate(activity, attrs, savedInstanceState); + + TypedArray a = activity.obtainStyledAttributes(attrs, + R.styleable.FragmentArguments); + mLabel = a.getText(R.styleable.FragmentArguments_android_label); + a.recycle(); + } + + /** + * During creation, if arguments have been supplied to the fragment + * then parse those out. + */ + @Override public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Bundle args = getArguments(); + if (args != null) { + CharSequence label = args.getCharSequence("label"); + if (label != null) { + mLabel = label; + } + } + } + + /** + * Create the view for this fragment, using the arguments given to it. + */ + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.hello_world, container, false); + View tv = v.findViewById(R.id.text); + ((TextView)tv).setText(mLabel != null ? mLabel : "(no label)"); + tv.setBackgroundDrawable(getResources().getDrawable(android.R.drawable.gallery_thumb)); + return v; + } + } + +} diff --git a/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentContextMenuSupport.java b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentContextMenuSupport.java new file mode 100755 index 0000000..a01e8bd --- /dev/null +++ b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentContextMenuSupport.java @@ -0,0 +1,77 @@ +/* + * 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.actionbarsherlock.sample.fragments; + +import android.os.Bundle; +import android.util.Log; +import android.view.ContextMenu; +import android.view.ContextMenu.ContextMenuInfo; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import com.actionbarsherlock.app.SherlockFragment; +import com.actionbarsherlock.app.SherlockFragmentActivity; + +/** + * Demonstration of displaying a context menu from a fragment. + */ +public class FragmentContextMenuSupport extends SherlockFragmentActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + setTheme(SampleList.THEME); //Used for theme switching in samples + super.onCreate(savedInstanceState); + + // Create the list fragment and add it as our sole content. + ContextMenuFragment content = new ContextMenuFragment(); + getSupportFragmentManager().beginTransaction().add( + android.R.id.content, content).commit(); + } + + public static class ContextMenuFragment extends SherlockFragment { + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View root = inflater.inflate(R.layout.fragment_context_menu, container, false); + registerForContextMenu(root.findViewById(R.id.long_press)); + return root; + } + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { + super.onCreateContextMenu(menu, v, menuInfo); + menu.add(Menu.NONE, R.id.a_item, Menu.NONE, "Menu A"); + menu.add(Menu.NONE, R.id.b_item, Menu.NONE, "Menu B"); + } + + @Override + public boolean onContextItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.a_item: + Log.i("ContextMenu", "Item 1a was chosen"); + return true; + case R.id.b_item: + Log.i("ContextMenu", "Item 1b was chosen"); + return true; + } + return super.onContextItemSelected(item); + } + } +} diff --git a/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentCustomAnimationSupport.java b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentCustomAnimationSupport.java new file mode 100755 index 0000000..125103a --- /dev/null +++ b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentCustomAnimationSupport.java @@ -0,0 +1,127 @@ +/* + * 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.actionbarsherlock.sample.fragments; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentTransaction; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; +import com.actionbarsherlock.app.SherlockFragment; +import com.actionbarsherlock.app.SherlockFragmentActivity; + +public class FragmentCustomAnimationSupport extends SherlockFragmentActivity { + int mStackLevel = 1; + + @Override + protected void onCreate(Bundle savedInstanceState) { + setTheme(SampleList.THEME); //Used for theme switching in samples + super.onCreate(savedInstanceState); + setContentView(R.layout.fragment_stack); + + // Watch for button clicks. + Button button = (Button)findViewById(R.id.new_fragment); + button.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + addFragmentToStack(); + } + }); + + if (savedInstanceState == null) { + // Do first time initialization -- add initial fragment. + Fragment newFragment = CountingFragment.newInstance(mStackLevel); + FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); + ft.add(R.id.simple_fragment, newFragment).commit(); + } else { + mStackLevel = savedInstanceState.getInt("level"); + } + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putInt("level", mStackLevel); + } + + + void addFragmentToStack() { + mStackLevel++; + + // Instantiate a new fragment. + Fragment newFragment = CountingFragment.newInstance(mStackLevel); + + // Add the fragment to the activity, pushing this transaction + // on to the back stack. + FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); + ft.setCustomAnimations(R.anim.fragment_slide_left_enter, + R.anim.fragment_slide_left_exit, + R.anim.fragment_slide_right_enter, + R.anim.fragment_slide_right_exit); + ft.replace(R.id.simple_fragment, newFragment); + ft.addToBackStack(null); + ft.commit(); + } + + + + public static class CountingFragment extends SherlockFragment { + int mNum; + + /** + * Create a new instance of CountingFragment, providing "num" + * as an argument. + */ + static CountingFragment newInstance(int num) { + CountingFragment f = new CountingFragment(); + + // Supply num input as an argument. + Bundle args = new Bundle(); + args.putInt("num", num); + f.setArguments(args); + + return f; + } + + /** + * When creating, retrieve this instance's number from its arguments. + */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mNum = getArguments() != null ? getArguments().getInt("num") : 1; + } + + /** + * The Fragment's UI is just a simple text view showing its + * instance number. + */ + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.hello_world, container, false); + View tv = v.findViewById(R.id.text); + ((TextView)tv).setText("Fragment #" + mNum); + tv.setBackgroundDrawable(getResources().getDrawable(android.R.drawable.gallery_thumb)); + return v; + } + } + +} diff --git a/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentDialogOrActivitySupport.java b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentDialogOrActivitySupport.java new file mode 100755 index 0000000..718fc20 --- /dev/null +++ b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentDialogOrActivitySupport.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.actionbarsherlock.sample.fragments; + +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.FragmentTransaction; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; +import com.actionbarsherlock.app.SherlockDialogFragment; +import com.actionbarsherlock.app.SherlockFragmentActivity; + +public class FragmentDialogOrActivitySupport extends SherlockFragmentActivity { + @Override + protected void onCreate(Bundle savedInstanceState) { + setTheme(SampleList.THEME); //Used for theme switching in samples + super.onCreate(savedInstanceState); + setContentView(R.layout.fragment_dialog_or_activity); + + if (savedInstanceState == null) { + // First-time init; create fragment to embed in activity. + + FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); + DialogFragment newFragment = MyDialogFragment.newInstance(); + ft.add(R.id.embedded, newFragment); + ft.commit(); + + } + + // Watch for button clicks. + Button button = (Button)findViewById(R.id.show_dialog); + button.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + showDialog(); + } + }); + } + + + void showDialog() { + // Create the fragment and show it as a dialog. + DialogFragment newFragment = MyDialogFragment.newInstance(); + newFragment.show(getSupportFragmentManager(), "dialog"); + } + + + + public static class MyDialogFragment extends SherlockDialogFragment { + static MyDialogFragment newInstance() { + return new MyDialogFragment(); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.hello_world, container, false); + View tv = v.findViewById(R.id.text); + ((TextView)tv).setText("This is an instance of MyDialogFragment"); + return v; + } + } + +} diff --git a/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentDialogSupport.java b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentDialogSupport.java new file mode 100755 index 0000000..ef9837b --- /dev/null +++ b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentDialogSupport.java @@ -0,0 +1,167 @@ +/* + * 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.actionbarsherlock.sample.fragments; + +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentTransaction; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; +import com.actionbarsherlock.app.SherlockDialogFragment; +import com.actionbarsherlock.app.SherlockFragmentActivity; + +public class FragmentDialogSupport extends SherlockFragmentActivity { + int mStackLevel = 0; + + @Override + protected void onCreate(Bundle savedInstanceState) { + setTheme(SampleList.THEME); //Used for theme switching in samples + super.onCreate(savedInstanceState); + setContentView(R.layout.fragment_dialog); + + View tv = findViewById(R.id.text); + ((TextView)tv).setText("Example of displaying dialogs with a DialogFragment. " + + "Press the show button below to see the first dialog; pressing " + + "successive show buttons will display other dialog styles as a " + + "stack, with dismissing or back going to the previous dialog."); + + // Watch for button clicks. + Button button = (Button)findViewById(R.id.show); + button.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + showDialog(); + } + }); + + if (savedInstanceState != null) { + mStackLevel = savedInstanceState.getInt("level"); + } + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putInt("level", mStackLevel); + } + + + void showDialog() { + mStackLevel++; + + // DialogFragment.show() will take care of adding the fragment + // in a transaction. We also want to remove any currently showing + // dialog, so make our own transaction and take care of that here. + FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); + Fragment prev = getSupportFragmentManager().findFragmentByTag("dialog"); + if (prev != null) { + ft.remove(prev); + } + ft.addToBackStack(null); + + // Create and show the dialog. + DialogFragment newFragment = MyDialogFragment.newInstance(mStackLevel); + newFragment.show(ft, "dialog"); + } + + + static String getNameForNum(int num) { + switch ((num-1)%6) { + case 1: return "STYLE_NO_TITLE"; + case 2: return "STYLE_NO_FRAME"; + case 3: return "STYLE_NO_INPUT (this window can't receive input, so " + + "you will need to press the bottom show button)"; + case 4: return "STYLE_NORMAL with dark fullscreen theme"; + case 5: return "STYLE_NORMAL with light theme"; + case 6: return "STYLE_NO_TITLE with light theme"; + case 7: return "STYLE_NO_FRAME with light theme"; + case 8: return "STYLE_NORMAL with light fullscreen theme"; + } + return "STYLE_NORMAL"; + } + + + public static class MyDialogFragment extends SherlockDialogFragment { + int mNum; + + /** + * Create a new instance of MyDialogFragment, providing "num" + * as an argument. + */ + static MyDialogFragment newInstance(int num) { + MyDialogFragment f = new MyDialogFragment(); + + // Supply num input as an argument. + Bundle args = new Bundle(); + args.putInt("num", num); + f.setArguments(args); + + return f; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mNum = getArguments().getInt("num"); + + // Pick a style based on the num. + int style = DialogFragment.STYLE_NORMAL, theme = 0; + switch ((mNum-1)%6) { + case 1: style = DialogFragment.STYLE_NO_TITLE; break; + case 2: style = DialogFragment.STYLE_NO_FRAME; break; + case 3: style = DialogFragment.STYLE_NO_INPUT; break; + case 4: style = DialogFragment.STYLE_NORMAL; break; + case 5: style = DialogFragment.STYLE_NO_TITLE; break; + case 6: style = DialogFragment.STYLE_NO_FRAME; break; + case 7: style = DialogFragment.STYLE_NORMAL; break; + } + switch ((mNum-1)%6) { + case 2: theme = android.R.style.Theme_Panel; break; + case 4: theme = android.R.style.Theme; break; + case 5: theme = android.R.style.Theme_Light; break; + case 6: theme = android.R.style.Theme_Light_Panel; break; + case 7: theme = android.R.style.Theme_Light; break; + } + setStyle(style, theme); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_dialog, container, false); + View tv = v.findViewById(R.id.text); + ((TextView)tv).setText("Dialog #" + mNum + ": using style " + + getNameForNum(mNum)); + + // Watch for button clicks. + Button button = (Button)v.findViewById(R.id.show); + button.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + // When button is clicked, call up to owning activity. + ((FragmentDialogSupport)getActivity()).showDialog(); + } + }); + + return v; + } + } + +} diff --git a/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentHideShowSupport.java b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentHideShowSupport.java new file mode 100755 index 0000000..41ce407 --- /dev/null +++ b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentHideShowSupport.java @@ -0,0 +1,113 @@ +/* + * 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.actionbarsherlock.sample.fragments; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentTransaction; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; +import com.actionbarsherlock.app.SherlockFragment; +import com.actionbarsherlock.app.SherlockFragmentActivity; + +/** + * Demonstration of hiding and showing fragments. + */ +public class FragmentHideShowSupport extends SherlockFragmentActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + setTheme(SampleList.THEME); //Used for theme switching in samples + super.onCreate(savedInstanceState); + setContentView(R.layout.fragment_hide_show_support); + + // The content view embeds two fragments; now retrieve them and attach + // their "hide" button. + FragmentManager fm = getSupportFragmentManager(); + addShowHideListener(R.id.frag1hide, fm.findFragmentById(R.id.fragment1)); + addShowHideListener(R.id.frag2hide, fm.findFragmentById(R.id.fragment2)); + } + + void addShowHideListener(int buttonId, final Fragment fragment) { + final Button button = (Button)findViewById(buttonId); + button.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); + ft.setCustomAnimations(android.R.anim.fade_in, + android.R.anim.fade_out); + if (fragment.isHidden()) { + ft.show(fragment); + button.setText("Hide"); + } else { + ft.hide(fragment); + button.setText("Show"); + } + ft.commit(); + } + }); + } + + public static class FirstFragment extends SherlockFragment { + TextView mTextView; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.labeled_text_edit, container, false); + View tv = v.findViewById(R.id.msg); + ((TextView)tv).setText("The fragment saves and restores this text."); + + // Retrieve the text editor, and restore the last saved state if needed. + mTextView = (TextView)v.findViewById(R.id.saved); + if (savedInstanceState != null) { + mTextView.setText(savedInstanceState.getCharSequence("text")); + } + return v; + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + + // Remember the current text, to restore if we later restart. + outState.putCharSequence("text", mTextView.getText()); + } + } + + public static class SecondFragment extends Fragment { + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.labeled_text_edit, container, false); + View tv = v.findViewById(R.id.msg); + ((TextView)tv).setText("The TextView saves and restores this text."); + + // Retrieve the text editor and tell it to save and restore its state. + // Note that you will often set this in the layout XML, but since + // we are sharing our layout with the other fragment we will customize + // it here. + ((TextView)v.findViewById(R.id.saved)).setSaveEnabled(true); + return v; + } + } +} diff --git a/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentLayoutSupport.java b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentLayoutSupport.java new file mode 100755 index 0000000..e3f6a92 --- /dev/null +++ b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentLayoutSupport.java @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.actionbarsherlock.sample.fragments; + +import android.content.Intent; +import android.content.res.Configuration; +import android.os.Bundle; +import android.support.v4.app.FragmentTransaction; +import android.util.TypedValue; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ListView; +import android.widget.ScrollView; +import android.widget.TextView; +import com.actionbarsherlock.app.SherlockFragment; +import com.actionbarsherlock.app.SherlockFragmentActivity; +import com.actionbarsherlock.app.SherlockListFragment; + +/** + * Demonstration of using fragments to implement different activity layouts. + * This sample provides a different layout (and activity flow) when run in + * landscape. + */ +public class FragmentLayoutSupport extends SherlockFragmentActivity { + + + @Override + protected void onCreate(Bundle savedInstanceState) { + setTheme(SampleList.THEME); //Used for theme switching in samples + super.onCreate(savedInstanceState); + + setContentView(R.layout.fragment_layout_support); + } + + + /** + * This is a secondary activity, to show what the user has selected + * when the screen is not large enough to show it all in one activity. + */ + + public static class DetailsActivity extends SherlockFragmentActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + setTheme(SampleList.THEME); //Used for theme switching in samples + super.onCreate(savedInstanceState); + + if (getResources().getConfiguration().orientation + == Configuration.ORIENTATION_LANDSCAPE) { + // If the screen is now in landscape mode, we can show the + // dialog in-line with the list so we don't need this activity. + finish(); + return; + } + + if (savedInstanceState == null) { + // During initial setup, plug in the details fragment. + DetailsFragment details = new DetailsFragment(); + details.setArguments(getIntent().getExtras()); + getSupportFragmentManager().beginTransaction().add( + android.R.id.content, details).commit(); + } + } + } + + + /** + * This is the "top-level" fragment, showing a list of items that the + * user can pick. Upon picking an item, it takes care of displaying the + * data to the user as appropriate based on the currrent UI layout. + */ + + public static class TitlesFragment extends SherlockListFragment { + boolean mDualPane; + int mCurCheckPosition = 0; + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + // Populate list with our static array of titles. + setListAdapter(new ArrayAdapter<String>(getActivity(), + R.layout.simple_list_item_checkable_1, + android.R.id.text1, Shakespeare.TITLES)); + + // Check to see if we have a frame in which to embed the details + // fragment directly in the containing UI. + View detailsFrame = getActivity().findViewById(R.id.details); + mDualPane = detailsFrame != null && detailsFrame.getVisibility() == View.VISIBLE; + + if (savedInstanceState != null) { + // Restore last state for checked position. + mCurCheckPosition = savedInstanceState.getInt("curChoice", 0); + } + + if (mDualPane) { + // In dual-pane mode, the list view highlights the selected item. + getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE); + // Make sure our UI is in the correct state. + showDetails(mCurCheckPosition); + } + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putInt("curChoice", mCurCheckPosition); + } + + @Override + public void onListItemClick(ListView l, View v, int position, long id) { + showDetails(position); + } + + /** + * Helper function to show the details of a selected item, either by + * displaying a fragment in-place in the current UI, or starting a + * whole new activity in which it is displayed. + */ + void showDetails(int index) { + mCurCheckPosition = index; + + if (mDualPane) { + // We can display everything in-place with fragments, so update + // the list to highlight the selected item and show the data. + getListView().setItemChecked(index, true); + + // Check what fragment is currently shown, replace if needed. + DetailsFragment details = (DetailsFragment) + getFragmentManager().findFragmentById(R.id.details); + if (details == null || details.getShownIndex() != index) { + // Make new fragment to show this selection. + details = DetailsFragment.newInstance(index); + + // Execute a transaction, replacing any existing fragment + // with this one inside the frame. + FragmentTransaction ft = getFragmentManager().beginTransaction(); + ft.replace(R.id.details, details); + ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE); + ft.commit(); + } + + } else { + // Otherwise we need to launch a new activity to display + // the dialog fragment with selected text. + Intent intent = new Intent(); + intent.setClass(getActivity(), DetailsActivity.class); + intent.putExtra("index", index); + startActivity(intent); + } + } + } + + + /** + * This is the secondary fragment, displaying the details of a particular + * item. + */ + + public static class DetailsFragment extends SherlockFragment { + /** + * Create a new instance of DetailsFragment, initialized to + * show the text at 'index'. + */ + public static DetailsFragment newInstance(int index) { + DetailsFragment f = new DetailsFragment(); + + // Supply index input as an argument. + Bundle args = new Bundle(); + args.putInt("index", index); + f.setArguments(args); + + return f; + } + + public int getShownIndex() { + return getArguments().getInt("index", 0); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + if (container == null) { + // We have different layouts, and in one of them this + // fragment's containing frame doesn't exist. The fragment + // may still be created from its saved state, but there is + // no reason to try to create its view hierarchy because it + // won't be displayed. Note this is not needed -- we could + // just run the code below, where we would create and return + // the view hierarchy; it would just never be used. + return null; + } + + ScrollView scroller = new ScrollView(getActivity()); + TextView text = new TextView(getActivity()); + int padding = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, + 4, getActivity().getResources().getDisplayMetrics()); + text.setPadding(padding, padding, padding, padding); + scroller.addView(text); + text.setText(Shakespeare.DIALOGUE[getShownIndex()]); + return scroller; + } + } + +} diff --git a/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentListArraySupport.java b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentListArraySupport.java new file mode 100755 index 0000000..9462375 --- /dev/null +++ b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentListArraySupport.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.actionbarsherlock.sample.fragments; + +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.widget.ArrayAdapter; +import android.widget.ListView; +import com.actionbarsherlock.app.SherlockFragmentActivity; +import com.actionbarsherlock.app.SherlockListFragment; + +/** + * Demonstration of using ListFragment to show a list of items + * from a canned array. + */ +public class FragmentListArraySupport extends SherlockFragmentActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + setTheme(SampleList.THEME); //Used for theme switching in samples + super.onCreate(savedInstanceState); + + // Create the list fragment and add it as our sole content. + if (getSupportFragmentManager().findFragmentById(android.R.id.content) == null) { + ArrayListFragment list = new ArrayListFragment(); + getSupportFragmentManager().beginTransaction().add(android.R.id.content, list).commit(); + } + } + + public static class ArrayListFragment extends SherlockListFragment { + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + setListAdapter(new ArrayAdapter<String>(getActivity(), + android.R.layout.simple_list_item_1, Shakespeare.TITLES)); + } + + @Override + public void onListItemClick(ListView l, View v, int position, long id) { + Log.i("FragmentList", "Item clicked: " + id); + } + } +} diff --git a/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentMenuSupport.java b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentMenuSupport.java new file mode 100755 index 0000000..58c818d --- /dev/null +++ b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentMenuSupport.java @@ -0,0 +1,132 @@ +/* + * 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.actionbarsherlock.sample.fragments; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentTransaction; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.CheckBox; +import com.actionbarsherlock.app.SherlockFragment; +import com.actionbarsherlock.app.SherlockFragmentActivity; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuInflater; +import com.actionbarsherlock.view.MenuItem; + +/** + * Demonstrates how fragments can participate in the options menu. + */ +public class FragmentMenuSupport extends SherlockFragmentActivity { + Fragment mFragment1; + Fragment mFragment2; + CheckBox mCheckBox1; + CheckBox mCheckBox2; + + // Update fragment visibility when check boxes are changed. + final OnClickListener mClickListener = new OnClickListener() { + public void onClick(View v) { + updateFragmentVisibility(); + } + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + setTheme(SampleList.THEME); //Used for theme switching in samples + super.onCreate(savedInstanceState); + setContentView(R.layout.fragment_menu); + + // Make sure the two menu fragments are created. + FragmentManager fm = getSupportFragmentManager(); + FragmentTransaction ft = fm.beginTransaction(); + mFragment1 = fm.findFragmentByTag("f1"); + if (mFragment1 == null) { + mFragment1 = new MenuFragment(); + ft.add(mFragment1, "f1"); + } + mFragment2 = fm.findFragmentByTag("f2"); + if (mFragment2 == null) { + mFragment2 = new Menu2Fragment(); + ft.add(mFragment2, "f2"); + } + ft.commit(); + + // Watch check box clicks. + mCheckBox1 = (CheckBox)findViewById(R.id.menu1); + mCheckBox1.setOnClickListener(mClickListener); + mCheckBox2 = (CheckBox)findViewById(R.id.menu2); + mCheckBox2.setOnClickListener(mClickListener); + + // Make sure fragments start out with correct visibility. + updateFragmentVisibility(); + } + + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) { + super.onRestoreInstanceState(savedInstanceState); + // Make sure fragments are updated after check box view state is restored. + updateFragmentVisibility(); + } + + // Update fragment visibility based on current check box state. + void updateFragmentVisibility() { + FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); + if (mCheckBox1.isChecked()) ft.show(mFragment1); + else ft.hide(mFragment1); + if (mCheckBox2.isChecked()) ft.show(mFragment2); + else ft.hide(mFragment2); + ft.commit(); + } + + /** + * A fragment that displays a menu. This fragment happens to not + * have a UI (it does not implement onCreateView), but it could also + * have one if it wanted. + */ + public static class MenuFragment extends SherlockFragment { + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(true); + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + menu.add("Menu 1a").setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); + menu.add("Menu 1b").setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); + } + } + + /** + * Second fragment with a menu. + */ + public static class Menu2Fragment extends SherlockFragment { + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(true); + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + menu.add("Menu 2").setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); + } + } +} diff --git a/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentPagerSupport.java b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentPagerSupport.java new file mode 100755 index 0000000..a531b15 --- /dev/null +++ b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentPagerSupport.java @@ -0,0 +1,139 @@ +/* + * 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.actionbarsherlock.sample.fragments; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; +import android.support.v4.view.ViewPager; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.ListView; +import android.widget.TextView; +import com.actionbarsherlock.app.SherlockFragmentActivity; +import com.actionbarsherlock.app.SherlockListFragment; + + +public class FragmentPagerSupport extends SherlockFragmentActivity { + static final int NUM_ITEMS = 10; + + MyAdapter mAdapter; + + ViewPager mPager; + + @Override + protected void onCreate(Bundle savedInstanceState) { + setTheme(SampleList.THEME); //Used for theme switching in samples + super.onCreate(savedInstanceState); + setContentView(R.layout.fragment_pager); + + mAdapter = new MyAdapter(getSupportFragmentManager()); + + mPager = (ViewPager)findViewById(R.id.pager); + mPager.setAdapter(mAdapter); + + // Watch for button clicks. + Button button = (Button)findViewById(R.id.goto_first); + button.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + mPager.setCurrentItem(0); + } + }); + button = (Button)findViewById(R.id.goto_last); + button.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + mPager.setCurrentItem(NUM_ITEMS-1); + } + }); + } + + public static class MyAdapter extends FragmentPagerAdapter { + public MyAdapter(FragmentManager fm) { + super(fm); + } + + @Override + public int getCount() { + return NUM_ITEMS; + } + + @Override + public Fragment getItem(int position) { + return ArrayListFragment.newInstance(position); + } + } + + public static class ArrayListFragment extends SherlockListFragment { + int mNum; + + /** + * Create a new instance of CountingFragment, providing "num" + * as an argument. + */ + static ArrayListFragment newInstance(int num) { + ArrayListFragment f = new ArrayListFragment(); + + // Supply num input as an argument. + Bundle args = new Bundle(); + args.putInt("num", num); + f.setArguments(args); + + return f; + } + + /** + * When creating, retrieve this instance's number from its arguments. + */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mNum = getArguments() != null ? getArguments().getInt("num") : 1; + } + + /** + * The Fragment's UI is just a simple text view showing its + * instance number. + */ + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_pager_list, container, false); + View tv = v.findViewById(R.id.text); + ((TextView)tv).setText("Fragment #" + mNum); + return v; + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + setListAdapter(new ArrayAdapter<String>(getActivity(), + android.R.layout.simple_list_item_1, Cheeses.sCheeseStrings)); + } + + @Override + public void onListItemClick(ListView l, View v, int position, long id) { + Log.i("FragmentList", "Item clicked: " + id); + } + } +} + diff --git a/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentReceiveResultSupport.java b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentReceiveResultSupport.java new file mode 100755 index 0000000..fda6d1c --- /dev/null +++ b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentReceiveResultSupport.java @@ -0,0 +1,133 @@ +/* + * 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.actionbarsherlock.sample.fragments; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentTransaction; +import android.text.Editable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.FrameLayout; +import android.widget.TextView; +import com.actionbarsherlock.app.SherlockFragment; +import com.actionbarsherlock.app.SherlockFragmentActivity; + +public class FragmentReceiveResultSupport extends SherlockFragmentActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + setTheme(SampleList.THEME); //Used for theme switching in samples + super.onCreate(savedInstanceState); + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.FILL_PARENT, + ViewGroup.LayoutParams.FILL_PARENT); + FrameLayout frame = new FrameLayout(this); + frame.setId(R.id.simple_fragment); + setContentView(frame, lp); + + if (savedInstanceState == null) { + // Do first time initialization -- add fragment. + Fragment newFragment = new ReceiveResultFragment(); + FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); + ft.add(R.id.simple_fragment, newFragment).commit(); + } + } + + public static class ReceiveResultFragment extends SherlockFragment { + // Definition of the one requestCode we use for receiving resuls. + static final private int GET_CODE = 0; + + private TextView mResults; + + private OnClickListener mGetListener = new OnClickListener() { + public void onClick(View v) { + // Start the activity whose result we want to retrieve. The + // result will come back with request code GET_CODE. + Intent intent = new Intent(getActivity(), SendResult.class); + startActivityForResult(intent, GET_CODE); + } + }; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.receive_result, container, false); + + // Retrieve the TextView widget that will display results. + mResults = (TextView)v.findViewById(R.id.results); + + // This allows us to later extend the text buffer. + mResults.setText(mResults.getText(), TextView.BufferType.EDITABLE); + + // Watch for button clicks. + Button getButton = (Button)v.findViewById(R.id.get); + getButton.setOnClickListener(mGetListener); + + return v; + } + + /** + * This method is called when the sending activity has finished, with the + * result it supplied. + */ + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + // You can use the requestCode to select between multiple child + // activities you may have started. Here there is only one thing + // we launch. + if (requestCode == GET_CODE) { + + // We will be adding to our text. + Editable text = (Editable)mResults.getText(); + + // This is a standard resultCode that is sent back if the + // activity doesn't supply an explicit result. It will also + // be returned if the activity failed to launch. + if (resultCode == RESULT_CANCELED) { + text.append("(cancelled)"); + + // Our protocol with the sending activity is that it will send + // text in 'data' as its result. + } else { + text.append("(okay "); + text.append(Integer.toString(resultCode)); + text.append(") "); + if (data != null) { + text.append(data.getAction()); + } + } + + text.append("\n"); + } + } + } +} diff --git a/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentRetainInstanceSupport.java b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentRetainInstanceSupport.java new file mode 100755 index 0000000..a6f5a73 --- /dev/null +++ b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentRetainInstanceSupport.java @@ -0,0 +1,231 @@ +/* + * 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.actionbarsherlock.sample.fragments; + +import android.os.Bundle; +import android.support.v4.app.FragmentManager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.ProgressBar; +import com.actionbarsherlock.app.SherlockFragment; +import com.actionbarsherlock.app.SherlockFragmentActivity; + +/** + * This example shows how you can use a Fragment to easily propagate state + * (such as threads) across activity instances when an activity needs to be + * restarted due to, for example, a configuration change. This is a lot + * easier than using the raw Activity.onRetainNonConfiguratinInstance() API. + */ +public class FragmentRetainInstanceSupport extends SherlockFragmentActivity { + @Override + protected void onCreate(Bundle savedInstanceState) { + setTheme(SampleList.THEME); //Used for theme switching in samples + super.onCreate(savedInstanceState); + + // First time init, create the UI. + if (savedInstanceState == null) { + getSupportFragmentManager().beginTransaction().add(android.R.id.content, + new UiFragment()).commit(); + } + } + + /** + * This is a fragment showing UI that will be updated from work done + * in the retained fragment. + */ + public static class UiFragment extends SherlockFragment { + RetainedFragment mWorkFragment; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_retain_instance, container, false); + + // Watch for button clicks. + Button button = (Button)v.findViewById(R.id.restart); + button.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + mWorkFragment.restart(); + } + }); + + return v; + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + FragmentManager fm = getFragmentManager(); + + // Check to see if we have retained the worker fragment. + mWorkFragment = (RetainedFragment)fm.findFragmentByTag("work"); + + // If not retained (or first time running), we need to create it. + if (mWorkFragment == null) { + mWorkFragment = new RetainedFragment(); + // Tell it who it is working with. + mWorkFragment.setTargetFragment(this, 0); + fm.beginTransaction().add(mWorkFragment, "work").commit(); + } + } + + } + + /** + * This is the Fragment implementation that will be retained across + * activity instances. It represents some ongoing work, here a thread + * we have that sits around incrementing a progress indicator. + */ + public static class RetainedFragment extends SherlockFragment { + ProgressBar mProgressBar; + int mPosition; + boolean mReady = false; + boolean mQuiting = false; + + /** + * This is the thread that will do our work. It sits in a loop running + * the progress up until it has reached the top, then stops and waits. + */ + final Thread mThread = new Thread() { + @Override + public void run() { + // We'll figure the real value out later. + int max = 10000; + + // This thread runs almost forever. + while (true) { + + // Update our shared state with the UI. + synchronized (this) { + // Our thread is stopped if the UI is not ready + // or it has completed its work. + while (!mReady || mPosition >= max) { + if (mQuiting) { + return; + } + try { + wait(); + } catch (InterruptedException e) { + } + } + + // Now update the progress. Note it is important that + // we touch the progress bar with the lock held, so it + // doesn't disappear on us. + mPosition++; + max = mProgressBar.getMax(); + mProgressBar.setProgress(mPosition); + } + + // Normally we would be doing some work, but put a kludge + // here to pretend like we are. + synchronized (this) { + try { + wait(50); + } catch (InterruptedException e) { + } + } + } + } + }; + + /** + * Fragment initialization. We way we want to be retained and + * start our thread. + */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // Tell the framework to try to keep this fragment around + // during a configuration change. + setRetainInstance(true); + + // Start up the worker thread. + mThread.start(); + } + + /** + * This is called when the Fragment's Activity is ready to go, after + * its content view has been installed; it is called both after + * the initial fragment creation and after the fragment is re-attached + * to a new activity. + */ + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + // Retrieve the progress bar from the target's view hierarchy. + mProgressBar = (ProgressBar)getTargetFragment().getView().findViewById( + R.id.progress_horizontal); + + // We are ready for our thread to go. + synchronized (mThread) { + mReady = true; + mThread.notify(); + } + } + + /** + * This is called when the fragment is going away. It is NOT called + * when the fragment is being propagated between activity instances. + */ + @Override + public void onDestroy() { + // Make the thread go away. + synchronized (mThread) { + mReady = false; + mQuiting = true; + mThread.notify(); + } + + super.onDestroy(); + } + + /** + * This is called right before the fragment is detached from its + * current activity instance. + */ + @Override + public void onDetach() { + // This fragment is being detached from its activity. We need + // to make sure its thread is not going to touch any activity + // state after returning from this function. + synchronized (mThread) { + mProgressBar = null; + mReady = false; + mThread.notify(); + } + + super.onDetach(); + } + + /** + * API for our UI to restart the progress thread. + */ + public void restart() { + synchronized (mThread) { + mPosition = 0; + mThread.notify(); + } + } + } +} diff --git a/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentStackSupport.java b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentStackSupport.java new file mode 100755 index 0000000..9e044a6 --- /dev/null +++ b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentStackSupport.java @@ -0,0 +1,124 @@ +/* + * 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.actionbarsherlock.sample.fragments; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentTransaction; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; +import com.actionbarsherlock.app.SherlockFragment; +import com.actionbarsherlock.app.SherlockFragmentActivity; + +public class FragmentStackSupport extends SherlockFragmentActivity { + int mStackLevel = 1; + + @Override + protected void onCreate(Bundle savedInstanceState) { + setTheme(SampleList.THEME); //Used for theme switching in samples + super.onCreate(savedInstanceState); + setContentView(R.layout.fragment_stack); + + // Watch for button clicks. + Button button = (Button)findViewById(R.id.new_fragment); + button.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + addFragmentToStack(); + } + }); + + if (savedInstanceState == null) { + // Do first time initialization -- add initial fragment. + Fragment newFragment = CountingFragment.newInstance(mStackLevel); + FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); + ft.add(R.id.simple_fragment, newFragment).commit(); + } else { + mStackLevel = savedInstanceState.getInt("level"); + } + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putInt("level", mStackLevel); + } + + + void addFragmentToStack() { + mStackLevel++; + + // Instantiate a new fragment. + Fragment newFragment = CountingFragment.newInstance(mStackLevel); + + // Add the fragment to the activity, pushing this transaction + // on to the back stack. + FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); + ft.replace(R.id.simple_fragment, newFragment); + ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); + ft.addToBackStack(null); + ft.commit(); + } + + + + public static class CountingFragment extends SherlockFragment { + int mNum; + + /** + * Create a new instance of CountingFragment, providing "num" + * as an argument. + */ + static CountingFragment newInstance(int num) { + CountingFragment f = new CountingFragment(); + + // Supply num input as an argument. + Bundle args = new Bundle(); + args.putInt("num", num); + f.setArguments(args); + + return f; + } + + /** + * When creating, retrieve this instance's number from its arguments. + */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mNum = getArguments() != null ? getArguments().getInt("num") : 1; + } + + /** + * The Fragment's UI is just a simple text view showing its + * instance number. + */ + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.hello_world, container, false); + View tv = v.findViewById(R.id.text); + ((TextView)tv).setText("Fragment #" + mNum); + tv.setBackgroundDrawable(getResources().getDrawable(android.R.drawable.gallery_thumb)); + return v; + } + } + +} diff --git a/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentStatePagerSupport.java b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentStatePagerSupport.java new file mode 100755 index 0000000..433c7e3 --- /dev/null +++ b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentStatePagerSupport.java @@ -0,0 +1,139 @@ +/* + * 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.actionbarsherlock.sample.fragments; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentStatePagerAdapter; +import android.support.v4.view.ViewPager; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.ListView; +import android.widget.TextView; +import com.actionbarsherlock.app.SherlockFragmentActivity; +import com.actionbarsherlock.app.SherlockListFragment; + + +public class FragmentStatePagerSupport extends SherlockFragmentActivity { + static final int NUM_ITEMS = 10; + + MyAdapter mAdapter; + + ViewPager mPager; + + @Override + protected void onCreate(Bundle savedInstanceState) { + setTheme(SampleList.THEME); //Used for theme switching in samples + super.onCreate(savedInstanceState); + setContentView(R.layout.fragment_pager); + + mAdapter = new MyAdapter(getSupportFragmentManager()); + + mPager = (ViewPager)findViewById(R.id.pager); + mPager.setAdapter(mAdapter); + + // Watch for button clicks. + Button button = (Button)findViewById(R.id.goto_first); + button.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + mPager.setCurrentItem(0); + } + }); + button = (Button)findViewById(R.id.goto_last); + button.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + mPager.setCurrentItem(NUM_ITEMS-1); + } + }); + } + + public static class MyAdapter extends FragmentStatePagerAdapter { + public MyAdapter(FragmentManager fm) { + super(fm); + } + + @Override + public int getCount() { + return NUM_ITEMS; + } + + @Override + public Fragment getItem(int position) { + return ArrayListFragment.newInstance(position); + } + } + + public static class ArrayListFragment extends SherlockListFragment { + int mNum; + + /** + * Create a new instance of CountingFragment, providing "num" + * as an argument. + */ + static ArrayListFragment newInstance(int num) { + ArrayListFragment f = new ArrayListFragment(); + + // Supply num input as an argument. + Bundle args = new Bundle(); + args.putInt("num", num); + f.setArguments(args); + + return f; + } + + /** + * When creating, retrieve this instance's number from its arguments. + */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mNum = getArguments() != null ? getArguments().getInt("num") : 1; + } + + /** + * The Fragment's UI is just a simple text view showing its + * instance number. + */ + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_pager_list, container, false); + View tv = v.findViewById(R.id.text); + ((TextView)tv).setText("Fragment #" + mNum); + return v; + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + setListAdapter(new ArrayAdapter<String>(getActivity(), + android.R.layout.simple_list_item_1, Cheeses.sCheeseStrings)); + } + + @Override + public void onListItemClick(ListView l, View v, int position, long id) { + Log.i("FragmentList", "Item clicked: " + id); + } + } +} + diff --git a/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentTabs.java b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentTabs.java new file mode 100755 index 0000000..e6dbd94 --- /dev/null +++ b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentTabs.java @@ -0,0 +1,170 @@ +/* + * 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.actionbarsherlock.sample.fragments; + + +import java.util.HashMap; +import android.content.Context; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentTransaction; +import android.view.View; +import android.widget.TabHost; +import com.actionbarsherlock.app.SherlockFragmentActivity; + +/** + * This demonstrates how you can implement switching between the tabs of a + * TabHost through fragments. It uses a trick (see the code below) to allow + * the tabs to switch between fragments instead of simple views. + */ +public class FragmentTabs extends SherlockFragmentActivity { + TabHost mTabHost; + TabManager mTabManager; + + @Override + protected void onCreate(Bundle savedInstanceState) { + setTheme(SampleList.THEME); //Used for theme switching in samples + super.onCreate(savedInstanceState); + + setContentView(R.layout.fragment_tabs); + mTabHost = (TabHost)findViewById(android.R.id.tabhost); + mTabHost.setup(); + + mTabManager = new TabManager(this, mTabHost, R.id.realtabcontent); + + mTabManager.addTab(mTabHost.newTabSpec("simple").setIndicator("Simple"), + FragmentStackSupport.CountingFragment.class, null); + mTabManager.addTab(mTabHost.newTabSpec("contacts").setIndicator("Contacts"), + LoaderCursorSupport.CursorLoaderListFragment.class, null); + mTabManager.addTab(mTabHost.newTabSpec("custom").setIndicator("Custom"), + LoaderCustomSupport.AppListFragment.class, null); + mTabManager.addTab(mTabHost.newTabSpec("throttle").setIndicator("Throttle"), + LoaderThrottleSupport.ThrottledLoaderListFragment.class, null); + + if (savedInstanceState != null) { + mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab")); + } + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putString("tab", mTabHost.getCurrentTabTag()); + } + + /** + * This is a helper class that implements a generic mechanism for + * associating fragments with the tabs in a tab host. It relies on a + * trick. Normally a tab host has a simple API for supplying a View or + * Intent that each tab will show. This is not sufficient for switching + * between fragments. So instead we make the content part of the tab host + * 0dp high (it is not shown) and the TabManager supplies its own dummy + * view to show as the tab content. It listens to changes in tabs, and takes + * care of switch to the correct fragment shown in a separate content area + * whenever the selected tab changes. + */ + public static class TabManager implements TabHost.OnTabChangeListener { + private final FragmentActivity mActivity; + private final TabHost mTabHost; + private final int mContainerId; + private final HashMap<String, TabInfo> mTabs = new HashMap<String, TabInfo>(); + TabInfo mLastTab; + + static final class TabInfo { + private final String tag; + private final Class<?> clss; + private final Bundle args; + private Fragment fragment; + + TabInfo(String _tag, Class<?> _class, Bundle _args) { + tag = _tag; + clss = _class; + args = _args; + } + } + + static class DummyTabFactory implements TabHost.TabContentFactory { + private final Context mContext; + + public DummyTabFactory(Context context) { + mContext = context; + } + + @Override + public View createTabContent(String tag) { + View v = new View(mContext); + v.setMinimumWidth(0); + v.setMinimumHeight(0); + return v; + } + } + + public TabManager(FragmentActivity activity, TabHost tabHost, int containerId) { + mActivity = activity; + mTabHost = tabHost; + mContainerId = containerId; + mTabHost.setOnTabChangedListener(this); + } + + public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) { + tabSpec.setContent(new DummyTabFactory(mActivity)); + String tag = tabSpec.getTag(); + + TabInfo info = new TabInfo(tag, clss, args); + + // Check to see if we already have a fragment for this tab, probably + // from a previously saved state. If so, deactivate it, because our + // initial state is that a tab isn't shown. + info.fragment = mActivity.getSupportFragmentManager().findFragmentByTag(tag); + if (info.fragment != null && !info.fragment.isDetached()) { + FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction(); + ft.detach(info.fragment); + ft.commit(); + } + + mTabs.put(tag, info); + mTabHost.addTab(tabSpec); + } + + @Override + public void onTabChanged(String tabId) { + TabInfo newTab = mTabs.get(tabId); + if (mLastTab != newTab) { + FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction(); + if (mLastTab != null) { + if (mLastTab.fragment != null) { + ft.detach(mLastTab.fragment); + } + } + if (newTab != null) { + if (newTab.fragment == null) { + newTab.fragment = Fragment.instantiate(mActivity, + newTab.clss.getName(), newTab.args); + ft.add(mContainerId, newTab.fragment, newTab.tag); + } else { + ft.attach(newTab.fragment); + } + } + + mLastTab = newTab; + ft.commit(); + mActivity.getSupportFragmentManager().executePendingTransactions(); + } + } + } +} + diff --git a/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentTabsPager.java b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentTabsPager.java new file mode 100755 index 0000000..d50092f --- /dev/null +++ b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentTabsPager.java @@ -0,0 +1,179 @@ +/* + * 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.actionbarsherlock.sample.fragments; + +import java.util.ArrayList; +import android.content.Context; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentPagerAdapter; +import android.support.v4.view.ViewPager; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TabHost; +import android.widget.TabWidget; +import com.actionbarsherlock.app.SherlockFragmentActivity; + +/** + * Demonstrates combining a TabHost with a ViewPager to implement a tab UI + * that switches between tabs and also allows the user to perform horizontal + * flicks to move between the tabs. + */ +public class FragmentTabsPager extends SherlockFragmentActivity { + TabHost mTabHost; + ViewPager mViewPager; + TabsAdapter mTabsAdapter; + + @Override + protected void onCreate(Bundle savedInstanceState) { + setTheme(SampleList.THEME); //Used for theme switching in samples + super.onCreate(savedInstanceState); + + setContentView(R.layout.fragment_tabs_pager); + mTabHost = (TabHost)findViewById(android.R.id.tabhost); + mTabHost.setup(); + + mViewPager = (ViewPager)findViewById(R.id.pager); + + mTabsAdapter = new TabsAdapter(this, mTabHost, mViewPager); + + mTabsAdapter.addTab(mTabHost.newTabSpec("simple").setIndicator("Simple"), + FragmentStackSupport.CountingFragment.class, null); + mTabsAdapter.addTab(mTabHost.newTabSpec("contacts").setIndicator("Contacts"), + LoaderCursorSupport.CursorLoaderListFragment.class, null); + mTabsAdapter.addTab(mTabHost.newTabSpec("custom").setIndicator("Custom"), + LoaderCustomSupport.AppListFragment.class, null); + mTabsAdapter.addTab(mTabHost.newTabSpec("throttle").setIndicator("Throttle"), + LoaderThrottleSupport.ThrottledLoaderListFragment.class, null); + + if (savedInstanceState != null) { + mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab")); + } + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putString("tab", mTabHost.getCurrentTabTag()); + } + + /** + * This is a helper class that implements the management of tabs and all + * details of connecting a ViewPager with associated TabHost. It relies on a + * trick. Normally a tab host has a simple API for supplying a View or + * Intent that each tab will show. This is not sufficient for switching + * between pages. So instead we make the content part of the tab host + * 0dp high (it is not shown) and the TabsAdapter supplies its own dummy + * view to show as the tab content. It listens to changes in tabs, and takes + * care of switch to the correct paged in the ViewPager whenever the selected + * tab changes. + */ + public static class TabsAdapter extends FragmentPagerAdapter + implements TabHost.OnTabChangeListener, ViewPager.OnPageChangeListener { + private final Context mContext; + private final TabHost mTabHost; + private final ViewPager mViewPager; + private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>(); + + static final class TabInfo { + private final String tag; + private final Class<?> clss; + private final Bundle args; + + TabInfo(String _tag, Class<?> _class, Bundle _args) { + tag = _tag; + clss = _class; + args = _args; + } + } + + static class DummyTabFactory implements TabHost.TabContentFactory { + private final Context mContext; + + public DummyTabFactory(Context context) { + mContext = context; + } + + @Override + public View createTabContent(String tag) { + View v = new View(mContext); + v.setMinimumWidth(0); + v.setMinimumHeight(0); + return v; + } + } + + public TabsAdapter(FragmentActivity activity, TabHost tabHost, ViewPager pager) { + super(activity.getSupportFragmentManager()); + mContext = activity; + mTabHost = tabHost; + mViewPager = pager; + mTabHost.setOnTabChangedListener(this); + mViewPager.setAdapter(this); + mViewPager.setOnPageChangeListener(this); + } + + public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) { + tabSpec.setContent(new DummyTabFactory(mContext)); + String tag = tabSpec.getTag(); + + TabInfo info = new TabInfo(tag, clss, args); + mTabs.add(info); + mTabHost.addTab(tabSpec); + notifyDataSetChanged(); + } + + @Override + public int getCount() { + return mTabs.size(); + } + + @Override + public Fragment getItem(int position) { + TabInfo info = mTabs.get(position); + return Fragment.instantiate(mContext, info.clss.getName(), info.args); + } + + @Override + public void onTabChanged(String tabId) { + int position = mTabHost.getCurrentTab(); + mViewPager.setCurrentItem(position); + } + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + } + + @Override + public void onPageSelected(int position) { + // Unfortunately when TabHost changes the current tab, it kindly + // also takes care of putting focus on it when not in touch mode. + // The jerk. + // This hack tries to prevent this from pulling focus out of our + // ViewPager. + TabWidget widget = mTabHost.getTabWidget(); + int oldFocusability = widget.getDescendantFocusability(); + widget.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); + mTabHost.setCurrentTab(position); + widget.setDescendantFocusability(oldFocusability); + } + + @Override + public void onPageScrollStateChanged(int state) { + } + } +} diff --git a/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/LoaderCursorSupport.java b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/LoaderCursorSupport.java new file mode 100755 index 0000000..08140c7 --- /dev/null +++ b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/LoaderCursorSupport.java @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.actionbarsherlock.sample.fragments; + +import android.database.Cursor; +import android.net.Uri; +import android.os.Bundle; +import android.provider.Contacts.People; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.LoaderManager; +import android.support.v4.content.CursorLoader; +import android.support.v4.content.Loader; +import android.support.v4.widget.SearchViewCompat; +import android.support.v4.widget.SearchViewCompat.OnQueryTextListenerCompat; +import android.support.v4.widget.SimpleCursorAdapter; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.widget.ListView; +import com.actionbarsherlock.app.SherlockFragmentActivity; +import com.actionbarsherlock.app.SherlockListFragment; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuInflater; +import com.actionbarsherlock.view.MenuItem; + +/** + * Demonstration of the use of a CursorLoader to load and display contacts + * data in a fragment. + */ +@SuppressWarnings("all") +public class LoaderCursorSupport extends SherlockFragmentActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + FragmentManager fm = getSupportFragmentManager(); + + // Create the list fragment and add it as our sole content. + if (fm.findFragmentById(android.R.id.content) == null) { + CursorLoaderListFragment list = new CursorLoaderListFragment(); + fm.beginTransaction().add(android.R.id.content, list).commit(); + } + } + + + public static class CursorLoaderListFragment extends SherlockListFragment + implements LoaderManager.LoaderCallbacks<Cursor> { + + // This is the Adapter being used to display the list's data. + SimpleCursorAdapter mAdapter; + + // If non-null, this is the current filter the user has provided. + String mCurFilter; + + @Override public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + // Give some text to display if there is no data. In a real + // application this would come from a resource. + setEmptyText("No phone numbers"); + + // We have a menu item to show in action bar. + setHasOptionsMenu(true); + + // Create an empty adapter we will use to display the loaded data. + mAdapter = new SimpleCursorAdapter(getActivity(), + android.R.layout.simple_list_item_1, null, + new String[] { People.DISPLAY_NAME }, + new int[] { android.R.id.text1}, 0); + setListAdapter(mAdapter); + + // Start out with a progress indicator. + setListShown(false); + + // Prepare the loader. Either re-connect with an existing one, + // or start a new one. + getLoaderManager().initLoader(0, null, this); + } + + @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + // Place an action bar item for searching. + MenuItem item = menu.add("Search"); + item.setIcon(android.R.drawable.ic_menu_search); + item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); + SherlockFragmentActivity activity = (SherlockFragmentActivity)getActivity(); + View searchView = SearchViewCompat.newSearchView(activity.getSupportActionBar().getThemedContext()); + if (searchView != null) { + SearchViewCompat.setOnQueryTextListener(searchView, + new OnQueryTextListenerCompat() { + @Override + public boolean onQueryTextChange(String newText) { + // Called when the action bar search text has changed. Update + // the search filter, and restart the loader to do a new query + // with this filter. + mCurFilter = !TextUtils.isEmpty(newText) ? newText : null; + getLoaderManager().restartLoader(0, null, CursorLoaderListFragment.this); + return true; + } + }); + item.setActionView(searchView); + } + } + + @Override public void onListItemClick(ListView l, View v, int position, long id) { + // Insert desired behavior here. + Log.i("FragmentComplexList", "Item clicked: " + id); + } + + // These are the Contacts rows that we will retrieve. + static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] { + People._ID, + People.DISPLAY_NAME, + }; + + public Loader<Cursor> onCreateLoader(int id, Bundle args) { + // This is called when a new Loader needs to be created. This + // sample only has one Loader, so we don't care about the ID. + // First, pick the base URI to use depending on whether we are + // currently filtering. + Uri baseUri; + if (mCurFilter != null) { + baseUri = Uri.withAppendedPath(People.CONTENT_FILTER_URI, Uri.encode(mCurFilter)); + } else { + baseUri = People.CONTENT_URI; + } + + // Now create and return a CursorLoader that will take care of + // creating a Cursor for the data being displayed. + String select = "((" + People.DISPLAY_NAME + " NOTNULL) AND (" + + People.DISPLAY_NAME + " != '' ))"; + return new CursorLoader(getActivity(), baseUri, + CONTACTS_SUMMARY_PROJECTION, select, null, + People.DISPLAY_NAME + " COLLATE LOCALIZED ASC"); + } + + public void onLoadFinished(Loader<Cursor> loader, Cursor data) { + // Swap the new cursor in. (The framework will take care of closing the + // old cursor once we return.) + mAdapter.swapCursor(data); + + // The list should now be shown. + if (isResumed()) { + setListShown(true); + } else { + setListShownNoAnimation(true); + } + } + + public void onLoaderReset(Loader<Cursor> loader) { + // This is called when the last Cursor provided to onLoadFinished() + // above is about to be closed. We need to make sure we are no + // longer using it. + mAdapter.swapCursor(null); + } + } + +} diff --git a/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/LoaderCustomSupport.java b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/LoaderCustomSupport.java new file mode 100755 index 0000000..e1852cd --- /dev/null +++ b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/LoaderCustomSupport.java @@ -0,0 +1,484 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.actionbarsherlock.sample.fragments; + +import java.io.File; +import java.text.Collator; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.LoaderManager; +import android.support.v4.content.AsyncTaskLoader; +import android.support.v4.content.IntentCompat; +import android.support.v4.content.Loader; +import android.support.v4.content.pm.ActivityInfoCompat; +import android.support.v4.widget.SearchViewCompat; +import android.support.v4.widget.SearchViewCompat.OnQueryTextListenerCompat; +import android.text.TextUtils; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.TextView; +import com.actionbarsherlock.app.SherlockFragmentActivity; +import com.actionbarsherlock.app.SherlockListFragment; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuInflater; +import com.actionbarsherlock.view.MenuItem; + +/** + * Demonstration of the implementation of a custom Loader. + */ +public class LoaderCustomSupport extends SherlockFragmentActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + FragmentManager fm = getSupportFragmentManager(); + + // Create the list fragment and add it as our sole content. + if (fm.findFragmentById(android.R.id.content) == null) { + AppListFragment list = new AppListFragment(); + fm.beginTransaction().add(android.R.id.content, list).commit(); + } + } + + + /** + * This class holds the per-item data in our Loader. + */ + public static class AppEntry { + public AppEntry(AppListLoader loader, ApplicationInfo info) { + mLoader = loader; + mInfo = info; + mApkFile = new File(info.sourceDir); + } + + public ApplicationInfo getApplicationInfo() { + return mInfo; + } + + public String getLabel() { + return mLabel; + } + + public Drawable getIcon() { + if (mIcon == null) { + if (mApkFile.exists()) { + mIcon = mInfo.loadIcon(mLoader.mPm); + return mIcon; + } else { + mMounted = false; + } + } else if (!mMounted) { + // If the app wasn't mounted but is now mounted, reload + // its icon. + if (mApkFile.exists()) { + mMounted = true; + mIcon = mInfo.loadIcon(mLoader.mPm); + return mIcon; + } + } else { + return mIcon; + } + + return mLoader.getContext().getResources().getDrawable( + android.R.drawable.sym_def_app_icon); + } + + @Override public String toString() { + return mLabel; + } + + void loadLabel(Context context) { + if (mLabel == null || !mMounted) { + if (!mApkFile.exists()) { + mMounted = false; + mLabel = mInfo.packageName; + } else { + mMounted = true; + CharSequence label = mInfo.loadLabel(context.getPackageManager()); + mLabel = label != null ? label.toString() : mInfo.packageName; + } + } + } + + private final AppListLoader mLoader; + private final ApplicationInfo mInfo; + private final File mApkFile; + private String mLabel; + private Drawable mIcon; + private boolean mMounted; + } + + /** + * Perform alphabetical comparison of application entry objects. + */ + public static final Comparator<AppEntry> ALPHA_COMPARATOR = new Comparator<AppEntry>() { + private final Collator sCollator = Collator.getInstance(); + @Override + public int compare(AppEntry object1, AppEntry object2) { + return sCollator.compare(object1.getLabel(), object2.getLabel()); + } + }; + + /** + * Helper for determining if the configuration has changed in an interesting + * way so we need to rebuild the app list. + */ + public static class InterestingConfigChanges { + final Configuration mLastConfiguration = new Configuration(); + int mLastDensity; + + boolean applyNewConfig(Resources res) { + int configChanges = mLastConfiguration.updateFrom(res.getConfiguration()); + boolean densityChanged = mLastDensity != res.getDisplayMetrics().densityDpi; + if (densityChanged || (configChanges&(ActivityInfo.CONFIG_LOCALE + |ActivityInfoCompat.CONFIG_UI_MODE|ActivityInfo.CONFIG_SCREEN_LAYOUT)) != 0) { + mLastDensity = res.getDisplayMetrics().densityDpi; + return true; + } + return false; + } + } + + /** + * Helper class to look for interesting changes to the installed apps + * so that the loader can be updated. + */ + public static class PackageIntentReceiver extends BroadcastReceiver { + final AppListLoader mLoader; + + public PackageIntentReceiver(AppListLoader loader) { + mLoader = loader; + IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED); + filter.addAction(Intent.ACTION_PACKAGE_REMOVED); + filter.addAction(Intent.ACTION_PACKAGE_CHANGED); + filter.addDataScheme("package"); + mLoader.getContext().registerReceiver(this, filter); + // Register for events related to sdcard installation. + IntentFilter sdFilter = new IntentFilter(); + sdFilter.addAction(IntentCompat.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE); + sdFilter.addAction(IntentCompat.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); + mLoader.getContext().registerReceiver(this, sdFilter); + } + + @Override public void onReceive(Context context, Intent intent) { + // Tell the loader about the change. + mLoader.onContentChanged(); + } + } + + /** + * A custom Loader that loads all of the installed applications. + */ + public static class AppListLoader extends AsyncTaskLoader<List<AppEntry>> { + final InterestingConfigChanges mLastConfig = new InterestingConfigChanges(); + final PackageManager mPm; + + List<AppEntry> mApps; + PackageIntentReceiver mPackageObserver; + + public AppListLoader(Context context) { + super(context); + + // Retrieve the package manager for later use; note we don't + // use 'context' directly but instead the save global application + // context returned by getContext(). + mPm = getContext().getPackageManager(); + } + + /** + * This is where the bulk of our work is done. This function is + * called in a background thread and should generate a new set of + * data to be published by the loader. + */ + @Override public List<AppEntry> loadInBackground() { + // Retrieve all known applications. + List<ApplicationInfo> apps = mPm.getInstalledApplications( + PackageManager.GET_UNINSTALLED_PACKAGES | + PackageManager.GET_DISABLED_COMPONENTS); + if (apps == null) { + apps = new ArrayList<ApplicationInfo>(); + } + + final Context context = getContext(); + + // Create corresponding array of entries and load their labels. + List<AppEntry> entries = new ArrayList<AppEntry>(apps.size()); + for (int i=0; i<apps.size(); i++) { + AppEntry entry = new AppEntry(this, apps.get(i)); + entry.loadLabel(context); + entries.add(entry); + } + + // Sort the list. + Collections.sort(entries, ALPHA_COMPARATOR); + + // Done! + return entries; + } + + /** + * Called when there is new data to deliver to the client. The + * super class will take care of delivering it; the implementation + * here just adds a little more logic. + */ + @Override public void deliverResult(List<AppEntry> apps) { + if (isReset()) { + // An async query came in while the loader is stopped. We + // don't need the result. + if (apps != null) { + onReleaseResources(apps); + } + } + List<AppEntry> oldApps = apps; + mApps = apps; + + if (isStarted()) { + // If the Loader is currently started, we can immediately + // deliver its results. + super.deliverResult(apps); + } + + // At this point we can release the resources associated with + // 'oldApps' if needed; now that the new result is delivered we + // know that it is no longer in use. + if (oldApps != null) { + onReleaseResources(oldApps); + } + } + + /** + * Handles a request to start the Loader. + */ + @Override protected void onStartLoading() { + if (mApps != null) { + // If we currently have a result available, deliver it + // immediately. + deliverResult(mApps); + } + + // Start watching for changes in the app data. + if (mPackageObserver == null) { + mPackageObserver = new PackageIntentReceiver(this); + } + + // Has something interesting in the configuration changed since we + // last built the app list? + boolean configChange = mLastConfig.applyNewConfig(getContext().getResources()); + + if (takeContentChanged() || mApps == null || configChange) { + // If the data has changed since the last time it was loaded + // or is not currently available, start a load. + forceLoad(); + } + } + + /** + * Handles a request to stop the Loader. + */ + @Override protected void onStopLoading() { + // Attempt to cancel the current load task if possible. + cancelLoad(); + } + + /** + * Handles a request to cancel a load. + */ + @Override public void onCanceled(List<AppEntry> apps) { + super.onCanceled(apps); + + // At this point we can release the resources associated with 'apps' + // if needed. + onReleaseResources(apps); + } + + /** + * Handles a request to completely reset the Loader. + */ + @Override protected void onReset() { + super.onReset(); + + // Ensure the loader is stopped + onStopLoading(); + + // At this point we can release the resources associated with 'apps' + // if needed. + if (mApps != null) { + onReleaseResources(mApps); + mApps = null; + } + + // Stop monitoring for changes. + if (mPackageObserver != null) { + getContext().unregisterReceiver(mPackageObserver); + mPackageObserver = null; + } + } + + /** + * Helper function to take care of releasing resources associated + * with an actively loaded data set. + */ + protected void onReleaseResources(List<AppEntry> apps) { + // For a simple List<> there is nothing to do. For something + // like a Cursor, we would close it here. + } + } + + + + public static class AppListAdapter extends ArrayAdapter<AppEntry> { + private final LayoutInflater mInflater; + + public AppListAdapter(Context context) { + super(context, android.R.layout.simple_list_item_2); + mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + } + + public void setData(List<AppEntry> data) { + clear(); + if (data != null) { + for (AppEntry appEntry : data) { + add(appEntry); + } + } + } + + /** + * Populate new items in the list. + */ + @Override public View getView(int position, View convertView, ViewGroup parent) { + View view; + + if (convertView == null) { + view = mInflater.inflate(R.layout.list_item_icon_text, parent, false); + } else { + view = convertView; + } + + AppEntry item = getItem(position); + ((ImageView)view.findViewById(R.id.icon)).setImageDrawable(item.getIcon()); + ((TextView)view.findViewById(R.id.text)).setText(item.getLabel()); + + return view; + } + } + + public static class AppListFragment extends SherlockListFragment + implements LoaderManager.LoaderCallbacks<List<AppEntry>> { + + // This is the Adapter being used to display the list's data. + AppListAdapter mAdapter; + + // If non-null, this is the current filter the user has provided. + String mCurFilter; + + OnQueryTextListenerCompat mOnQueryTextListenerCompat; + + @Override public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + // Give some text to display if there is no data. In a real + // application this would come from a resource. + setEmptyText("No applications"); + + // We have a menu item to show in action bar. + setHasOptionsMenu(true); + + // Create an empty adapter we will use to display the loaded data. + mAdapter = new AppListAdapter(getActivity()); + setListAdapter(mAdapter); + + // Start out with a progress indicator. + setListShown(false); + + // Prepare the loader. Either re-connect with an existing one, + // or start a new one. + getLoaderManager().initLoader(0, null, this); + } + + @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + // Place an action bar item for searching. + MenuItem item = menu.add("Search"); + item.setIcon(android.R.drawable.ic_menu_search); + item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); + View searchView = SearchViewCompat.newSearchView(getActivity()); + if (searchView != null) { + SearchViewCompat.setOnQueryTextListener(searchView, + new OnQueryTextListenerCompat() { + @Override + public boolean onQueryTextChange(String newText) { + // Called when the action bar search text has changed. Since this + // is a simple array adapter, we can just have it do the filtering. + mCurFilter = !TextUtils.isEmpty(newText) ? newText : null; + mAdapter.getFilter().filter(mCurFilter); + return true; + } + }); + item.setActionView(searchView); + } + } + + @Override public void onListItemClick(ListView l, View v, int position, long id) { + // Insert desired behavior here. + Log.i("LoaderCustom", "Item clicked: " + id); + } + + @Override public Loader<List<AppEntry>> onCreateLoader(int id, Bundle args) { + // This is called when a new Loader needs to be created. This + // sample only has one Loader with no arguments, so it is simple. + return new AppListLoader(getActivity()); + } + + @Override public void onLoadFinished(Loader<List<AppEntry>> loader, List<AppEntry> data) { + // Set the new data in the adapter. + mAdapter.setData(data); + + // The list should now be shown. + if (isResumed()) { + setListShown(true); + } else { + setListShownNoAnimation(true); + } + } + + @Override public void onLoaderReset(Loader<List<AppEntry>> loader) { + // Clear the data in the adapter. + mAdapter.setData(null); + } + } + +} diff --git a/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/LoaderThrottleSupport.java b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/LoaderThrottleSupport.java new file mode 100755 index 0000000..0495fc9 --- /dev/null +++ b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/LoaderThrottleSupport.java @@ -0,0 +1,510 @@ +/* + * 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.actionbarsherlock.sample.fragments; + + +import java.util.HashMap; +import android.content.ContentProvider; +import android.content.ContentResolver; +import android.content.ContentUris; +import android.content.ContentValues; +import android.content.Context; +import android.content.UriMatcher; +import android.database.Cursor; +import android.database.SQLException; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.database.sqlite.SQLiteQueryBuilder; +import android.net.Uri; +import android.os.AsyncTask; +import android.os.Bundle; +import android.provider.BaseColumns; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.LoaderManager; +import android.support.v4.content.CursorLoader; +import android.support.v4.content.Loader; +import android.support.v4.database.DatabaseUtilsCompat; +import android.support.v4.widget.SimpleCursorAdapter; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.widget.ListView; +import com.actionbarsherlock.app.SherlockFragmentActivity; +import com.actionbarsherlock.app.SherlockListFragment; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuInflater; +import com.actionbarsherlock.view.MenuItem; + +/** + * Demonstration of bottom to top implementation of a content provider holding + * structured data through displaying it in the UI, using throttling to reduce + * the number of queries done when its data changes. + */ +public class LoaderThrottleSupport extends SherlockFragmentActivity { + // Debugging. + static final String TAG = "LoaderThrottle"; + + /** + * The authority we use to get to our sample provider. + */ + public static final String AUTHORITY = "com.actionbarsherlock.sample.fragments.LoaderThrottle"; + + /** + * Definition of the contract for the main table of our provider. + */ + public static final class MainTable implements BaseColumns { + + // This class cannot be instantiated + private MainTable() {} + + /** + * The table name offered by this provider + */ + public static final String TABLE_NAME = "main"; + + /** + * The content:// style URL for this table + */ + public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/main"); + + /** + * The content URI base for a single row of data. Callers must + * append a numeric row id to this Uri to retrieve a row + */ + public static final Uri CONTENT_ID_URI_BASE + = Uri.parse("content://" + AUTHORITY + "/main/"); + + /** + * The MIME type of {@link #CONTENT_URI}. + */ + public static final String CONTENT_TYPE + = "vnd.android.cursor.dir/vnd.example.api-demos-throttle"; + + /** + * The MIME type of a {@link #CONTENT_URI} sub-directory of a single row. + */ + public static final String CONTENT_ITEM_TYPE + = "vnd.android.cursor.item/vnd.example.api-demos-throttle"; + /** + * The default sort order for this table + */ + public static final String DEFAULT_SORT_ORDER = "data COLLATE LOCALIZED ASC"; + + /** + * Column name for the single column holding our data. + * <P>Type: TEXT</P> + */ + public static final String COLUMN_NAME_DATA = "data"; + } + + /** + * This class helps open, create, and upgrade the database file. + */ + static class DatabaseHelper extends SQLiteOpenHelper { + + private static final String DATABASE_NAME = "loader_throttle.db"; + private static final int DATABASE_VERSION = 2; + + DatabaseHelper(Context context) { + + // calls the super constructor, requesting the default cursor factory. + super(context, DATABASE_NAME, null, DATABASE_VERSION); + } + + /** + * + * Creates the underlying database with table name and column names taken from the + * NotePad class. + */ + @Override + public void onCreate(SQLiteDatabase db) { + db.execSQL("CREATE TABLE " + MainTable.TABLE_NAME + " (" + + MainTable._ID + " INTEGER PRIMARY KEY," + + MainTable.COLUMN_NAME_DATA + " TEXT" + + ");"); + } + + /** + * + * Demonstrates that the provider must consider what happens when the + * underlying datastore is changed. In this sample, the database is upgraded the database + * by destroying the existing data. + * A real application should upgrade the database in place. + */ + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + + // Logs that the database is being upgraded + Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + + newVersion + ", which will destroy all old data"); + + // Kills the table and existing data + db.execSQL("DROP TABLE IF EXISTS notes"); + + // Recreates the database with a new version + onCreate(db); + } + } + + /** + * A very simple implementation of a content provider. + */ + public static class SimpleProvider extends ContentProvider { + // A projection map used to select columns from the database + private final HashMap<String, String> mNotesProjectionMap; + // Uri matcher to decode incoming URIs. + private final UriMatcher mUriMatcher; + + // The incoming URI matches the main table URI pattern + private static final int MAIN = 1; + // The incoming URI matches the main table row ID URI pattern + private static final int MAIN_ID = 2; + + // Handle to a new DatabaseHelper. + private DatabaseHelper mOpenHelper; + + /** + * Global provider initialization. + */ + public SimpleProvider() { + // Create and initialize URI matcher. + mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); + mUriMatcher.addURI(AUTHORITY, MainTable.TABLE_NAME, MAIN); + mUriMatcher.addURI(AUTHORITY, MainTable.TABLE_NAME + "/#", MAIN_ID); + + // Create and initialize projection map for all columns. This is + // simply an identity mapping. + mNotesProjectionMap = new HashMap<String, String>(); + mNotesProjectionMap.put(MainTable._ID, MainTable._ID); + mNotesProjectionMap.put(MainTable.COLUMN_NAME_DATA, MainTable.COLUMN_NAME_DATA); + } + + /** + * Perform provider creation. + */ + @Override + public boolean onCreate() { + mOpenHelper = new DatabaseHelper(getContext()); + // Assumes that any failures will be reported by a thrown exception. + return true; + } + + /** + * Handle incoming queries. + */ + @Override + public Cursor query(Uri uri, String[] projection, String selection, + String[] selectionArgs, String sortOrder) { + + // Constructs a new query builder and sets its table name + SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); + qb.setTables(MainTable.TABLE_NAME); + + switch (mUriMatcher.match(uri)) { + case MAIN: + // If the incoming URI is for main table. + qb.setProjectionMap(mNotesProjectionMap); + break; + + case MAIN_ID: + // The incoming URI is for a single row. + qb.setProjectionMap(mNotesProjectionMap); + qb.appendWhere(MainTable._ID + "=?"); + selectionArgs = DatabaseUtilsCompat.appendSelectionArgs(selectionArgs, + new String[] { uri.getLastPathSegment() }); + break; + + default: + throw new IllegalArgumentException("Unknown URI " + uri); + } + + + if (TextUtils.isEmpty(sortOrder)) { + sortOrder = MainTable.DEFAULT_SORT_ORDER; + } + + SQLiteDatabase db = mOpenHelper.getReadableDatabase(); + + Cursor c = qb.query(db, projection, selection, selectionArgs, + null /* no group */, null /* no filter */, sortOrder); + + c.setNotificationUri(getContext().getContentResolver(), uri); + return c; + } + + /** + * Return the MIME type for an known URI in the provider. + */ + @Override + public String getType(Uri uri) { + switch (mUriMatcher.match(uri)) { + case MAIN: + return MainTable.CONTENT_TYPE; + case MAIN_ID: + return MainTable.CONTENT_ITEM_TYPE; + default: + throw new IllegalArgumentException("Unknown URI " + uri); + } + } + + /** + * Handler inserting new data. + */ + @Override + public Uri insert(Uri uri, ContentValues initialValues) { + if (mUriMatcher.match(uri) != MAIN) { + // Can only insert into to main URI. + throw new IllegalArgumentException("Unknown URI " + uri); + } + + ContentValues values; + + if (initialValues != null) { + values = new ContentValues(initialValues); + } else { + values = new ContentValues(); + } + + if (values.containsKey(MainTable.COLUMN_NAME_DATA) == false) { + values.put(MainTable.COLUMN_NAME_DATA, ""); + } + + SQLiteDatabase db = mOpenHelper.getWritableDatabase(); + + long rowId = db.insert(MainTable.TABLE_NAME, null, values); + + // If the insert succeeded, the row ID exists. + if (rowId > 0) { + Uri noteUri = ContentUris.withAppendedId(MainTable.CONTENT_ID_URI_BASE, rowId); + getContext().getContentResolver().notifyChange(noteUri, null); + return noteUri; + } + + throw new SQLException("Failed to insert row into " + uri); + } + + /** + * Handle deleting data. + */ + @Override + public int delete(Uri uri, String where, String[] whereArgs) { + SQLiteDatabase db = mOpenHelper.getWritableDatabase(); + String finalWhere; + + int count; + + switch (mUriMatcher.match(uri)) { + case MAIN: + // If URI is main table, delete uses incoming where clause and args. + count = db.delete(MainTable.TABLE_NAME, where, whereArgs); + break; + + // If the incoming URI matches a single note ID, does the delete based on the + // incoming data, but modifies the where clause to restrict it to the + // particular note ID. + case MAIN_ID: + // If URI is for a particular row ID, delete is based on incoming + // data but modified to restrict to the given ID. + finalWhere = DatabaseUtilsCompat.concatenateWhere( + MainTable._ID + " = " + ContentUris.parseId(uri), where); + count = db.delete(MainTable.TABLE_NAME, finalWhere, whereArgs); + break; + + default: + throw new IllegalArgumentException("Unknown URI " + uri); + } + + getContext().getContentResolver().notifyChange(uri, null); + + return count; + } + + /** + * Handle updating data. + */ + @Override + public int update(Uri uri, ContentValues values, String where, String[] whereArgs) { + SQLiteDatabase db = mOpenHelper.getWritableDatabase(); + int count; + String finalWhere; + + switch (mUriMatcher.match(uri)) { + case MAIN: + // If URI is main table, update uses incoming where clause and args. + count = db.update(MainTable.TABLE_NAME, values, where, whereArgs); + break; + + case MAIN_ID: + // If URI is for a particular row ID, update is based on incoming + // data but modified to restrict to the given ID. + finalWhere = DatabaseUtilsCompat.concatenateWhere( + MainTable._ID + " = " + ContentUris.parseId(uri), where); + count = db.update(MainTable.TABLE_NAME, values, finalWhere, whereArgs); + break; + + default: + throw new IllegalArgumentException("Unknown URI " + uri); + } + + getContext().getContentResolver().notifyChange(uri, null); + + return count; + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + FragmentManager fm = getSupportFragmentManager(); + + // Create the list fragment and add it as our sole content. + if (fm.findFragmentById(android.R.id.content) == null) { + ThrottledLoaderListFragment list = new ThrottledLoaderListFragment(); + fm.beginTransaction().add(android.R.id.content, list).commit(); + } + } + + public static class ThrottledLoaderListFragment extends SherlockListFragment + implements LoaderManager.LoaderCallbacks<Cursor> { + + // Menu identifiers + static final int POPULATE_ID = Menu.FIRST; + static final int CLEAR_ID = Menu.FIRST+1; + + // This is the Adapter being used to display the list's data. + SimpleCursorAdapter mAdapter; + + // If non-null, this is the current filter the user has provided. + String mCurFilter; + + // Task we have running to populate the database. + AsyncTask<Void, Void, Void> mPopulatingTask; + + @Override public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + setEmptyText("No data. Select 'Populate' to fill with data from Z to A at a rate of 4 per second."); + setHasOptionsMenu(true); + + // Create an empty adapter we will use to display the loaded data. + mAdapter = new SimpleCursorAdapter(getActivity(), + android.R.layout.simple_list_item_1, null, + new String[] { MainTable.COLUMN_NAME_DATA }, + new int[] { android.R.id.text1 }, 0); + setListAdapter(mAdapter); + + // Start out with a progress indicator. + setListShown(false); + + // Prepare the loader. Either re-connect with an existing one, + // or start a new one. + getLoaderManager().initLoader(0, null, this); + } + + @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + MenuItem populateItem = menu.add(Menu.NONE, POPULATE_ID, 0, "Populate"); + populateItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); + MenuItem clearItem = menu.add(Menu.NONE, CLEAR_ID, 0, "Clear"); + clearItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); + } + + @Override public boolean onOptionsItemSelected(MenuItem item) { + final ContentResolver cr = getActivity().getContentResolver(); + + switch (item.getItemId()) { + case POPULATE_ID: + if (mPopulatingTask != null) { + mPopulatingTask.cancel(false); + } + mPopulatingTask = new AsyncTask<Void, Void, Void>() { + @Override protected Void doInBackground(Void... params) { + for (char c='Z'; c>='A'; c--) { + if (isCancelled()) { + break; + } + StringBuilder builder = new StringBuilder("Data "); + builder.append(c); + ContentValues values = new ContentValues(); + values.put(MainTable.COLUMN_NAME_DATA, builder.toString()); + cr.insert(MainTable.CONTENT_URI, values); + // Wait a bit between each insert. + try { + Thread.sleep(250); + } catch (InterruptedException e) { + } + } + return null; + } + }; + mPopulatingTask.execute((Void[]) null); + return true; + + case CLEAR_ID: + if (mPopulatingTask != null) { + mPopulatingTask.cancel(false); + mPopulatingTask = null; + } + AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() { + @Override protected Void doInBackground(Void... params) { + cr.delete(MainTable.CONTENT_URI, null, null); + return null; + } + }; + task.execute((Void[])null); + return true; + + default: + return super.onOptionsItemSelected(item); + } + } + + @Override public void onListItemClick(ListView l, View v, int position, long id) { + // Insert desired behavior here. + Log.i(TAG, "Item clicked: " + id); + } + + // These are the rows that we will retrieve. + static final String[] PROJECTION = new String[] { + MainTable._ID, + MainTable.COLUMN_NAME_DATA, + }; + + public Loader<Cursor> onCreateLoader(int id, Bundle args) { + CursorLoader cl = new CursorLoader(getActivity(), MainTable.CONTENT_URI, + PROJECTION, null, null, null); + cl.setUpdateThrottle(2000); // update at most every 2 seconds. + return cl; + } + + public void onLoadFinished(Loader<Cursor> loader, Cursor data) { + mAdapter.swapCursor(data); + + // The list should now be shown. + if (isResumed()) { + setListShown(true); + } else { + setListShownNoAnimation(true); + } + } + + public void onLoaderReset(Loader<Cursor> loader) { + mAdapter.swapCursor(null); + } + } +} + diff --git a/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/SampleList.java b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/SampleList.java new file mode 100755 index 0000000..5ec19f1 --- /dev/null +++ b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/SampleList.java @@ -0,0 +1,175 @@ +/* + * 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.actionbarsherlock.sample.fragments; + +import java.text.Collator; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.os.Bundle; +import android.view.View; +import android.widget.ListView; +import android.widget.SimpleAdapter; +import android.widget.Toast; + +import com.actionbarsherlock.app.SherlockListActivity; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.actionbarsherlock.view.SubMenu; + +public class SampleList extends SherlockListActivity { + public static int THEME = R.style.Theme_Sherlock; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Intent intent = getIntent(); + String path = intent.getStringExtra("com.example.android.apis.Path"); + + if (path == null) { + path = ""; + } + + setListAdapter(new SimpleAdapter(this, getData(path), + android.R.layout.simple_list_item_1, new String[] { "title" }, + new int[] { android.R.id.text1 })); + getListView().setTextFilterEnabled(true); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + SubMenu sub = menu.addSubMenu("Theme"); + sub.add(0, R.style.Theme_Sherlock, 0, "Default"); + sub.add(0, R.style.Theme_Sherlock_Light, 0, "Light"); + sub.add(0, R.style.Theme_Sherlock_Light_DarkActionBar, 0, "Light (Dark Action Bar)"); + sub.getItem().setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == android.R.id.home || item.getItemId() == 0) { + return false; + } + THEME = item.getItemId(); + Toast.makeText(this, "Theme changed to \"" + item.getTitle() + "\"", Toast.LENGTH_SHORT).show(); + return true; + } + + protected List<Map<String, Object>> getData(String prefix) { + List<Map<String, Object>> myData = new ArrayList<Map<String, Object>>(); + + Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); + mainIntent.addCategory("com.actionbarsherlock.sample.fragments.EXAMPLE"); + + PackageManager pm = getPackageManager(); + List<ResolveInfo> list = pm.queryIntentActivities(mainIntent, 0); + + if (null == list) + return myData; + + String[] prefixPath; + String prefixWithSlash = prefix; + + if (prefix.equals("")) { + prefixPath = null; + } else { + prefixPath = prefix.split("/"); + prefixWithSlash = prefix + "/"; + } + + int len = list.size(); + + Map<String, Boolean> entries = new HashMap<String, Boolean>(); + + for (int i = 0; i < len; i++) { + ResolveInfo info = list.get(i); + CharSequence labelSeq = info.loadLabel(pm); + String label = labelSeq != null + ? labelSeq.toString() + : info.activityInfo.name; + + if (prefixWithSlash.length() == 0 || label.startsWith(prefixWithSlash)) { + + String[] labelPath = label.split("/"); + + String nextLabel = prefixPath == null ? labelPath[0] : labelPath[prefixPath.length]; + + if ((prefixPath != null ? prefixPath.length : 0) == labelPath.length - 1) { + addItem(myData, nextLabel, activityIntent( + info.activityInfo.applicationInfo.packageName, + info.activityInfo.name)); + } else { + if (entries.get(nextLabel) == null) { + addItem(myData, nextLabel, browseIntent(prefix.equals("") ? nextLabel : prefix + "/" + nextLabel)); + entries.put(nextLabel, true); + } + } + } + } + + Collections.sort(myData, sDisplayNameComparator); + + return myData; + } + + private final static Comparator<Map<String, Object>> sDisplayNameComparator = + new Comparator<Map<String, Object>>() { + private final Collator collator = Collator.getInstance(); + + public int compare(Map<String, Object> map1, Map<String, Object> map2) { + return collator.compare(map1.get("title"), map2.get("title")); + } + }; + + protected Intent activityIntent(String pkg, String componentName) { + Intent result = new Intent(); + result.setClassName(pkg, componentName); + return result; + } + + protected Intent browseIntent(String path) { + Intent result = new Intent(); + result.setClass(this, SampleList.class); + result.putExtra("com.example.android.apis.Path", path); + return result; + } + + protected void addItem(List<Map<String, Object>> data, String name, Intent intent) { + Map<String, Object> temp = new HashMap<String, Object>(); + temp.put("title", name); + temp.put("intent", intent); + data.add(temp); + } + + @Override + @SuppressWarnings("unchecked") + protected void onListItemClick(ListView l, View v, int position, long id) { + Map<String, Object> map = (Map<String, Object>)l.getItemAtPosition(position); + + Intent intent = (Intent) map.get("intent"); + startActivity(intent); + } +} diff --git a/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/SendResult.java b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/SendResult.java new file mode 100755 index 0000000..fa1c28a --- /dev/null +++ b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/SendResult.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.actionbarsherlock.sample.fragments; + +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import com.actionbarsherlock.app.SherlockActivity; + + +/** + * Example of receiving a result from another activity. + */ +public class SendResult extends SherlockActivity +{ + /** + * Initialization of the Activity after it is first created. Must at least + * call {@link android.app.Activity#setContentView setContentView()} to + * describe what is to be displayed in the screen. + */ + @Override + protected void onCreate(Bundle savedInstanceState) + { + setTheme(SampleList.THEME); //Used for theme switching in samples + // Be sure to call the super class. + super.onCreate(savedInstanceState); + + // See assets/res/any/layout/hello_world.xml for this + // view layout definition, which is being set here as + // the content of our screen. + setContentView(R.layout.send_result); + + // Watch for button clicks. + Button button = (Button)findViewById(R.id.corky); + button.setOnClickListener(mCorkyListener); + button = (Button)findViewById(R.id.violet); + button.setOnClickListener(mVioletListener); + } + + private OnClickListener mCorkyListener = new OnClickListener() + { + public void onClick(View v) + { + // To send a result, simply call setResult() before your + // activity is finished. + setResult(RESULT_OK, (new Intent()).setAction("Corky!")); + finish(); + } + }; + + private OnClickListener mVioletListener = new OnClickListener() + { + public void onClick(View v) + { + // To send a result, simply call setResult() before your + // activity is finished. + setResult(RESULT_OK, (new Intent()).setAction("Violet!")); + finish(); + } + }; +} + diff --git a/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/Shakespeare.java b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/Shakespeare.java new file mode 100755 index 0000000..66e243f --- /dev/null +++ b/actionbarsherlock-samples/fragments/src/com/actionbarsherlock/sample/fragments/Shakespeare.java @@ -0,0 +1,223 @@ +package com.actionbarsherlock.sample.fragments; + +public final class Shakespeare { + /** + * Our data, part 1. + */ + public static final String[] TITLES = + { + "Henry IV (1)", + "Henry V", + "Henry VIII", + "Richard II", + "Richard III", + "Merchant of Venice", + "Othello", + "King Lear" + }; + + /** + * Our data, part 2. + */ + public static final String[] DIALOGUE = + { + "So shaken as we are, so wan with care," + + "Find we a time for frighted peace to pant," + + "And breathe short-winded accents of new broils" + + "To be commenced in strands afar remote." + + "No more the thirsty entrance of this soil" + + "Shall daub her lips with her own children's blood;" + + "Nor more shall trenching war channel her fields," + + "Nor bruise her flowerets with the armed hoofs" + + "Of hostile paces: those opposed eyes," + + "Which, like the meteors of a troubled heaven," + + "All of one nature, of one substance bred," + + "Did lately meet in the intestine shock" + + "And furious close of civil butchery" + + "Shall now, in mutual well-beseeming ranks," + + "March all one way and be no more opposed" + + "Against acquaintance, kindred and allies:" + + "The edge of war, like an ill-sheathed knife," + + "No more shall cut his master. Therefore, friends," + + "As far as to the sepulchre of Christ," + + "Whose soldier now, under whose blessed cross" + + "We are impressed and engaged to fight," + + "Forthwith a power of English shall we levy;" + + "Whose arms were moulded in their mothers' womb" + + "To chase these pagans in those holy fields" + + "Over whose acres walk'd those blessed feet" + + "Which fourteen hundred years ago were nail'd" + + "For our advantage on the bitter cross." + + "But this our purpose now is twelve month old," + + "And bootless 'tis to tell you we will go:" + + "Therefore we meet not now. Then let me hear" + + "Of you, my gentle cousin Westmoreland," + + "What yesternight our council did decree" + + "In forwarding this dear expedience.", + + "Hear him but reason in divinity," + + "And all-admiring with an inward wish" + + "You would desire the king were made a prelate:" + + "Hear him debate of commonwealth affairs," + + "You would say it hath been all in all his study:" + + "List his discourse of war, and you shall hear" + + "A fearful battle render'd you in music:" + + "Turn him to any cause of policy," + + "The Gordian knot of it he will unloose," + + "Familiar as his garter: that, when he speaks," + + "The air, a charter'd libertine, is still," + + "And the mute wonder lurketh in men's ears," + + "To steal his sweet and honey'd sentences;" + + "So that the art and practic part of life" + + "Must be the mistress to this theoric:" + + "Which is a wonder how his grace should glean it," + + "Since his addiction was to courses vain," + + "His companies unletter'd, rude and shallow," + + "His hours fill'd up with riots, banquets, sports," + + "And never noted in him any study," + + "Any retirement, any sequestration" + + "From open haunts and popularity.", + + "I come no more to make you laugh: things now," + + "That bear a weighty and a serious brow," + + "Sad, high, and working, full of state and woe," + + "Such noble scenes as draw the eye to flow," + + "We now present. Those that can pity, here" + + "May, if they think it well, let fall a tear;" + + "The subject will deserve it. Such as give" + + "Their money out of hope they may believe," + + "May here find truth too. Those that come to see" + + "Only a show or two, and so agree" + + "The play may pass, if they be still and willing," + + "I'll undertake may see away their shilling" + + "Richly in two short hours. Only they" + + "That come to hear a merry bawdy play," + + "A noise of targets, or to see a fellow" + + "In a long motley coat guarded with yellow," + + "Will be deceived; for, gentle hearers, know," + + "To rank our chosen truth with such a show" + + "As fool and fight is, beside forfeiting" + + "Our own brains, and the opinion that we bring," + + "To make that only true we now intend," + + "Will leave us never an understanding friend." + + "Therefore, for goodness' sake, and as you are known" + + "The first and happiest hearers of the town," + + "Be sad, as we would make ye: think ye see" + + "The very persons of our noble story" + + "As they were living; think you see them great," + + "And follow'd with the general throng and sweat" + + "Of thousand friends; then in a moment, see" + + "How soon this mightiness meets misery:" + + "And, if you can be merry then, I'll say" + + "A man may weep upon his wedding-day.", + + "First, heaven be the record to my speech!" + + "In the devotion of a subject's love," + + "Tendering the precious safety of my prince," + + "And free from other misbegotten hate," + + "Come I appellant to this princely presence." + + "Now, Thomas Mowbray, do I turn to thee," + + "And mark my greeting well; for what I speak" + + "My body shall make good upon this earth," + + "Or my divine soul answer it in heaven." + + "Thou art a traitor and a miscreant," + + "Too good to be so and too bad to live," + + "Since the more fair and crystal is the sky," + + "The uglier seem the clouds that in it fly." + + "Once more, the more to aggravate the note," + + "With a foul traitor's name stuff I thy throat;" + + "And wish, so please my sovereign, ere I move," + + "What my tongue speaks my right drawn sword may prove.", + + "Now is the winter of our discontent" + + "Made glorious summer by this sun of York;" + + "And all the clouds that lour'd upon our house" + + "In the deep bosom of the ocean buried." + + "Now are our brows bound with victorious wreaths;" + + "Our bruised arms hung up for monuments;" + + "Our stern alarums changed to merry meetings," + + "Our dreadful marches to delightful measures." + + "Grim-visaged war hath smooth'd his wrinkled front;" + + "And now, instead of mounting barded steeds" + + "To fright the souls of fearful adversaries," + + "He capers nimbly in a lady's chamber" + + "To the lascivious pleasing of a lute." + + "But I, that am not shaped for sportive tricks," + + "Nor made to court an amorous looking-glass;" + + "I, that am rudely stamp'd, and want love's majesty" + + "To strut before a wanton ambling nymph;" + + "I, that am curtail'd of this fair proportion," + + "Cheated of feature by dissembling nature," + + "Deformed, unfinish'd, sent before my time" + + "Into this breathing world, scarce half made up," + + "And that so lamely and unfashionable" + + "That dogs bark at me as I halt by them;" + + "Why, I, in this weak piping time of peace," + + "Have no delight to pass away the time," + + "Unless to spy my shadow in the sun" + + "And descant on mine own deformity:" + + "And therefore, since I cannot prove a lover," + + "To entertain these fair well-spoken days," + + "I am determined to prove a villain" + + "And hate the idle pleasures of these days." + + "Plots have I laid, inductions dangerous," + + "By drunken prophecies, libels and dreams," + + "To set my brother Clarence and the king" + + "In deadly hate the one against the other:" + + "And if King Edward be as true and just" + + "As I am subtle, false and treacherous," + + "This day should Clarence closely be mew'd up," + + "About a prophecy, which says that 'G'" + + "Of Edward's heirs the murderer shall be." + + "Dive, thoughts, down to my soul: here" + + "Clarence comes.", + + "To bait fish withal: if it will feed nothing else," + + "it will feed my revenge. He hath disgraced me, and" + + "hindered me half a million; laughed at my losses," + + "mocked at my gains, scorned my nation, thwarted my" + + "bargains, cooled my friends, heated mine" + + "enemies; and what's his reason? I am a Jew. Hath" + + "not a Jew eyes? hath not a Jew hands, organs," + + "dimensions, senses, affections, passions? fed with" + + "the same food, hurt with the same weapons, subject" + + "to the same diseases, healed by the same means," + + "warmed and cooled by the same winter and summer, as" + + "a Christian is? If you prick us, do we not bleed?" + + "if you tickle us, do we not laugh? if you poison" + + "us, do we not die? and if you wrong us, shall we not" + + "revenge? If we are like you in the rest, we will" + + "resemble you in that. If a Jew wrong a Christian," + + "what is his humility? Revenge. If a Christian" + + "wrong a Jew, what should his sufferance be by" + + "Christian example? Why, revenge. The villany you" + + "teach me, I will execute, and it shall go hard but I" + + "will better the instruction.", + + "Virtue! a fig! 'tis in ourselves that we are thus" + + "or thus. Our bodies are our gardens, to the which" + + "our wills are gardeners: so that if we will plant" + + "nettles, or sow lettuce, set hyssop and weed up" + + "thyme, supply it with one gender of herbs, or" + + "distract it with many, either to have it sterile" + + "with idleness, or manured with industry, why, the" + + "power and corrigible authority of this lies in our" + + "wills. If the balance of our lives had not one" + + "scale of reason to poise another of sensuality, the" + + "blood and baseness of our natures would conduct us" + + "to most preposterous conclusions: but we have" + + "reason to cool our raging motions, our carnal" + + "stings, our unbitted lusts, whereof I take this that" + + "you call love to be a sect or scion.", + + "Blow, winds, and crack your cheeks! rage! blow!" + + "You cataracts and hurricanoes, spout" + + "Till you have drench'd our steeples, drown'd the cocks!" + + "You sulphurous and thought-executing fires," + + "Vaunt-couriers to oak-cleaving thunderbolts," + + "Singe my white head! And thou, all-shaking thunder," + + "Smite flat the thick rotundity o' the world!" + + "Crack nature's moulds, an germens spill at once," + + "That make ingrateful man!" + }; +} |