Java tutorial
package com.wmstein.transektcount; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.os.Bundle; import android.support.v4.app.NavUtils; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.LinearLayout; import android.widget.ScrollView; import android.widget.Toast; import com.wmstein.transektcount.database.AlertDataSource; import com.wmstein.transektcount.database.Count; import com.wmstein.transektcount.database.CountDataSource; import com.wmstein.transektcount.database.Section; import com.wmstein.transektcount.database.SectionDataSource; import com.wmstein.transektcount.widgets.CountEditWidget; import com.wmstein.transektcount.widgets.EditNotesWidget; import com.wmstein.transektcount.widgets.EditTitleWidget; import java.util.ArrayList; import java.util.List; /************************************************************************* * Edit the current section list (change, delete) and insert new species * EditSectionActivity is called from CountingActivity. * Uses CountEditWidget.java, EditTitleWidget.java, EditNotesWidget.java, * activity_edit_section.xml, widget_edit_title.xml, widget_edit_notes.xml. * Based on EditProjectActivity.java by milo on 05/05/2014. * Changed by wmstein on 18.02.2016 */ public class EditSectionActivity extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener { TransektCountApplication transektCount; SharedPreferences prefs; public static String TAG = "TransektCountEditSectionActivity"; // the actual data Section section; List<Count> counts; private SectionDataSource sectionDataSource; private CountDataSource countDataSource; private AlertDataSource alertDataSource; int section_id; LinearLayout counts_area; LinearLayout notes_area; EditTitleWidget etw; EditNotesWidget enw; private View markedForDelete; private int idToDelete; AlertDialog.Builder areYouSure; public ArrayList<String> countNames; public ArrayList<String> countCodes; public ArrayList<String> cmpCountNames; public ArrayList<Integer> countIds; public ArrayList<CountEditWidget> savedCounts; private Bitmap bMap; private BitmapDrawable bg; //added for duplicates check private boolean dupPref; String new_count_name = ""; String oldname; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_edit_section); countNames = new ArrayList<>(); countCodes = new ArrayList<>(); countIds = new ArrayList<>(); savedCounts = new ArrayList<>(); notes_area = (LinearLayout) findViewById(R.id.editingNotesLayout); counts_area = (LinearLayout) findViewById(R.id.editingCountsLayout); Bundle extras = getIntent().getExtras(); if (extras != null) { section_id = extras.getInt("section_id"); } /* * Restore any edit widgets the user has added previously */ if (savedInstanceState != null) { if (savedInstanceState.getSerializable("savedCounts") != null) { savedCounts = (ArrayList<CountEditWidget>) savedInstanceState.getSerializable("savedCounts"); } } // Load preferences transektCount = (TransektCountApplication) getApplication(); prefs = TransektCountApplication.getPrefs(); prefs.registerOnSharedPreferenceChangeListener(this); boolean brightPref = prefs.getBoolean("pref_bright", true); dupPref = prefs.getBoolean("pref_duplicate", true); // Set full brightness of screen if (brightPref) { getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); WindowManager.LayoutParams params = getWindow().getAttributes(); params.screenBrightness = 1.0f; getWindow().setAttributes(params); } ScrollView counting_screen = (ScrollView) findViewById(R.id.editingScreen); bMap = transektCount.decodeBitmap(R.drawable.kbackground, transektCount.width, transektCount.height); bg = new BitmapDrawable(counting_screen.getResources(), bMap); counting_screen.setBackground(bg); } @Override protected void onResume() { super.onResume(); // build the Edit Section screen // clear any existing views counts_area.removeAllViews(); notes_area.removeAllViews(); // setup the data sources sectionDataSource = new SectionDataSource(this); sectionDataSource.open(); countDataSource = new CountDataSource(this); countDataSource.open(); alertDataSource = new AlertDataSource(this); alertDataSource.open(); // load the sections data section = sectionDataSource.getSection(section_id); oldname = section.name; try { getSupportActionBar().setTitle(oldname); } catch (NullPointerException e) { Log.i(TAG, "NullPointerException: No section name!"); } // display the section title etw = new EditTitleWidget(this, null); etw.setSectionName(oldname); etw.setWidgetTitle(getString(R.string.titleEdit)); notes_area.addView(etw); // display editable section notes; the same class // is being used for both due to being lazy enw = new EditNotesWidget(this, null); enw.setSectionNotes(section.notes); enw.setWidgetNotes(getString(R.string.notesHere)); enw.setHint(getString(R.string.notesHint)); enw.requestFocus(); notes_area.addView(enw); // load the counts data counts = countDataSource.getAllCountsForSection(section.id); // display all the counts by adding them to countCountLayout for (Count count : counts) { // widget CountEditWidget cew = new CountEditWidget(this, null); cew.setCountName(count.name); cew.setCountCode(count.code); cew.setCountId(count.id); counts_area.addView(cew); } for (CountEditWidget cew : savedCounts) { counts_area.addView(cew); } getCountNames(); } @Override protected void onSaveInstanceState(Bundle outState) { /* * Before these widgets can be serialised they must be removed from their parent, or else * trying to add them to a new parent causes a crash because they've already got one. */ super.onSaveInstanceState(outState); for (CountEditWidget cew : savedCounts) { ((ViewGroup) cew.getParent()).removeView(cew); } outState.putSerializable("savedCounts", savedCounts); } @Override protected void onPause() { super.onPause(); // close the data sources sectionDataSource.close(); countDataSource.close(); alertDataSource.close(); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.edit_section, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.home) { Intent intent = NavUtils.getParentActivityIntent(this); intent.putExtra("section_id", section_id); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); NavUtils.navigateUpTo(this, intent); } else if (id == R.id.menuSaveExit) { if (saveData()) { savedCounts.clear(); super.finish(); } } else if (id == R.id.newCount) { newCount(findViewById(R.id.editingCountsLayout)); } return super.onOptionsItemSelected(item); } public void getCountNames() { /* * The plan here is that names, codes and ids arrays contain the entries in the same * order, so I can link count and code name to its id by knowing the index. */ countNames.clear(); countCodes.clear(); countIds.clear(); int childcount = counts_area.getChildCount(); for (int i = 0; i < childcount; i++) { CountEditWidget cew = (CountEditWidget) counts_area.getChildAt(i); String name = cew.getCountName(); String code = cew.getCountCode(); // ignore count widgets where the user has filled nothing in. // Id will be 0 if this is a new count. if (isNotEmpty(name)) { countNames.add(name); countCodes.add(code); countIds.add(cew.countId); } } } // Compare count names for duplicates and returns name of 1. duplicate found public String compCountNames() { String name = ""; String isDbl = ""; cmpCountNames = new ArrayList<String>(); int childcount = counts_area.getChildCount(); // for all CountEditWidgets for (int i = 0; i < childcount; i++) { CountEditWidget cew = (CountEditWidget) counts_area.getChildAt(i); name = cew.getCountName(); if (cmpCountNames.contains(name)) { isDbl = name; //Log.i(TAG, "Double name = " + isDbl); break; } cmpCountNames.add(name); } return isDbl; } public void saveAndExit(View view) { if (saveData()) { savedCounts.clear(); super.finish(); } } public boolean saveData() { // save section notes only if they have changed boolean savesection = false; String newtitle = etw.getSectionName(); if (isNotEmpty(newtitle)) { //check if this is not a duplicate of an existing name if (compSectionNames(newtitle)) { Toast.makeText(EditSectionActivity.this, newtitle + " " + getString(R.string.isdouble), Toast.LENGTH_SHORT).show(); savesection = false; } else { section.name = newtitle; savesection = true; } } else { Toast.makeText(EditSectionActivity.this, newtitle + " " + getString(R.string.isempty), Toast.LENGTH_SHORT).show(); savesection = false; } // Always add notes if the user has written some... String newnotes = enw.getSectionNotes(); if (isNotEmpty(newnotes) && savesection) { section.notes = newnotes; } //...if they haven't, only save if the current notes have a value else { if (isNotEmpty(section.notes)) { section.notes = newnotes; } } boolean retValue = false; if (savesection) { sectionDataSource.saveSection(section); // save counts (species list) String isDbl = ""; int childcount; //No. of species in list childcount = counts_area.getChildCount(); //Log.i(TAG, "childcount: " + String.valueOf(childcount)); // check for unique species names if (dupPref) { isDbl = compCountNames(); if (isDbl.equals("")) { // do for all species for (int i = 0; i < childcount; i++) { CountEditWidget cew = (CountEditWidget) counts_area.getChildAt(i); if (isNotEmpty(cew.getCountName())) { //Log.i(TAG, "cew: " + String.valueOf(cew.countId) + ", " + cew.getCountName()); // create or save if (cew.countId == 0) { //Log.i(TAG, "Creating!"); //returns newCount countDataSource.createCount(section_id, cew.getCountName(), cew.getCountCode()); } else { //Log.i(TAG, "Updating!"); countDataSource.updateCountName(cew.countId, cew.getCountName(), cew.getCountCode()); } retValue = true; } } } else { Toast.makeText(this, isDbl + " " + getString(R.string.isdouble), Toast.LENGTH_SHORT).show(); retValue = false; } } if (retValue) { Toast.makeText(EditSectionActivity.this, getString(R.string.sectSaving) + " " + section.name + "!", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, getString(R.string.empty), Toast.LENGTH_SHORT).show(); } } return retValue; } // Compare section names for duplicates and return TRUE when duplicate found // created by wmstein on 10.04.2016 public boolean compSectionNames(String newname) { boolean isDbl = false; String sname; if (newname.equals(oldname)) { return false; // name has not changed } List<Section> sectionList = sectionDataSource.getAllSectionNames(); int childcount = sectionList.size() + 1; // for all Sections for (int i = 1; i < childcount; i++) { section = sectionDataSource.getSection(i); sname = section.name; //Log.i(TAG, "sname = " + sname); if (newname.equals(sname)) { isDbl = true; //Log.i(TAG, "Double name = " + sname); break; } } return isDbl; } // Scroll to end of view, by wmstein public void ScrollToEndOfView(View scrlV) { int scroll_amount = scrlV.getBottom(); int scrollY = scroll_amount; boolean pageend = false; while (!pageend) { scrlV.scrollTo(0, scroll_amount); //scroll scroll_amount = scroll_amount + scroll_amount; //increase scroll_amount scrollY = scrollY + scrlV.getScrollY(); //scroll position 1. row if (scroll_amount > scrollY) { pageend = true; } } } // add new CountEditWidget to view public void newCount(View view) { CountEditWidget cew = new CountEditWidget(this, null); counts_area.addView(cew); // adds a child view cew // Scroll to end of view, added by wmstein View scrollV = findViewById(R.id.editingScreen); ScrollToEndOfView(scrollV); // set focus to cew, added by wmstein cew.requestFocus(); savedCounts.add(cew); } // purging counts (with associated alerts) public void deleteCount(View view) { /* * These global variables keep a track of the view containing an alert to be deleted and also the id * of the alert itself, to make sure that they're available inside the code for the alert dialog by * which they will be deleted. */ markedForDelete = view; idToDelete = (Integer) view.getTag(); if (idToDelete == 0) { // the actual CountEditWidget is two levels up from the button in which it is embedded counts_area.removeView((CountEditWidget) view.getParent().getParent()); } else { //Log.i(TAG, "(2) View tag was " + String.valueOf(deleteAnAlert)); // before removing this widget it is necessary to do the following: // (1) Check the user is sure they want to delete it and, if so... // (2) Delete the associated alert from the database. areYouSure = new AlertDialog.Builder(this); areYouSure.setTitle(getString(R.string.deleteCount)); areYouSure.setMessage(getString(R.string.reallyDeleteCount)); areYouSure.setPositiveButton(R.string.yesDeleteIt, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { // go ahead for the delete countDataSource.deleteCountById(idToDelete); counts_area.removeView((CountEditWidget) markedForDelete.getParent().getParent()); new_count_name = ""; } }); areYouSure.setNegativeButton(R.string.noCancel, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { // Cancelled. } }); areYouSure.show(); } getCountNames(); } public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { ScrollView counting_screen = (ScrollView) findViewById(R.id.editingScreen); counting_screen.setBackground(null); bMap = transektCount.decodeBitmap(R.drawable.kbackground, transektCount.width, transektCount.height); bg = new BitmapDrawable(counting_screen.getResources(), bMap); counting_screen.setBackground(bg); //added for duplicates check dupPref = prefs.getBoolean("duplicate_counts", true); } /** * Following functions are taken from the Apache commons-lang3-3.4 library * licensed under Apache License Version 2.0, January 2004 * * Checks if a CharSequence is not empty ("") and not null. * <p> * isNotEmpty(null) = false * isNotEmpty("") = false * isNotEmpty(" ") = true * isNotEmpty("bob") = true * isNotEmpty(" bob ") = true * * @param cs the CharSequence to check, may be null * @return {@code true} if the CharSequence is not empty and not null */ public static boolean isNotEmpty(final CharSequence cs) { return !isEmpty(cs); } /** * Checks if a CharSequence is empty ("") or null. * <p> * isEmpty(null) = true * isEmpty("") = true * isEmpty(" ") = false * isEmpty("bob") = false * isEmpty(" bob ") = false * * @param cs the CharSequence to check, may be null * @return {@code true} if the CharSequence is empty or null */ public static boolean isEmpty(final CharSequence cs) { return cs == null || cs.length() == 0; } }