Android Open Source - CATaZine-Live Entries List Fragment






From Project

Back to project page CATaZine-Live.

License

The source code is released under:

GNU General Public License

If you think the Android project CATaZine-Live 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.melegy.catazine.fragment;
/*from  w  ww  .  ja  va 2  s.  co m*/
import android.app.ListFragment;
import android.app.LoaderManager;
import android.content.ContentUris;
import android.content.Context;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.SearchView;

import com.melegy.catazine.Constants;
import com.melegy.catazine.R;
import com.melegy.catazine.adapter.EntriesCursorAdapter;
import com.melegy.catazine.provider.FeedData;
import com.melegy.catazine.provider.FeedDataContentProvider;
import com.melegy.catazine.provider.FeedData.EntryColumns;
import com.melegy.catazine.provider.FeedData.FeedColumns;
import com.melegy.catazine.service.FetcherService;
import com.melegy.catazine.utils.PrefUtils;

public class EntriesListFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor> {

    private static final String STATE_URI = "STATE_URI";
    private static final String STATE_SHOW_FEED_INFO = "STATE_SHOW_FEED_INFO";

    private static final int LOADER_ID = 1;

    private Uri mUri;
    private boolean mShowFeedInfo = false;
    private EntriesCursorAdapter mEntriesCursorAdapter;
    private ListView mListView;
    private SearchView mSearchView;

    private final OnSharedPreferenceChangeListener mPrefListener = new OnSharedPreferenceChangeListener() {
        @Override
        public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
            if (PrefUtils.SHOW_READ.equals(key)) {
                getLoaderManager().restartLoader(LOADER_ID, null, EntriesListFragment.this);
            }
        }
    };

    private class SwipeGestureListener extends SimpleOnGestureListener implements OnTouchListener {
        static final int SWIPE_MIN_DISTANCE = 120;
        static final int SWIPE_MAX_OFF_PATH = 150;
        static final int SWIPE_THRESHOLD_VELOCITY = 150;

        private GestureDetector mGestureDetector;

        public SwipeGestureListener(Context context) {
            mGestureDetector = new GestureDetector(context, this);
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            if (mListView != null && e1 != null && e2 != null && Math.abs(e1.getY() - e2.getY()) <= SWIPE_MAX_OFF_PATH && Math.abs(velocityX) >= SWIPE_THRESHOLD_VELOCITY) {
                int position = mListView.pointToPosition(Math.round(e2.getX()), Math.round(e2.getY()));
                View view = mListView.getChildAt(position - mListView.getFirstVisiblePosition());

                if (view != null) {
                    // Just click on views, the adapter will do the real stuff
                    if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE) {
                        CheckBox cb = (CheckBox) view.findViewById(android.R.id.checkbox);
                        cb.setChecked(!cb.isChecked());
                    } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE) {
                        ImageView star = (ImageView) view.findViewById(android.R.id.icon);
                        star.callOnClick();
                    }

                    // Just simulate a CANCEL event to remove the item highlighting
                    mListView.post(new Runnable() { // In a post to avoid a crash on 4.0.x
                        @Override
                        public void run() {
                            MotionEvent motionEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0);
                            mListView.dispatchTouchEvent(motionEvent);
                            motionEvent.recycle();
                        }
                    });
                    return true;
                }
            }

            return super.onFling(e1, e2, velocityX, velocityY);
        }

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            return mGestureDetector.onTouchEvent(event);
        }
    }

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

        if (savedInstanceState != null) {
            mUri = savedInstanceState.getParcelable(STATE_URI);
            mShowFeedInfo = savedInstanceState.getBoolean(STATE_SHOW_FEED_INFO);

            mEntriesCursorAdapter = new EntriesCursorAdapter(getActivity(), mUri, null, mShowFeedInfo);
            //getLoaderManager().initLoader(LOADER_ID, null, this);
        }

        PrefUtils.registerOnPrefChangeListener(mPrefListener);
    }

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

        // I don't know why this is needed... The loader seems to not be notified when the article is mark as read
        if (mUri != null) {
            getLoaderManager().restartLoader(LOADER_ID, null, this);
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        outState.putParcelable(STATE_URI, mUri);
        outState.putBoolean(STATE_SHOW_FEED_INFO, mShowFeedInfo);

        super.onSaveInstanceState(outState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_entry_list, container, false);

        if (mEntriesCursorAdapter != null) {
            setListAdapter(mEntriesCursorAdapter);
        }

        mListView = (ListView) rootView.findViewById(android.R.id.list);
        mListView.setFastScrollEnabled(true);
        mListView.setOnTouchListener(new SwipeGestureListener(getActivity()));

        mSearchView = (SearchView) rootView.findViewById(R.id.searchView);
        if (savedInstanceState != null) {
            refreshUI(); // To hide/show the search bar
        }

        mSearchView.post(new Runnable() { // Do this AFTER the text has been restored from saveInstanceState
            @Override
            public void run() {
                mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
                    @Override
                    public boolean onQueryTextSubmit(String s) {
                        InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
                        imm.hideSoftInputFromWindow(mSearchView.getWindowToken(), 0);
                        return false;
                    }

                    @Override
                    public boolean onQueryTextChange(String s) {
                        setData(EntryColumns.SEARCH_URI(s), true);
                        return false;
                    }
                });
            }
        });

        return rootView;
    }

    @Override
    public void onDestroy() {
        PrefUtils.unregisterOnPrefChangeListener(mPrefListener);
        super.onDestroy();
    }

    @Override
    public void onListItemClick(ListView listView, View view, int position, long id) {
        startActivity(new Intent(Intent.ACTION_VIEW, ContentUris.withAppendedId(mUri, id)));
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        menu.clear(); // This is needed to remove a bug on Android 4.0.3

        inflater.inflate(R.menu.entry_list, menu);

        if (EntryColumns.FAVORITES_CONTENT_URI.equals(mUri)) {
            menu.findItem(R.id.menu_hide_read).setVisible(false);
            menu.findItem(R.id.menu_refresh).setVisible(false);
            menu.findItem(R.id.menu_settings_main).setVisible(false);
        } else if (mUri != null && FeedDataContentProvider.URI_MATCHER.match(mUri) == FeedDataContentProvider.URI_SEARCH) {
            menu.findItem(R.id.menu_hide_read).setVisible(false);
            menu.findItem(R.id.menu_share_starred).setVisible(false);
            menu.findItem(R.id.menu_settings_main).setVisible(false);
        } else {
            menu.findItem(R.id.menu_share_starred).setVisible(false);

            if (!PrefUtils.getBoolean(PrefUtils.SHOW_READ, true)) {
                menu.findItem(R.id.menu_hide_read).setTitle(R.string.context_menu_show_read).setIcon(R.drawable.view_reads);
            }

            
        }

        super.onCreateOptionsMenu(menu, inflater);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.menu_share_starred: {
                String starredList = "";
                Cursor cursor = mEntriesCursorAdapter.getCursor();
                if (cursor != null && !cursor.isClosed()) {
                    int titlePos = cursor.getColumnIndex(EntryColumns.TITLE);
                    int linkPos = cursor.getColumnIndex(EntryColumns.LINK);
                    if (cursor.moveToFirst()) {
                        do {
                            starredList += cursor.getString(titlePos) + "\n" + cursor.getString(linkPos) + "\n\n";
                        } while (cursor.moveToNext());
                    }
                    startActivity(Intent.createChooser(
                            new Intent(Intent.ACTION_SEND).putExtra(Intent.EXTRA_SUBJECT, getString(R.string.share_favorites_title))
                                    .putExtra(Intent.EXTRA_TEXT, starredList).setType(Constants.MIMETYPE_TEXT_PLAIN), getString(R.string.menu_share)));
                }
                return true;
            }
            case R.id.menu_refresh: {
                if (!PrefUtils.getBoolean(PrefUtils.IS_REFRESHING, false)) {
                    if (FeedDataContentProvider.URI_MATCHER.match(mUri) == FeedDataContentProvider.URI_ENTRIES_FOR_FEED) {
                        getActivity().startService(new Intent(getActivity(), FetcherService.class).setAction(FetcherService.ACTION_REFRESH_FEEDS).putExtra(Constants.FEED_ID,
                                mUri.getPathSegments().get(1)));
                    } else {
                        getActivity().startService(new Intent(getActivity(), FetcherService.class).setAction(FetcherService.ACTION_REFRESH_FEEDS));
                    }
                }
                return true;
            }
            case R.id.menu_all_read: {
                mEntriesCursorAdapter.markAllAsRead();

                // If we are on "all items" uri, we can remove the notification here
                if (EntryColumns.CONTENT_URI.equals(mUri) && Constants.NOTIF_MGR != null) {
                    Constants.NOTIF_MGR.cancel(0);
                }
                return true;
            }
            case R.id.menu_hide_read: {
                if (!PrefUtils.getBoolean(PrefUtils.SHOW_READ, true)) {
                    PrefUtils.putBoolean(PrefUtils.SHOW_READ, true);
                    item.setTitle(R.string.context_menu_hide_read).setIcon(R.drawable.hide_reads);
                } else {
                    PrefUtils.putBoolean(PrefUtils.SHOW_READ, false);
                    item.setTitle(R.string.context_menu_show_read).setIcon(R.drawable.view_reads);
                }
            }
        }
        return super.onOptionsItemSelected(item);
    }

    public Uri getUri() {
        return mUri;
    }

    public String getCurrentSearch() {
        return mSearchView == null ? null : mSearchView.getQuery().toString();
    }

    public void setData(Uri uri, boolean showFeedInfo) {
        mUri = uri;
        mShowFeedInfo = showFeedInfo;

        mEntriesCursorAdapter = new EntriesCursorAdapter(getActivity(), mUri, null, mShowFeedInfo);
        setListAdapter(mEntriesCursorAdapter);
        getLoaderManager().restartLoader(LOADER_ID, null, this);

        refreshUI();
    }

    private void refreshUI() {
        if (mUri != null && FeedDataContentProvider.URI_MATCHER.match(mUri) == FeedDataContentProvider.URI_SEARCH) {
            mSearchView.setVisibility(View.VISIBLE);
        } else {
            mSearchView.setVisibility(View.GONE);
        }
    }

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        String entriesOrder = PrefUtils.getBoolean(PrefUtils.DISPLAY_OLDEST_FIRST, false) ? Constants.DB_ASC : Constants.DB_DESC;
        CursorLoader cursorLoader = new CursorLoader(getActivity(), mUri, null, FeedData.shouldShowReadEntries(mUri) ? null : EntryColumns.WHERE_UNREAD,
                null, EntryColumns.DATE + entriesOrder);
        cursorLoader.setUpdateThrottle(150);
        return cursorLoader;
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        mEntriesCursorAdapter.swapCursor(data);
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        mEntriesCursorAdapter.swapCursor(null);
    }
}




Java Source Code List

com.melegy.catazine.Constants.java
com.melegy.catazine.MainApplication.java
com.melegy.catazine.activity.AboutActivity.java
com.melegy.catazine.activity.BaseActivity.java
com.melegy.catazine.activity.EntryActivity.java
com.melegy.catazine.activity.GeneralPrefsActivity.java
com.melegy.catazine.activity.HomeActivity.java
com.melegy.catazine.adapter.CursorLoaderExpandableListAdapter.java
com.melegy.catazine.adapter.DrawerAdapter.java
com.melegy.catazine.adapter.EntriesCursorAdapter.java
com.melegy.catazine.adapter.FeedsCursorAdapter.java
com.melegy.catazine.fragment.EntriesListFragment.java
com.melegy.catazine.fragment.EntryFragment.java
com.melegy.catazine.loader.BaseLoader.java
com.melegy.catazine.parser.OPML.java
com.melegy.catazine.parser.RssAtomParser.java
com.melegy.catazine.provider.DatabaseHelper.java
com.melegy.catazine.provider.FeedDataContentProvider.java
com.melegy.catazine.provider.FeedData.java
com.melegy.catazine.receiver.BootCompletedBroadcastReceiver.java
com.melegy.catazine.receiver.ConnectionChangeReceiver.java
com.melegy.catazine.service.FetcherService.java
com.melegy.catazine.service.RefreshService.java
com.melegy.catazine.utils.ArticleTextExtractor.java
com.melegy.catazine.utils.HtmlUtils.java
com.melegy.catazine.utils.NetworkUtils.java
com.melegy.catazine.utils.PrefUtils.java
com.melegy.catazine.utils.StringUtils.java
com.melegy.catazine.utils.ThrottledContentObserver.java
com.melegy.catazine.utils.UiUtils.java
com.melegy.catazine.view.DragNDropExpandableListView.java
com.melegy.catazine.view.DragNDropListener.java
com.melegy.catazine.view.EntryView.java
com.melegy.catazine.widget.ColorPickerDialogPreference.java
com.melegy.catazine.widget.TickerWidgetProvider.java
com.melegy.catazine.widget.WidgetConfigActivity.java
com.melegy.catazine.widget.WidgetProvider.java
com.melegy.catazine.widget.WidgetService.java