Java tutorial
/* * MonMa: Eine freie Android-Application fuer die Verwaltung privater Finanzen * * Copyright [2015] [Alexander Winkler, 2373 Dahme/Germany] * * This program is free software; you can redistribute it and/or modify it under the terms of the * GNU 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 * General Public License for more details. * * You should have received a copy of the GNU General Public License along with this program; if * not, see <http://www.gnu.org/licenses/>. */ package de.aw.monma.views; import android.content.Context; import android.content.res.TypedArray; import android.database.Cursor; import android.databinding.BindingAdapter; import android.os.Bundle; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.support.v7.app.AppCompatActivity; import android.util.AttributeSet; import android.view.View; import android.widget.AdapterView; import android.widget.SimpleCursorAdapter; import android.widget.Spinner; import de.aw.awlib.application.AWApplication; import de.aw.monma.R; import de.aw.monma.database.DBDefinition; import de.aw.monma.database.TableColums; import de.aw.monma.enums.Kontotyp; /** * Spinner fuer die Auswahl von Konten. Es kann gesteuert werden, ob nur nicht-ausgeblendete Konten * (Default) oder die gesamte Kontolist gezeigt wird. Welche Konten gezeigt werden, kann wie folgt * gesteuert werden: Ueber {@link de.aw.monma.views.SpinnerAccount#setModus(Modus)} kann der Modus * gesetzt werden. Alternativ kann auch ueber xml der Modus gesetzt werden. Folgende Varioanten sind * moeglich: app:modus="cash" - entspricht {@link de.aw.monma.views.SpinnerAccount.Modus#Cash} * app:modus="verrechnung" - entspricht {@link de.aw.monma.views.SpinnerAccount.Modus#Verrechnung} * app:modus="offline" - entspricht {@link de.aw.monma.views.SpinnerAccount.Modus#Offline} */ public class SpinnerAccount extends android.support.v7.widget.AppCompatSpinner implements LoaderManager.LoaderCallbacks<Cursor>, AdapterView.OnItemSelectedListener, TableColums { protected static final DBDefinition tbd = DBDefinition.Account; protected String[] projection; protected String selectionNotAusgeblendet; protected boolean showOnlyAusgeblendet = true; protected String userOrderBy; protected String userSelection; protected String[] userSelectionArgs; private boolean showSelectedItem = false; private SimpleCursorAdapter adapter; private LoaderManager mLoaderManager; private Modus mModus; private OnItemSelectionListener mOnItemSelectedListener; private Integer selectedAccountID; public SpinnerAccount(Context context) { this(context, Spinner.MODE_DROPDOWN); } public SpinnerAccount(Context context, int mode) { super(context, mode); init(context, null); } public SpinnerAccount(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs); } public SpinnerAccount(Context context, AttributeSet attrs, int defStyleAttr) { this(context, attrs, defStyleAttr, Spinner.MODE_DROPDOWN); init(context, attrs); } public SpinnerAccount(Context context, AttributeSet attrs, int defStyleAttr, int mode) { super(context, attrs, defStyleAttr, mode); init(context, attrs); } @BindingAdapter({ "onItemSelected" }) public static void onItemSelected(SpinnerAccount view, OnItemSelectionListener listener) { view.setOnItemSelectedListener(listener); } @BindingAdapter({ "value" }) public static void setValue(SpinnerAccount view, int accountID) { view.setSelectedAccountID(accountID); } private Integer getPosition(int accountID, Cursor cursor) { Integer position = null; if (cursor.moveToFirst()) { int i = 0; do { int mID = cursor.getInt(0); if (mID == accountID) { position = i; break; } i++; } while (cursor.moveToNext()); } return position; } private void init(Context context, AttributeSet attrs) { if (!isInEditMode()) { mLoaderManager = ((AppCompatActivity) context).getSupportLoaderManager(); projection = new String[] { _id, column_accountname }; selectionNotAusgeblendet = " NOT " + column_ausgeblendet; if (mModus == null) { TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SpinnerAccount); try { int modus = a.getInteger(R.styleable.SpinnerAccount_modus, Modus.Cash.ordinal()); mModus = Modus.values()[modus]; } finally { a.recycle(); } } int[] adapterRowViews = new int[] { android.R.id.text1 }; String[] adapterCols = new String[] { column_accountname }; adapter = new SimpleCursorAdapter(getContext(), android.R.layout.simple_spinner_item, null, adapterCols, adapterRowViews, 0); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); setAdapter(adapter); super.setOnItemSelectedListener(this); if (getVisibility() == VISIBLE) { startOrRestartLoader(getId()); } } } @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { String selection = userSelection; if (showOnlyAusgeblendet) { if (selection != null) { selection = "(" + selection + ") AND " + selectionNotAusgeblendet; } else { selection = selectionNotAusgeblendet; } } switch (mModus) { case Offline: selection += " AND " + column_accounttyp + " != '" + Kontotyp.Port.name() + "'"; break; case Cash: case Verrechnung: selection += " AND " + column_accounttyp + " != '" + Kontotyp.Port.name() + "'"; break; } return new CursorLoader(getContext(), tbd.getUri(), projection, selection, userSelectionArgs, userOrderBy); } @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { selectedAccountID = ((Long) id).intValue(); if (mOnItemSelectedListener != null) { mOnItemSelectedListener.onItemSelected(this, position, selectedAccountID); } } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor data) { if (adapter != null) { adapter.swapCursor(data); if (selectedAccountID != null) { Integer position = getPosition(selectedAccountID, data); if (position != null) { setSelection(position); } } } } @Override public void onLoaderReset(Loader<Cursor> loader) { if (adapter != null) { adapter.swapCursor(null); } } @Override public void onNothingSelected(AdapterView<?> parent) { } /** * Initializer fur Konten gemaess {@link de.aw.monma.views.SpinnerAccount.Modus} * * @param modus * Modus */ public void setModus(Modus modus) { mModus = modus; startOrRestartLoader(getId()); } public void setOnItemSelectedListener(OnItemSelectionListener listener) { mOnItemSelectedListener = listener; } public void setSelectedAccountID(Integer accountID) { selectedAccountID = accountID; setSelection(accountID); } private void startOrRestartLoader(int loaderID) { AWApplication.Log("SpinnerAccount: Loading Cursor"); if (mLoaderManager != null) { Loader<Cursor> loader = mLoaderManager.getLoader(loaderID); if (loader != null && !loader.isReset()) { mLoaderManager.initLoader(loaderID, null, this); } else { mLoaderManager.restartLoader(loaderID, null, this); } } } /** * Modus des Spinner. */ public enum Modus { /** * Zeigt nur Cashkonten. xml: app:modus="cash" */ Cash /** * Zeigt nur moegliche Gegenkonten fuer Depots. xml: app:modus="verrechnung" */ , Verrechnung /** * Zeigt nur Offline-CashKonten. xml: app:modus="offline" */ ,Offline, } public interface OnItemSelectionListener { void onItemSelected(SpinnerAccount view, int position, int accountID); } }