org.orange.querysystem.content.ListPostsFragment.java Source code

Java tutorial

Introduction

Here is the source code for org.orange.querysystem.content.ListPostsFragment.java

Source

/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * 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 org.orange.querysystem.content;

import org.orange.querysystem.PostDetailsActivity;
import org.orange.querysystem.R;
import org.orange.studentinformationdatabase.Contract;

import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.widget.CursorAdapter;
import android.support.v4.widget.SearchViewCompat;
import android.support.v4.widget.SearchViewCompat.OnQueryTextListenerCompat;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * modified from Support4Demo's LoaderCursorSupport
 *
 * @modifiedBy Bai Jie
 */
public class ListPostsFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor> {

    public static final String SOURCE = Contract.Posts.COLUMN_NAME_SOURCE;

    private static final int SEARCH_EDIT_TEXT = 100;

    private static final int SEARCH = 200;

    private LinearLayout mLinearLayout;

    public static Bundle buildArgument(byte source) {
        Bundle args = new Bundle();
        args.putString(SOURCE, String.valueOf(source));
        return args;
    }

    public static ListPostsFragment newInstance(byte source) {
        ListPostsFragment frag = new ListPostsFragment();
        frag.setArguments(buildArgument(source));
        return frag;
    }

    // This is the Adapter being used to display the list's data.
    CursorAdapter mAdapter;

    // If non-null, this is the filter the user has provided.
    String mFilter;

    /**
     * search mFilter by this clause
     */
    private static final String searchClause = Contract.Posts.COLUMN_NAME_TITLE + " LIKE ? OR "
            + Contract.Posts.COLUMN_NAME_CATEGORY + " LIKE ? OR " + Contract.Posts.COLUMN_NAME_AUTHOR + " LIKE ?";

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View layout = super.onCreateView(inflater, container, savedInstanceState);
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
            View lv = layout.findViewById(android.R.id.list);
            ViewGroup parent = (ViewGroup) lv.getParent();
            // Remove ListView and add CustomView  in its place
            int lvIndex = parent.indexOfChild(lv);
            parent.removeViewAt(lvIndex);

            mLinearLayout = new LinearLayout(getActivity());
            mLinearLayout.setOrientation(LinearLayout.VERTICAL);
            if (mFilter != null) {
                insertSearchEditText().setText(mFilter);
            }
            mLinearLayout.addView(lv);
            parent.addView(mLinearLayout, lvIndex, lv.getLayoutParams());
        }
        return layout;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        mLinearLayout = null;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        this.getListView().setCacheColorHint(Color.TRANSPARENT);

        // Give some text to display if there is no data.
        setEmptyText(getResources().getText(R.string.no_post));

        // We have a menu item to show in action bar.
        setHasOptionsMenu(true);

        // Create an empty adapter we will use to display the loaded data.
        mAdapter = new PostsCursorAdapter(getActivity(), null, 0);
        setListAdapter(mAdapter);

        // Start out with a progress indicator.
        setListShown(false);

        // Prepare the loader.  Either re-connect with an existing one,
        // or start a new one.
        getLoaderManager().initLoader(0, null, this);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        // Place an action bar item for searching.
        MenuItem item = menu.add(Menu.NONE, SEARCH, Menu.NONE, R.string.search);
        item.setIcon(R.drawable.ic_action_search);
        MenuItemCompat.setShowAsAction(item,
                MenuItemCompat.SHOW_AS_ACTION_ALWAYS | MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
        Context context = Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH
                ? getActivity().getApplicationContext()
                : getActivity().getActionBar().getThemedContext();
        View searchView = SearchViewCompat.newSearchView(context);
        if (searchView != null) {
            SearchViewCompat.setOnQueryTextListener(searchView, new OnQueryTextListenerCompat() {
                @Override
                public boolean onQueryTextChange(String newText) {
                    onSearchTextChanged(newText);
                    return true;
                }
            });
            MenuItemCompat.setActionView(item, searchView);
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case SEARCH:
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
                View searchEditText = mLinearLayout.findViewById(SEARCH_EDIT_TEXT);
                if (searchEditText == null) {
                    searchEditText = insertSearchEditText();
                }
                searchEditText.requestFocus();
                return true;
            }
        default:
            return super.onOptionsItemSelected(item);
        }
    }

    /**
     * ???
     *
     * @param newText ?
     */
    private void onSearchTextChanged(String newText) {
        // Called when the action bar search text has changed.  Update
        // the search filter, and restart the loader to do a new query
        // with this filter.
        if (newText != null) {
            newText = newText.trim();
            if (newText.length() == 0) {
                newText = null;
            }
        }
        // Don't do anything if the filter hasn't actually changed.
        // Prevents restarting the loader when restoring state.
        if (mFilter == null && newText == null) {
            return;
        }
        if (mFilter != null && mFilter.equals(newText)) {
            return;
        }
        mFilter = newText;
        restartLoader();
    }

    public void restartLoader() {
        getLoaderManager().restartLoader(0, null, ListPostsFragment.this);
    }

    /**
     * <p><strong>Note</strong>{@link Build.VERSION_CODES.HONEYCOMB}?
     * {@link Build.VERSION_CODES.HONEYCOMB HONEYCOMB}</p>
     * {@link Build.VERSION_CODES.HONEYCOMB HONEYCOMB}{@link android.widget.SearchView}
     * ?{@link EditText}
     *
     * @return ?{@link android.widget.SearchView SearchView}{@link EditText}
     */
    private EditText insertSearchEditText() {
        final EditText mSearchEditText = new EditText(getActivity());
        mSearchEditText.setId(SEARCH_EDIT_TEXT);
        mSearchEditText.setHint(R.string.search_hint);
        mSearchEditText.setSingleLine();
        mSearchEditText.setImeOptions(EditorInfo.IME_ACTION_DONE);
        mSearchEditText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
            }

            @Override
            public void afterTextChanged(Editable s) {
                onSearchTextChanged(s.toString());
                if (s.length() == 0) {
                    InputMethodManager imm = (InputMethodManager) getActivity()
                            .getSystemService(Context.INPUT_METHOD_SERVICE);
                    imm.hideSoftInputFromWindow(mSearchEditText.getWindowToken(), 0);
                    mLinearLayout.removeView(mSearchEditText);
                }
            }
        });
        mLinearLayout.addView(mSearchEditText, 0);
        return mSearchEditText;
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        Intent intent = new Intent(getActivity(), PostDetailsActivity.class);
        intent.putExtra(PostDetailsActivity.EXTRA_POST_ID, id);
        startActivity(intent);
    }

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        // This is called when a new Loader needs to be created.  This
        // sample only has one Loader, so we don't care about the ID.
        // First, pick the base URI to use depending on whether we are
        // currently filtering.
        Uri baseUri;
        //        if (mFilter != null) {
        //            baseUri = Uri.withAppendedPath(People.CONTENT_FILTER_URI, Uri.encode(mFilter));
        //        } else {
        baseUri = Contract.Posts.CONTENT_URI;
        //        }

        String source = getArguments().getString(SOURCE);
        String selection = null;
        String[] selectionArgs = null;
        if (!TextUtils.isEmpty(source)) {
            selection = Contract.Posts.COLUMN_NAME_SOURCE + "= ?";
            if (mFilter == null) {
                selectionArgs = new String[] { source };
            } else {
                selection += " AND (" + searchClause + ")";
                selectionArgs = new String[] { source, "%" + mFilter + "%", "%" + mFilter + "%",
                        "%" + mFilter + "%" };
            }
        } else if (mFilter != null) {
            selection = searchClause;
            selectionArgs = new String[] { "%" + mFilter + "%", "%" + mFilter + "%", "%" + mFilter + "%" };
        }
        // Now create and return a CursorLoader that will take care of
        // creating a Cursor for the data being displayed.
        return new CursorLoader(getActivity(), baseUri,
                new String[] { Contract.Posts._ID, Contract.Posts.COLUMN_NAME_TITLE,
                        Contract.Posts.COLUMN_NAME_CATEGORY, Contract.Posts.COLUMN_NAME_DATE,
                        Contract.Posts.COLUMN_NAME_AUTHOR },
                selection, selectionArgs, Contract.Posts.DEFAULT_SORT_ORDER);
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        // Swap the new cursor in.  (The framework will take care of closing the
        // old cursor once we return.)
        mAdapter.swapCursor(data);

        // The list should now be shown.
        if (isResumed()) {
            setListShown(true);
        } else {
            setListShownNoAnimation(true);
        }
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        // This is called when the last Cursor provided to onLoadFinished()
        // above is about to be closed.  We need to make sure we are no
        // longer using it.
        mAdapter.swapCursor(null);
    }

    public static class PostsCursorAdapter extends CursorAdapter {

        private final LayoutInflater mInflater;

        private static final SimpleDateFormat mDateFormat = new SimpleDateFormat("yyyy-MM-dd");

        public PostsCursorAdapter(Context context, Cursor c, int flags) {
            super(context, c, flags);
            mInflater = LayoutInflater.from(context);
        }

        @Override
        public void bindView(View view, Context context, Cursor cursor) {
            String tempString;
            tempString = cursor.getString(cursor.getColumnIndex(Contract.Posts.COLUMN_NAME_TITLE));
            ((TextView) view.findViewById(R.id.post_title)).setText(tempString);
            tempString = cursor.getString(cursor.getColumnIndex(Contract.Posts.COLUMN_NAME_CATEGORY));
            ((TextView) view.findViewById(R.id.post_category)).setText(tempString);
            tempString = cursor.getString(cursor.getColumnIndex(Contract.Posts.COLUMN_NAME_AUTHOR));
            ((TextView) view.findViewById(R.id.post_author)).setText(tempString);
            long date = cursor.getLong(cursor.getColumnIndex(Contract.Posts.COLUMN_NAME_DATE));
            ((TextView) view.findViewById(R.id.post_date)).setText(mDateFormat.format(new Date(date)));
        }

        @Override
        public View newView(Context context, Cursor cursor, ViewGroup parent) {
            return mInflater.inflate(R.layout.fragment_list_post_row, parent, false);
        }
    }
}