Java tutorial
/* * Copyright 2012 Michael Potter * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ /* * RecipeListFragment.java - Displays a list of recipes stored in the database. * Recipes are filtered and sorted based on options and searches. */ package net.potterpcs.recipebook; import java.io.IOException; import net.potterpcs.recipebook.RecipeData.Recipe; import android.content.ContentUris; import android.content.Intent; import android.database.Cursor; import android.media.MediaScannerConnection; import android.net.Uri; import android.os.Bundle; import android.support.v4.app.FragmentTransaction; import android.support.v4.app.ListFragment; import android.support.v4.view.MenuItemCompat; import android.support.v4.widget.SimpleCursorAdapter; import android.support.v4.widget.SimpleCursorAdapter.ViewBinder; import android.text.format.DateUtils; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView.AdapterContextMenuInfo; import android.widget.ListAdapter; import android.widget.ListView; import android.widget.RatingBar; import android.widget.TextView; public class RecipeListFragment extends ListFragment { // Tag for logging // static final String TAG = "RecipeListFragment"; // Projections for the cursor adapter static final String[] FROM = { RecipeData.RT_ID, RecipeData.RT_NAME, RecipeData.RT_DESCRIPTION, RecipeData.RT_CREATOR, RecipeData.RT_RATING, RecipeData.RT_TIME }; static final int[] TO = { R.id.rowhidden, R.id.rowname, R.id.rowdescription, R.id.rowcreator, R.id.rowrating, R.id.rowtime }; // The cursor holding our list Cursor cursor; // The view binder fixes up the UI elements that the basic // SimpleCursorAdapter can't handle. For us, that's the // rating bar and the time display. static final ViewBinder VIEW_BINDER = new ViewBinder() { @Override public boolean setViewValue(View view, Cursor cursor, int columnIndex) { if (view.getId() == R.id.rowrating) { RatingBar rating = (RatingBar) view; rating.setRating(cursor.getFloat(columnIndex)); return true; } else if (view.getId() == R.id.rowtime) { // TODO: this is a hack until we can get something better TextView theTime = (TextView) view; theTime.setText(DateUtils.formatElapsedTime(cursor.getInt(columnIndex))); return true; } else { return false; } } }; private SimpleCursorAdapter adapter; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.recipelist, null); } @Override public void onStart() { super.onStart(); registerForContextMenu(getListView()); } @Override public void onStop() { super.onStop(); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); adapter = new SimpleCursorAdapter(getActivity(), R.layout.rowlayout, null, FROM, TO, 0); adapter.setViewBinder(VIEW_BINDER); setListAdapter(adapter); } @Override public void onResume() { super.onResume(); retrieveRecipes(); } @Override public void onPause() { super.onPause(); // We need to swap a null Cursor into the adapter before we close // the Cursor we're using, otherwise crashes can happen as the // ListView tries to access a closed cursor. adapter.swapCursor(null); cursor.close(); } private void retrieveRecipes() { RecipeBookActivity activity = (RecipeBookActivity) getActivity(); RecipeBook app = (RecipeBook) activity.getApplication(); RecipeData data = app.getData(); String sort; switch (activity.getSortKey()) { case R.id.menusortrating: sort = RecipeData.RT_RATING; break; case R.id.menusorttime: sort = RecipeData.RT_TIME; break; case R.id.menusortdate: sort = RecipeData.RT_DATE; break; case R.id.menusortname: default: sort = RecipeData.RT_NAME; break; } if (activity.getSortDirection()) { // descending sort sort += RecipeBookActivity.SORT_DESCENDING; } getRecipes(activity, data, sort); } void getRecipes(RecipeBookActivity activity, RecipeData data, String sortData) { // This uses the "multi-query" method so filtering previous searches works cursor = data.query(activity.getSearchQuery(), activity.getSearchTag(), activity.getMinTime(), activity.getMaxTime(), sortData); int nr = cursor.getCount(); adapter.swapCursor(cursor); TextView footer = (TextView) activity.findViewById(R.id.footertext); footer.setText(String.format(activity.getResources().getString(R.string.numrecipes), nr)); } long[] getItemIds() { ListAdapter adapter = getListAdapter(); long[] ids = new long[adapter.getCount()]; for (int i = 0; i < ids.length; i++) { ids[i] = adapter.getItemId(i); } return ids; } public void onExportItemSelected(MenuItem item) { RecipeData data = ((RecipeBook) getActivity().getApplication()).getData(); try { String filename = data.exportRecipes(getItemIds()); if (filename != null) { // Log.v(TAG, "Exported to " + filename); MediaScannerConnection.scanFile(getActivity(), new String[] { filename }, null, null); } else { // Log.e(TAG, "Unable to export recipes"); } } catch (IOException e) { // Log.e(TAG, e.toString()); } } @Override public void onDestroyView() { super.onDestroyView(); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.listviewmenu, menu); MenuItemCompat.setShowAsAction(menu.findItem(R.id.switchtoflipbook), MenuItem.SHOW_AS_ACTION_IF_ROOM); } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); MenuInflater inflater = getActivity().getMenuInflater(); inflater.inflate(R.menu.recipelistcontext, menu); } @Override public void onListItemClick(ListView l, View v, int position, long id) { Uri uri = new Uri.Builder().scheme("content").authority("net.potterpcs.recipebook").build(); uri = ContentUris.withAppendedId(uri, id); // Log.i(TAG, uri.toString()); // Intent intent = new Intent(RecipeBook.OPEN_RECIPE_ACTION, uri); Intent intent = new Intent(getActivity(), RecipeViewer.class).setData(uri); startActivity(intent); } @Override public boolean onContextItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.ctxmenuedit: onEditItemSelected(item); return true; case R.id.ctxmenudelete: onDeleteItemSelected(item); return true; case R.id.ctxmenurate: onRateItemSelected(item); return true; case R.id.ctxmenutag: onTagItemSelected(item); return true; default: return super.onContextItemSelected(item); } } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.switchtoflipbook: RecipeBookActivity activity = (RecipeBookActivity) getActivity(); activity.switchToFlipBook(); return true; case R.id.menuexport: onExportItemSelected(item); return true; default: return super.onOptionsItemSelected(item); } } public void onEditItemSelected(MenuItem item) { AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo(); Uri uri = new Uri.Builder().scheme("content").authority("net.potterpcs.recipebook").build(); uri = ContentUris.withAppendedId(uri, info.id); // Log.i(TAG, "edit option selected, id=" + info.id); Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT, uri); startActivity(intent); } public void onDeleteItemSelected(MenuItem item) { AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo(); // Log.i(TAG, "delete option selected, id=" + info.id); RecipeBookActivity activity = (RecipeBookActivity) getActivity(); RecipeData data = ((RecipeBook) activity.getApplication()).getData(); data.deleteRecipe(info.id); retrieveRecipes(); } public void onRateItemSelected(MenuItem item) { AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo(); // Log.i(TAG, "rate option selected, id=" + info.id); RecipeBookActivity activity = (RecipeBookActivity) getActivity(); FragmentTransaction ft = activity.getSupportFragmentManager().beginTransaction(); Recipe r = ((RecipeBook) activity.getApplication()).getData().getSingleRecipeObject(info.id); RateRecipeDialog rrd = RateRecipeDialog.newInstance(this, r.id, r.name, r.rating); rrd.show(ft, "dialog"); } public void onTagItemSelected(MenuItem item) { AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo(); // Log.i(TAG, "tag option selected, id=" + info.id); RecipeBookActivity activity = (RecipeBookActivity) getActivity(); FragmentTransaction ft = activity.getSupportFragmentManager().beginTransaction(); Recipe r = ((RecipeBook) activity.getApplication()).getData().getSingleRecipeObject(info.id); TagRecipeDialog trd = TagRecipeDialog.newInstance(r.id); trd.show(ft, "dialog"); } public void onRateDialogDismissed() { retrieveRecipes(); } }