nl.basvanmarwijk.mylocations.viewcontroller.LocationItemListFragment.java Source code

Java tutorial

Introduction

Here is the source code for nl.basvanmarwijk.mylocations.viewcontroller.LocationItemListFragment.java

Source

/*
 * Copyright 2014 Bas van Marwijk
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package nl.basvanmarwijk.mylocations.viewcontroller;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.location.Location;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.support.v4.widget.CursorAdapter;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.Toast;

import nl.basvanmarwijk.mylocations.App;
import nl.basvanmarwijk.mylocations.R;
import nl.basvanmarwijk.mylocations.location.LocationBridge;
import nl.basvanmarwijk.mylocations.location.LocationException;
import nl.basvanmarwijk.mylocations.logic.PlaceDownloaderTask;

/**
 * A list fragment representing a list of Contents. This fragment also supports
 * tablet devices by allowing list items to be given an 'activated' state upon
 * selection. This helps indicate which item is currently being viewed in a
 * {@link LocationItemDetailFragment}.
 * <p>
 * Activities containing this fragment MUST implement the {@link Callbacks}
 * interface.
 *
 * TODO on item click gmaps api
 *
 * @author Bas
 * @since revision 1
 * @version 2.1 moved PlaceDownloaderTask.Callback in separate inner class
 * @version 2.0 uses {@link android.support.v4.widget.CursorAdapter}
 * @version 1.4 onResume refreshes the list adapter
 * @version 1.3 compatible with {@link PlaceDownloaderTask} version 2.1
 * @version 1.2 progress circle
 * @version 1.1 loads locationitems in de background
 * @version 1.0 creation
 */
public class LocationItemListFragment extends ListFragment {

    /**
     * The serialization (saved instance state) Bundle key representing the
     * activated item position. Only used on tablets.
     */
    private static final String STATE_ACTIVATED_POSITION = "activated_position";

    /**
     * The fragment's current callback object, which is notified of list item
     * clicks.
     */
    private Callbacks mCallbacks = null;
    private BaseAdapter adapter;
    private boolean refreshNeeded = true;
    /**
     * The current activated item position. Only used on tablets.
     */
    private int mActivatedPosition = ListView.INVALID_POSITION;

    /**
     * Mandatory empty constructor for the fragment manager to instantiate the
     * fragment (e.g. upon screen orientation changes).
     */
    public LocationItemListFragment() {
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        // Activities containing this fragment must implement its callbacks.
        if (!(activity instanceof Callbacks)) {
            throw new IllegalStateException("Activity must implement fragment's callbacks.");
        }
        mCallbacks = (Callbacks) activity;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }

    /*
     * (non-Javadoc)
     *
     * @see android.support.v4.app.Fragment#onActivityCreated(android.os.Bundle)
     */
    @SuppressLint("InflateParams")
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        //TODO other constructor flag
        adapter = new LocationItemCursorAdapter(App.getAppContext(), App.getDbManager().getAllColumnsCursor(),
                CursorAdapter.FLAG_AUTO_REQUERY);

        final View btn_add = getActivity().getLayoutInflater().inflate(R.layout.add_button, null);
        final ListView lv = getListView();
        lv.addHeaderView(btn_add);

        btn_add.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                LocationBridge lb = new LocationBridge(getActivity().getApplicationContext());

                final String TAG = ((Object) this).getClass().getName();
                Log.i(TAG, "start locatie zoeken");

                Location locatie = null;
                try {
                    locatie = lb.getLastLocation();
                } catch (LocationException e) {
                    Log.w(TAG, e.getMessage());
                } finally {
                    lb.close();
                }

                if (locatie != null) {
                    Toast.makeText(getActivity(), R.string.location_found, Toast.LENGTH_SHORT).show();

                    toggleProgressBar(true);

                    PlaceDownloaderTask downloader = new PlaceDownloaderTask(new PlaceDownloaderListener());
                    downloader.execute(locatie);

                } else {
                    Toast.makeText(getActivity(), R.string.location_not_available, Toast.LENGTH_LONG).show();
                }
            }
        });

        setListAdapter(adapter);
    }

    /*
     * (non-Javadoc)
     *
     * @see android.support.v4.app.Fragment#onResume()
     */
    @Override
    public void onResume() {
        super.onResume();
        refreshAdapter();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        if (mActivatedPosition != ListView.INVALID_POSITION) {
            // Serialize and persist the activated item position.
            outState.putInt(STATE_ACTIVATED_POSITION, mActivatedPosition);
        }
    }

    @Override
    public void onStop() {
        super.onStop();
        // maybe item is edited in detailfragment
        refreshNeeded = true;
    }

    @Override
    public void onDetach() {
        super.onDetach();

        // Reset the active callbacks interface to the dummy implementation.
        mCallbacks = null;
    }

    /**
     * Refreshes list adapter
     */
    private void refreshAdapter() {
        if (refreshNeeded) {
            adapter.notifyDataSetChanged();
        }
    }

    /**
     * Sets progress bar to boolean enabled
     *
     * @param enabled enable the progressbar with true, disable with false
     */
    private void toggleProgressBar(boolean enabled) {
        getActivity().setProgressBarIndeterminateVisibility(enabled);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        // Restore the previously serialized activated item position.
        if (savedInstanceState != null && savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) {
            setActivatedPosition(savedInstanceState.getInt(STATE_ACTIVATED_POSITION));
        }

    }

    @Override
    public void onListItemClick(ListView listView, View view, int position, long id) {
        super.onListItemClick(listView, view, position, id);

        // Notify the active callbacks interface (the activity, if the
        // fragment is attached to one) that an item has been selected.
        if (adapter.getCount() >= position) {
            mCallbacks.onItemSelected((nl.basvanmarwijk.mylocations.db.dao.Location) adapter.getItem(position - 1));
        }
    }

    private void setActivatedPosition(int position) {
        if (position == ListView.INVALID_POSITION) {
            getListView().setItemChecked(mActivatedPosition, false);
        } else {
            getListView().setItemChecked(position, true);
        }

        mActivatedPosition = position;
    }

    /**
     * Turns on activate-on-click mode. When this mode is on, list items will be
     * given the 'activated' state when touched.
     */
    public void setActivateOnItemClick(boolean activateOnItemClick) {
        // When setting CHOICE_MODE_SINGLE, ListView will automatically
        // give items the 'activated' state when touched.
        getListView().setChoiceMode(activateOnItemClick ? ListView.CHOICE_MODE_SINGLE : ListView.CHOICE_MODE_NONE);
    }

    /**
     * A callback interface that all activities containing this fragment must
     * implement. This mechanism allows activities to be notified of item
     * selections.
     */
    public interface Callbacks {
        /**
         * Callback for when an item has been selected.
         */
        public void onItemSelected(nl.basvanmarwijk.mylocations.db.dao.Location item);
    }

    private class PlaceDownloaderListener implements PlaceDownloaderTask.Callback {
        @Override
        public void onLoad(nl.basvanmarwijk.mylocations.db.dao.Location item) {

            // if no flag path is set, set the dummy picture
            if (item.getFlag_path() == null) {
                Uri dummyURI = Uri
                        .parse("android.resource://" + getActivity().getPackageName() + "/drawable/stub.jpg");
                item.setFlag_path(dummyURI.getPath());
            }
            toggleProgressBar(false);

            adapter.notifyDataSetChanged();
        }

        @Override
        public void onProgress(byte progress) {
            // ignore
        }
    }
}