Java tutorial
/* Copyright (C) 2013, Martin Stoyanov * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU Affero General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more * details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.mstoyanov.music_lessons; import java.util.ArrayList; import java.util.List; import com.mstoyanov.music_lessons.data.SchoolContract; import com.mstoyanov.music_lessons.model.Actions; import com.mstoyanov.music_lessons.model.ActionsAdapter; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; 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; import android.widget.AdapterView.OnItemClickListener; import android.widget.ListView; import android.widget.SimpleCursorAdapter; import android.widget.TextView; import android.support.v4.app.Fragment; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; /* A fragment of the MainActivity, under tab 2 of total 3 tabs, * which Displays a list of all students. * * In single pane mode it calls StudentDetailsActivity, with student * Id passed in. The StudentDetailsActivity contains the clicked student's * contact data, so call, SMS or email action can be performed. * * In dual pane mode the layout of the StudentDetailsActivity appears * on the right side of the screen of the StudentsFragment. */ public class StudentsFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor>, OnItemClickListener { private boolean dualPane; // flag private int selectedStudent; // index // there are students entered into the database: private boolean studentsEntered; private int studentId; private List<Actions> actions; // call, SMS, email private SimpleCursorAdapter studentsAdapter; private ActionsAdapter studentDetailsAdapter; private ListView studentsList; private ListView studentDetailsList; private TextView firstNameTextView; private TextView lastNameTextView; private TextView firstNameLabel; private TextView lastNameLabel; private static final int STUDENTS_LOADER = 0; private static final int STUDENT_DETAILS_LOADER = 1; private static final int LESSONS_LOADER = 2; private static final String selection = "studentID = ?"; private String[] selectionArgs = new String[1]; private static final String[] projection = { SchoolContract.Students.COLUMN_NAME_STUDENT_ID + " as _id", SchoolContract.Students.COLUMN_NAME_FIRST_NAME, SchoolContract.Students.COLUMN_NAME_LAST_NAME }; private static final String sortOrder = SchoolContract.Students.COLUMN_NAME_FIRST_NAME + ", " + SchoolContract.Students.COLUMN_NAME_LAST_NAME; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); View view = inflater.inflate(R.layout.students_fragment, container, false); return view; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); setHasOptionsMenu(true); String[] fromColumns = new String[] { "firstName", "lastName" }; int[] toViews = new int[] { R.id.firstName, R.id.lastName }; studentsAdapter = new SimpleCursorAdapter(getActivity(), R.layout.student_list_item, // layout null, // no cursor is created yet fromColumns, // columns toViews, // UI controls 0 // flags ); studentsList = (ListView) getActivity().findViewById(R.id.students_list); studentsList.setOnItemClickListener(this); studentsList.setAdapter(studentsAdapter); // determine the current layout: View studentDetailsView = getActivity().findViewById(R.id.student_details_pane); dualPane = studentDetailsView != null && studentDetailsView.getVisibility() == View.VISIBLE; if (dualPane) { if (savedInstanceState != null) { selectedStudent = savedInstanceState.getInt("SELECTED_STUDENT", 0); } else if (getActivity().getIntent() != null) { selectedStudent = getActivity().getIntent().getIntExtra("SELECTED_STUDENT", selectedStudent); } firstNameLabel = ((TextView) getActivity().findViewById(R.id.label_fname_students)); firstNameTextView = ((TextView) getActivity().findViewById(R.id.fname_students)); lastNameLabel = ((TextView) getActivity().findViewById(R.id.label_lname_students)); lastNameTextView = ((TextView) getActivity().findViewById(R.id.lname_students)); studentDetailsList = (ListView) getActivity().findViewById(R.id.student_details_list); studentDetailsList.setOnItemClickListener(this); actions = new ArrayList<Actions>(); studentDetailsAdapter = new ActionsAdapter(getActivity(), actions); studentDetailsList.setAdapter(studentDetailsAdapter); } } @Override public void onResume() { super.onResume(); getLoaderManager().restartLoader(STUDENTS_LOADER, null, this); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { if (dualPane) { getActivity().getMenuInflater().inflate(R.menu.student_details_menu, menu); } } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_edit_student: if (studentsEntered) { Intent intent = new Intent(getActivity(), EditStudentActivity.class); intent.putExtra("STUDENT_ID", studentId); intent.putExtra("DUAL_PANE", dualPane); intent.putExtra("SELECTED_STUDENT", selectedStudent); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); return true; } return true; case R.id.menu_delete_student: if (studentsEntered) { // Create AlertDialog: AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity()); alertDialogBuilder.setMessage("Delete student?") .setPositiveButton("Delete", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // delete the selected student: getActivity().getContentResolver().delete(SchoolContract.STUDENTS_TABLE_CONTENTURI, // uri selection, // selection selectionArgs // selectionArgs ); // check if this student has associated // lessons, and delete them, if so: getLoaderManager().initLoader(LESSONS_LOADER, null, StudentsFragment.this); // Navigate back to the main screen: Intent intent = new Intent(getActivity(), MainActivity.class); // select the "Students" tab: intent.putExtra("SELECTED_TAB", 1); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); } }).setNegativeButton("Cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); AlertDialog alertDialog = alertDialogBuilder.create(); alertDialog.show(); return true; } return true; default: throw new IllegalArgumentException("Invalid ItemId: " + item.getItemId()); } } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); if (dualPane) { outState.putInt("SELECTED_STUDENT", selectedStudent); } } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { switch (parent.getId()) { case R.id.students_list: Cursor cursor = (Cursor) parent.getItemAtPosition(position); studentId = cursor.getInt(cursor.getColumnIndex("_id")); String firstName = cursor.getString(cursor.getColumnIndex("firstName")); String lastName = cursor.getString(cursor.getColumnIndex("lastName")); if (dualPane) { studentsList.setItemChecked(position, true); selectedStudent = position; selectionArgs[0] = String.valueOf(studentId); firstNameLabel.setText("First Name"); firstNameTextView.setText(firstName); lastNameLabel.setText("Last Name"); lastNameTextView.setText(lastName); getLoaderManager().restartLoader(STUDENT_DETAILS_LOADER, null, this); } else { Intent intent = new Intent(getActivity(), StudentDetailsActivity.class); intent.putExtra("STUDENT_ID", studentId); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); } break; case R.id.student_details_list: Actions action = actions.get(position); switch (action.getType()) { case Actions.ACTION_CALL: Uri callUri = Uri.parse("tel:" + action.getData()); Intent intent = new Intent(Intent.ACTION_CALL, callUri); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); break; case Actions.ACTION_EMAIL: intent = new Intent(Intent.ACTION_SEND); intent.setType("plain/text"); intent.putExtra(Intent.EXTRA_EMAIL, new String[] { action.getData() }); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); break; case Actions.ACTION_SMS: Uri smsUri = Uri.parse("sms:" + action.getData()); intent = new Intent(Intent.ACTION_VIEW, smsUri); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); default: throw new IllegalArgumentException("Invalid action type: " + action.getType()); } default: throw new IllegalArgumentException("Invalid parentId: " + parent.getId()); } } @Override public Loader<Cursor> onCreateLoader(int loaderID, Bundle bundle) { switch (loaderID) { case STUDENTS_LOADER: return new CursorLoader(getActivity(), // context SchoolContract.STUDENTS_TABLE_CONTENTURI, // uri projection, // projection null, // selection null, // selectionArgs sortOrder // firstName, lastName ); case STUDENT_DETAILS_LOADER: return new CursorLoader(getActivity(), // context SchoolContract.STUDENTS_TABLE_CONTENTURI, // uri null, // projection selection, // selection selectionArgs, // selectionArgs null // sortOrder ); case LESSONS_LOADER: return new CursorLoader(getActivity(), // context SchoolContract.SCHEDULE_TABLE_CONTENTURI, // uri null, // projection selection, // selection selectionArgs, // selectionArgs null // sortOrder ); default: throw new IllegalArgumentException("Invalid loaderID: " + loaderID); } } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { switch (loader.getId()) { case STUDENTS_LOADER: studentsAdapter.swapCursor(cursor); // select the first student, or recover previous state, if the // list is not empty: if (dualPane && cursor.getCount() > 0) { studentsEntered = true; onItemClick(studentsList, studentsList.getChildAt(selectedStudent), selectedStudent, -1); } break; case STUDENT_DETAILS_LOADER: if (cursor != null) { cursor.moveToFirst(); actions.clear(); String homePhone = cursor.getString(cursor.getColumnIndex("homePhone")); if (homePhone.length() > 0) { actions.add(new Actions("Home", homePhone, Actions.ACTION_CALL)); } String cellPhone = cursor.getString(cursor.getColumnIndex("cellPhone")); if (cellPhone.length() > 0) { actions.add(new Actions("Mobile", cellPhone, Actions.ACTION_CALL)); actions.add(new Actions("SMS", cellPhone, Actions.ACTION_SMS)); } String workPhone = cursor.getString(cursor.getColumnIndex("workPhone")); if (workPhone.length() > 0) { actions.add(new Actions("Office", workPhone, Actions.ACTION_CALL)); } String email = cursor.getString(cursor.getColumnIndex("email")); if (email.length() > 0) { actions.add(new Actions("Email", email, Actions.ACTION_EMAIL)); } } studentDetailsAdapter.notifyDataSetChanged(); break; case LESSONS_LOADER: if (cursor.getCount() > 0) { getActivity().getContentResolver().delete(SchoolContract.SCHEDULE_TABLE_CONTENTURI, // uri selection, // selection selectionArgs // selectionArgs ); } break; default: throw new IllegalArgumentException("Unknown loaderId " + loader.getId()); } } @Override public void onLoaderReset(Loader<Cursor> loader) { switch (loader.getId()) { case STUDENTS_LOADER: studentsAdapter.swapCursor(null); break; case STUDENT_DETAILS_LOADER: studentDetailsAdapter.clear(); break; case LESSONS_LOADER: // at this point the cursor is out of scope and respectively null; // no adapters have been created to clear; break; } } }