Android Open Source - android-kidspend Spinner With Prefs






From Project

Back to project page android-kidspend.

License

The source code is released under:

GNU General Public License

If you think the Android project android-kidspend listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.manangatangy.kidspend;
//from w  w  w. j  av  a 2  s .c  om
/**
 * Created with IntelliJ IDEA.
 * User: david
 * Date: 24/11/14
 * Time: 2:55 PM
 * To change this template use File | Settings | File Templates.
 */

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import android.util.Log;

import java.util.ArrayList;

/**
 * Manages a Spinner and its Adapter.  The Spinner is loaded with from the string
 * resources and also from the preferences.
 * The value currently selected is available at getCurrentSelection().
 * The extra types held in the preferences may be cleared or added to.
 * Calling addType will add a new type to the preferences and to the spinner (also selecting it).
 *
 */
public class SpinnerWithPrefs {

    static final String TAG = "Expenditure";

    static final String PREFERENCES_FILE = "ExpenditurePrefs";
    static final String TYPE_EXTRAS_KEY = "ExtraTypes";
    static final String TYPE_POSITION_KEY = "TypePosition";

    private final SpendAdder spendAdder;            // Used for prefs and resources.
    private EditText newTypeInput;            // View holding the candidate new type value.

    // The extraTypes string is a comma-separated list of expenditure types.
    // It is only referenced by loadExtraTypesFromPrefs and saveNewType.
    private String extraTypes = "";    // maybe should be ArrayList<String> ???

    // Only types prefixed with this value will be loaded into the spinner.
    private String currentPrefix = "";

    private EditableSpinner editableSpinner;

    /**
     * A SpinnerWithPrefs creates a Spinner and ArrayAdapter to back it, which is filled with values from
     * the string resources and user preferences. The item selected from the spinners list will be available
     * at getSelectedValue().  Short clicking on the Spinner widget pops up the selection list and long
     * clicking on the widget pops up a dialog (invoked by the spendAdder.onCreateDialog(DIALOG_NEW_SPEND_TYPE_ID))
     * that allows a new spend type to be created and added/stored to the prefs (if it is not a duplicate of
     * an existing spend type).  When the new spend type dialog appears, then long clicking on the add button
     * will prompt for the clearing of all the spend type preferences.
     */
    public SpinnerWithPrefs(final SpendAdder spendAdder, String prefix) {
        this.spendAdder = spendAdder;
        ArrayList<String> arrayList = getFromResourceAndPrefs(prefix);
        editableSpinner = new EditableSpinner(spendAdder, R.id.typeSpinner, arrayList, new View.OnLongClickListener() {
            // Long clicking the spinner widget pops up the new type dialog, first clearing previous value, error.
            @Override
            public boolean onLongClick(View v) {
                if (newTypeInput != null) {    // Will only be set after onCreateDialog first called.
                    newTypeInput.setText("");
                    newTypeInput.setError(null);
                }
                spendAdder.showDialog(SpendAdder.DIALOG_NEW_SPEND_TYPE_ID);
                return true;
            }
        });
    }

    public String getSelectedValue() {
        return editableSpinner.getSelected();
    }

    /**
     * Create a new ArrayAdapter and load it with values from the string resources and from the prefs.
     * Only load values with the specified prefix (stripping it from the loaded value).
     * If the newPrefix _ non null, then use tit to set a new currentPrefix
     */
    public void reset(String newPrefix) {
        ArrayList<String> arrayList = getFromResourceAndPrefs(newPrefix);
        editableSpinner.resetAdapter(spendAdder, arrayList);
    }

    /**
     * Add a new type to the current set of preferences and save it (also adding it to the local field).
     * The new type is also added into the adapter and set as the selection in the spinner.
     * Returns false if the newType failed validation.
     */
    private boolean addType(String newType) {
        if (editableSpinner.addOption(newType) == false)
            return false;

        // Save it to the prefs, (with the current prefix) first storing locally in extraTypes.
        if (extraTypes.length() > 0)
            extraTypes = extraTypes + ",";
        extraTypes = extraTypes + currentPrefix + newType;
        savePref(extraTypes);
        return true;
    }

    /**
     * Assign a new value for the currentPrefix.
     * Create a new ArrayList and fill it with the values from the resource and the prefs.
     * Only values prefixed with the currentPriefix will be loaded (after stripping the prefix).
     * @return
     */
    private ArrayList<String> getFromResourceAndPrefs(String newPrefix) {

        if (!TextUtils.isEmpty(newPrefix)) {
            this.currentPrefix = newPrefix + ":";
        }
        // The spinner is loaded with a bunch of statically
        // defined values from the string resource, and then any user-defined values from the
        // prefs file.  In addition, the spinner initial position may also be held as a user
        // pref, from a previous session, so we try and load that too.
        // The preferences are stored in a SharedPreferences file, which is a "file"
        // containing a hashmap and is shared by all instances of the application.
        // Note: use boolean SharedPreferences.contains("some_key") to test if pref exists.
        // R.array.types_array
        String[] typesArray = spendAdder.getResources().getStringArray(R.array.types_array);
        ArrayList<String> arrayList = new ArrayList<String>();    // Arrays.asList(spendTypesArray)
        for (String spendType : typesArray) {
            String stripped = hasPrefix(spendType, currentPrefix);
            if (!TextUtils.isEmpty(stripped)) {
                arrayList.add(stripped);
            }
        }

        // http://developer.android.com/guide/topics/fundamentals/activities.html#SavingActivityState
        SharedPreferences prefs = spendAdder.getSharedPreferences(PREFERENCES_FILE, Activity.MODE_WORLD_READABLE);
        extraTypes = prefs.getString(TYPE_EXTRAS_KEY, "");
        //Log.v(TAG, "loadExtraTypesFromPrefs: extraTypes=" + extraTypes);

        for (String extraType : extraTypes.split(",")) {
            if (!TextUtils.isEmpty(extraType)) {
                String stripped = hasPrefix(extraType, currentPrefix);
                if (!TextUtils.isEmpty(stripped)) {
                    //Log.d(TAG, "adding: " + extraType);
                    arrayList.add(stripped);
                }
            }
        }

        return arrayList;
    }

    /**
     * If the text has the specified prefix, return the text (minus the prefix) else return null.
     */
    private String hasPrefix(String text, String prefix) {
        if (text.startsWith(prefix)) {
            return text.substring(prefix.length());
        } else
            return null;
    }

    public AlertDialog createAddTypeDialog() {
        // Ref: http://developer.android.com/guide/topics/ui/dialogs.html#CustomDialog
        //Context mContext = getApplicationContext();
        LayoutInflater inflater = (LayoutInflater)spendAdder.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
        View layout = inflater.inflate(R.layout.new_type, (ViewGroup)spendAdder.findViewById(R.id.new_type_root));

        newTypeInput = (EditText)layout.findViewById(R.id.newTypeInput);

        // Note that the Context passed to AlertDialog.Builder() must be an Activity
        // ref: http://stackoverflow.com/questions/1561803/android-progressdialog-show-crashes-with-getapplicationcontext
        final AlertDialog newTypeDialog = new AlertDialog.Builder(spendAdder)
                .setView(layout)
                .setTitle(R.string.new_type_dialog_title)
                .setPositiveButton(R.string.new_type_create_label, null)
                .setNegativeButton(R.string.new_type_cancel_label, null)
                .create();

        // The buttons default onClickListeners always dismiss the dialog.  We want to keep
        // it hanging around if there is an input eror, so override them.  Must do it after
        // onShow() is called otherwise getButton() returns null.
        // ref: http://stackoverflow.com/questions/2620444/android-how-to-prevent-dialog-closed-or-remain-dialog-when-button-is-clicked
        newTypeDialog.setOnShowListener(new DialogInterface.OnShowListener() {
            @Override
            public void onShow(DialogInterface dialog) {
                Button positiveButton = newTypeDialog.getButton(AlertDialog.BUTTON_POSITIVE);
                positiveButton.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        // Log.v(TAG, "mSpendList: onItemLongclick,onClick: " + deleteId);
                        String newType = newTypeInput.getText().toString();
                        if (!addType(newType))
                            newTypeInput.setError("duplicate/empty type");
                        else {
                            Toast.makeText(spendAdder.getApplicationContext(), "added new-type  " + currentPrefix + newType, Toast.LENGTH_SHORT).show();
                            //Dismiss once everything is OK.
                            newTypeDialog.dismiss();
                        }
                    }
                });
                // Long clicking the add button on the new spend type dialog, prompts to delete all extra types.
                positiveButton.setOnLongClickListener(new View.OnLongClickListener() {
                    @Override
                    public boolean onLongClick(View v) {
                        new AlertDialog.Builder(spendAdder)
                                .setMessage("Delete all extra type prefs?")
                                .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                                    public void onClick(DialogInterface dialog, int which) {
                                        savePref(extraTypes = "");    // Empty the local prefs and save it.
                                        reset(null);    // No change to currentPrefix
                                        Toast.makeText(spendAdder.getApplicationContext(), "Deleted all spend type prefs", Toast.LENGTH_SHORT).show();
                                        dialog.dismiss();
                                    }
                                })
                                .setNegativeButton("Cancel", null)
                                .show();
                        return false;
                    }
                });
            }
        });
        return newTypeDialog;
    }

    private void savePref(String typePref) {
        SharedPreferences prefs = spendAdder.getSharedPreferences(PREFERENCES_FILE, Activity.MODE_WORLD_READABLE);
        SharedPreferences.Editor editor = prefs.edit();
        //e.putInt(TYPE_POSITION_KEY, typePosition);
        editor.putString(TYPE_EXTRAS_KEY, typePref);
        // The commit to persistent storage may fail
        if (!editor.commit()) {
            Toast.makeText(spendAdder, "Expenditure: failed to write state", Toast.LENGTH_LONG).show();
        } else {
            Log.v(TAG, "savePref: typePref=" + typePref);
        }
    }


}




Java Source Code List

com.manangatangy.kidspend.EditableSpinner.java
com.manangatangy.kidspend.RepeatManager.java
com.manangatangy.kidspend.SpendAdder.java
com.manangatangy.kidspend.SpendManager.java
com.manangatangy.kidspend.SpendProviderMetaData.java
com.manangatangy.kidspend.SpendProvider.java
com.manangatangy.kidspend.SpendTotals.java
com.manangatangy.kidspend.SpinnerWithPrefs.java