de.aw.awlib.fragments.AWFragment.java Source code

Java tutorial

Introduction

Here is the source code for de.aw.awlib.fragments.AWFragment.java

Source

/*
 * 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.awlib.fragments;

import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.annotation.CallSuper;
import android.support.annotation.LayoutRes;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.preference.PreferenceManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import de.aw.awlib.activities.AWActivityActions;
import de.aw.awlib.activities.AWInterface;
import de.aw.awlib.activities.AWMainActivity;
import de.aw.awlib.application.AWApplication;

import static de.aw.awlib.events.AWEvent.ShowPicture;

/**
 * Template fuer MonMaFragmente
 * <p/>
 * Folgende Funktionen: Bereitstellung eines Bundle 'args' fuer alle abgeleiteten Klassen
 */
public abstract class AWFragment extends DialogFragment implements AWInterface, AWFragmentInterface {
    /**
     * TAG Fuer die Fragmente
     */
    public final String TAG = this.getClass().getSimpleName();
    /**
     * Bundle fuer ein Fragment. Wird in onCreate() wiederhergestellt und in OnSaveStateInstance()
     * gesichert.
     */
    protected final Bundle args = new Bundle();
    /**
     * Layout des Fragments
     */
    protected int layout = NOLAYOUT;
    /**
     * SharedPreferences werden allen abgeleiteten Fragmenten bereitgestellt
     */
    protected SharedPreferences prefs;
    protected boolean isCanceled;
    private int containerID;
    /**
     * Merker, ob der ActionBarSubtitle ueberschrieben wurde.
     */
    private boolean isSavedActionBarSubtitle;
    private OnAWFragmentCancelListener mOnCancelListener;
    /**
     *
     */
    private OnAWFragmentDismissListener mOnDismissListener;
    /**
     * Gemerkter ActionBarSubTitle. Wird in onPause() wiederhergestellt.
     */
    private CharSequence mSavedActionBarSubtitle;
    private MainAction mainAction;
    /**
     * Dient zur Berechnung der Startdauer
     */
    private long timer;

    public AWFragment() {
        timer = System.currentTimeMillis();
    }

    protected final void Log(String message) {
        AWApplication.Log(message);
    }

    protected final void LogError(String message) {
        AWApplication.LogError(message);
    }

    public MainAction getMainAction() {
        return mainAction;
    }

    @Override
    public final String getTAG() {
        return TAG;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        String title = args.getString(ACTIONBARTITLE);
        if (title != null) {
            setTitle(title);
        }
        String subTitle = args.getString(ACTIONBARSUBTITLE);
        if (subTitle != null) {
            setSubTitle(subTitle);
        }
    }

    /**
     * Die aktuellen Preferences werden ermittelt und in prefs gespeichert. Ausserdem werden die
     * Argumente aus {@link Fragment#getArguments()} gelesen und in args gespeichert. Danach wird
     * {@link AWFragment#setInternalArguments(Bundle)} } gerufen.
     */
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        prefs = PreferenceManager.getDefaultSharedPreferences(context);
        Bundle argumente = getArguments();
        if (argumente != null) {
            args.putAll(argumente);
        }
        setInternalArguments(args);
    }

    /**
     * Wird ein Dialog gecancelt, wird der mOnCancelListener gerufen (wenn vorhanden) Ausserdem ist
     * dann isCanceled true.
     */
    @Override
    public void onCancel(DialogInterface dialog) {
        isCanceled = true;
        if (mOnCancelListener != null) {
            mOnCancelListener.onCancel(layout, dialog);
        }
    }

    /**
     * Setzen der durch setArguments(args) erhaltenen bzw. Ruecksichern der Argumente im Bundle
     * args. Gibt es keine MainAction unter AWLIBACTION, wird MainAction.SHOW verwendet.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState != null) {
            args.putAll(savedInstanceState);
        }
        layout = args.getInt(LAYOUT, NOLAYOUT);
        mainAction = args.getParcelable(AWLIBACTION);
        if (mainAction == null) {
            mainAction = MainAction.SHOW;
        }
    }

    /**
     * Handelt es sich um einen Dialog, wird null zurueckgegeben. Ansoonsten wird die View erstellt
     * und zurueckgegeben.
     */
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        if (container != null) {
            this.containerID = container.getId();
        }
        if (!getShowsDialog()) {
            return layout == NOLAYOUT ? null : inflater.inflate(layout, container, false);
        }
        return null;
    }

    /**
     * Nur loggen, dass Fragment destroeyed wurde.
     */
    @Override
    public void onDestroy() {
        super.onDestroy();
        Log("Fragment " + getClass().getSimpleName() + " destroyed");
    }

    /**
     * Der Dailog verschwindet bei eine Aenderung der Configuration (z.B. drehen). Wenn das Fragment
     * retainInstance(true) gesetz hat, wird dies mit diesem Code verhindert. @see <a
     * href="https://code.google.com/p/android/issues/detail?id=17423">Hinweis</a>
     */
    @Override
    public void onDestroyView() {
        if (getDialog() != null && getRetainInstance()) {
            getDialog().setDismissMessage(null);
        }
        super.onDestroyView();
    }

    /**
     * Bei Dismiss wird ein OnDismissListener informiert(wenn vorhanden).
     */
    @Override
    public void onDismiss(DialogInterface dialog) {
        super.onDismiss(dialog);
        if (!isCanceled && mOnDismissListener != null) {
            mOnDismissListener.onDismiss(layout, dialog);
        }
    }

    /**
     * Deregistrierung als OnSharedPreferenceListener, wenn die Klasse eine Instanz von
     * OnSharedPreferenceChangeListener ist. Wiederherstellen eines Subtitles, wenn vorhanden.
     */
    @Override
    public void onPause() {
        super.onPause();
        if (this instanceof SharedPreferences.OnSharedPreferenceChangeListener) {
            prefs.unregisterOnSharedPreferenceChangeListener(
                    (SharedPreferences.OnSharedPreferenceChangeListener) this);
        }
        if (isSavedActionBarSubtitle) {
            setSubTitle(mSavedActionBarSubtitle);
        }
    }

    /**
     * Ist die Klasse eine Instanz von OnSharedPreferenceChangeListener, wird diese als {@link
     * SharedPreferences#registerOnSharedPreferenceChangeListener} registriert.
     */
    @Override
    public void onResume() {
        super.onResume();
        if (this instanceof SharedPreferences.OnSharedPreferenceChangeListener) {
            prefs.registerOnSharedPreferenceChangeListener(
                    (SharedPreferences.OnSharedPreferenceChangeListener) this);
        }
        CharSequence title = args.getCharSequence(ACTIONBARTITLE);
        if (title != null) {
            setTitle(title);
        }
    }

    /**
     * Sichern des bereitgestellten Bundles args. Wird in onCreate() wiederhergestellt.
     */
    @Override
    public void onSaveInstanceState(Bundle outState) {
        outState.putAll(args);
        super.onSaveInstanceState(outState);
    }

    /**
     * Ausgabe Dauer des Starts des Fragments
     */
    @Override
    public void onStart() {
        super.onStart();
        if (timer != 0) {
            Log("Fragment " + getClass().getSimpleName() + " Startdauer: " + (System.currentTimeMillis() - timer));
            timer = 0;
        }
    }

    /**
     * Ersetzt das aktuelle Fragment durch das uebergebene Fragment und fuegt es dem BackStacj
     * hinzu.
     *
     * @param f
     *         neues Fragment
     *
     * @throws IllegalStateException,
     *         wenn nicht super.onCreate(...) gerufen wurde..
     */
    protected void replaceFragment(AWFragment f) {
        if (containerID == NOID) {
            throw new IllegalStateException("Container nicht bekannt. Wurde super.onCreateView(...) gerufen?");
        }
        getActivity().getSupportFragmentManager().beginTransaction().replace(containerID, f).addToBackStack(null)
                .commit();
    }

    /**
     * Uebernimmt Argumente zusaetzlich(!) zu bereits vorhandenen
     *
     * @see Fragment#setArguments(Bundle)
     */
    public final void setArguments(Bundle args) {
        Bundle oldArgs = getArguments();
        if (oldArgs != null) {
            if (args != null) {
                oldArgs.putAll(args);
            }
        } else {
            super.setArguments(args);
        }
    }

    /**
     * Setzt die Sichtbarkkeit des DefaultFloatingActionButton
     *
     * @param visible
     *         true: Visible
     *
     * @throws ClassCastException
     *         wenn Activity nicht Instance von {@link AWMainActivity}
     */
    protected void setDefaultFabVisibility(boolean visible) {
        FloatingActionButton fab = ((AWMainActivity) getActivity()).getDefaultFAB();
        if (visible) {
            fab.setVisibility(View.VISIBLE);
        } else {
            fab.setVisibility(View.GONE);
        }
    }

    /**
     * Methode wird aus onAttach gerufen. Im uebergebenen Bundle sind alle Argumente gespeichert,
     * die ggfs. in newInstance(...) belegt wurden. Zweckmaessigerweise wird zuerst
     * super.setInternalArguments(args) gerufen. Danach sind in args die Argumente der
     * Vererbungshirache vorhanden, welche auch ueberschrieben werden koennen. Es koennen weitere
     * Argumente zum Initialisieren genau dieses Fragments gesetzt werden. Argumente, die von einem
     * vererbten Fragment gesetzt werden, sind aber noch nicht vorhanden. Werden diese benoetigt,
     * sollten diese fruehestens in onCreate(saveStateInstance) aus args geholt werden.
     *
     * @param args
     *         Bundle mit Argumenten.
     */
    @CallSuper
    protected void setInternalArguments(Bundle args) {
    }

    /**
     * @param listener
     *         erweiterter {@link OnAWFragmentCancelListener}
     */
    public void setOnCancelListener(OnAWFragmentCancelListener listener) {
        mOnCancelListener = listener;
    }

    /**
     * @param listener
     *         erweiterter {@link OnAWFragmentDismissListener}
     */
    public void setOnDismissListener(OnAWFragmentDismissListener listener) {
        mOnDismissListener = listener;
    }

    /**
     * Setzt den SubTitle in der SupportActionBar. Rettet vorher den aktuellen Subtitle, der wird
     * dann in onPause() wiederhergestellt.
     *
     * @param subTitle
     *         Text des Subtitles
     */
    public void setSubTitle(CharSequence subTitle) {
        ActionBar bar = ((AppCompatActivity) getActivity()).getSupportActionBar();
        if (bar != null) {
            if (!isSavedActionBarSubtitle) {
                mSavedActionBarSubtitle = bar.getSubtitle();
                isSavedActionBarSubtitle = true;
            }
            bar.setSubtitle(subTitle);
        }
        args.putCharSequence(ACTIONBARSUBTITLE, subTitle);
    }

    /**
     * Setzt den SubTitle in der SupportActionBar Rettet vorher den aktuellen Subtitle, der wird
     * dann in onPause() wiederhergestellt.
     *
     * @param subTitleResID
     *         resID des Subtitles
     */
    public void setSubTitle(int subTitleResID) {
        setSubTitle(getString(subTitleResID));
    }

    /**
     * Setzt den Title in der SupportActionBar
     *
     * @param title
     *         Text des STitles
     */
    public void setTitle(CharSequence title) {
        ActionBar bar = ((AppCompatActivity) getActivity()).getSupportActionBar();
        if (bar != null) {
            bar.setTitle(title);
        }
        args.putCharSequence(ACTIONBARTITLE, title);
    }

    /**
     * Setzt den Title in der SupportActionBar
     *
     * @param titleResID
     *         resID des Titles
     */
    public void setTitle(int titleResID) {
        setTitle(getString(titleResID));
    }

    /**
     * Startet eine Activity zum anzeigen eines Bildes.
     *
     * @param filename
     *         Absoluter Path zum File. File muss ein Bild enthalten
     */
    protected void showPictureFrom(String filename) {
        Intent intent = new Intent(getActivity(), AWActivityActions.class);
        intent.putExtra(FILENAME, filename);
        intent.putExtra(AWLIBEVENT, ShowPicture);
        getActivity().startActivity(intent);
    }

    /**
     * Erweiterter Dialog-Cancel-Listener. Liefert zusaetzlich zum Dialog auch die layoutID des
     * Fragments mit.
     */
    public interface OnAWFragmentCancelListener {
        /**
         * Wird gerufen, wenn ein Dialog gecancelt wurde.Liefert zusaetzlich zum Dialog auch die
         * layoutID des Fragments mit.
         *
         * @param layoutID
         *         layout des Fragments
         * @param dialog
         *         Dialog
         */
        void onCancel(@LayoutRes int layoutID, DialogInterface dialog);
    }

    /**
     * Erweiterter Dialog-Dismiss-Listener. Liefert zusaetzlich zum Dialog auch die layoutID des
     * Fragments mit.
     */
    public interface OnAWFragmentDismissListener {
        /**
         * Wird gerufen, wenn ein Dialog beendet wurde.Liefert zusaetzlich zum Dialog auch die
         * layoutID des Fragments mit.
         *
         * @param layoutID
         *         layout des Fragments
         * @param dialog
         *         Dialog
         */
        void onDismiss(@LayoutRes int layoutID, DialogInterface dialog);
    }
}