Android Open Source - android-wear-tutorial Books Fragment






From Project

Back to project page android-wear-tutorial.

License

The source code is released under:

Apache License

If you think the Android project android-wear-tutorial 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

/*
 * Copyright 2015 Simone Casagranda.//ww  w  .  j  av  a2  s .  com
 *
 * 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 com.alchemiasoft.book.fragment;

import android.content.Context;
import android.database.Cursor;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.PopupMenu;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.Gravity;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

import com.alchemiasoft.book.R;
import com.alchemiasoft.common.content.BookDB;
import com.alchemiasoft.book.fragment.base.RecyclerViewFragment;
import com.alchemiasoft.common.model.Book;
import com.alchemiasoft.book.service.BookActionService;
import com.alchemiasoft.common.util.ViewUtil;
import com.alchemiasoft.book.widget.SmartSwipeRefreshLayout;

import java.util.ArrayList;
import java.util.List;

/**
 * Fragment that displays books to the users.
 * <p/>
 * Created by Simone Casagranda on 20/12/14.
 */
public class BooksFragment extends RecyclerViewFragment implements LoaderManager.LoaderCallbacks<Cursor> {

    /**
     * Interface that is used to signal when the user selects a book.
     */
    private static interface OnBookSelectListener {

        /**
         * Called when a book is selected.
         *
         * @param book that has been selected.
         */
        void onBookSelected(@NonNull Book book);
    }

    /**
     * Key used to pass the owner filter. This parameter is completely optional.
     */
    private static final String KEY_OWNED = "com.alchemiasoft.book.OWNED";

    /**
     * Number of columns shown to the user.
     */
    private static final int COLUMN_COUNT = 2;

    /**
     * Id used for the book(s) loader.
     */
    private static final int ID_LOADER_BOOKS = 23;

    private static final String SELECTION = BookDB.Book.OWNED + " = ?";
    private static final String[] SELECT_OWNED = {String.valueOf(1)};

    /**
     * Creates a new instance of BookListFragment.
     *
     * @param context
     * @param owned   true to get only the owned books, false otherwise.
     * @return an instance of BookListFragment ready to be attached.
     */
    public static BooksFragment create(Context context, boolean owned) {
        final BooksFragment fragment = new BooksFragment();
        final Bundle args = new Bundle();
        args.putBoolean(KEY_OWNED, owned);
        fragment.setArguments(args);
        return fragment;
    }

    private BooksAdapter mAdapter;
    private StaggeredGridLayoutManager mLayoutManager;

    private final OnBookSelectListener mOnBookSelectListener = new OnBookSelectListener() {
        @Override
        public void onBookSelected(@NonNull Book book) {
            final FragmentActivity activity = getActivity();
            if (activity != null) {
                activity.getSupportFragmentManager().beginTransaction().replace(R.id.content, BookDetailFragment.create(book.getId())).commit();
            }
        }
    };

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        setEmptyText(getString(R.string.no_books));
        final RecyclerView recyclerView = getRecyclerView();
        // Set up adapter and recycler view
        mAdapter = new BooksAdapter();
        mAdapter.setOnBookSelectListener(mOnBookSelectListener);
        setRecyclerAdapter(mAdapter);
        mLayoutManager = new StaggeredGridLayoutManager(COLUMN_COUNT, GridLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(mLayoutManager);
        recyclerView.setHasFixedSize(true);
        setScrollInterceptor(new SmartSwipeRefreshLayout.ScrollInterceptor() {
            @Override
            public boolean canChildScrollUp() {
                // We don't need any scroll update
                return true;
            }
        });
    }

    @Override
    public void onResume() {
        super.onResume();
        // Initialising the loader
        getLoaderManager().initLoader(ID_LOADER_BOOKS, getArguments(), this);
    }

    @Override
    public void onPause() {
        super.onPause();
        getLoaderManager().destroyLoader(ID_LOADER_BOOKS);
    }

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        switch (id) {
            case ID_LOADER_BOOKS:
                final boolean owned = args.getBoolean(KEY_OWNED);
                if (owned) {
                    return new CursorLoader(getActivity(), BookDB.Book.CONTENT_URI, null, SELECTION, SELECT_OWNED, null);
                } else {
                    return new CursorLoader(getActivity(), BookDB.Book.CONTENT_URI, null, null, null, null);
                }
            default:
                throw new IllegalArgumentException("loader id=" + id + " is not supported!");
        }
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        final List<Book> books = Book.allFrom(data);
        mAdapter.swap(books);
        if (isResumed()) {
            setContentShown(true);
        } else {
            setContentShownNoAnimation(true);
        }
    }

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

    /**
     * Holder that has got references to the UI for a book entry.
     */
    private static class BookHolder extends RecyclerView.ViewHolder {

        private TextView mTitleTextView, mAuthorTextView;
        private View mOwnedView, mOverflowView;

        private BookHolder(View itemView) {
            super(itemView);
            mTitleTextView = (TextView) itemView.findViewById(R.id.title);
            mAuthorTextView = (TextView) itemView.findViewById(R.id.author);
            mOwnedView = itemView.findViewById(R.id.owned_book);
            mOverflowView = itemView.findViewById(R.id.menu_overflow);
        }

    }

    /**
     * Adapter that takes care of displaying the right data in the BookHolder(s)
     * based on the current/expected Book entries.
     */
    private static class BooksAdapter extends RecyclerView.Adapter<BookHolder> {

        /**
         * Books currently shown.
         */
        private final List<Book> mBooks = new ArrayList<>();

        private OnBookSelectListener mOnBookSelectListener;

        @Override
        public BookHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
            final View view = View.inflate(viewGroup.getContext(), R.layout.item_book, null);
            return new BookHolder(view);
        }

        @Override
        public void onBindViewHolder(final BookHolder bookHolder, int pos) {
            final Book book = mBooks.get(pos);
            bookHolder.mTitleTextView.setText(book.getTitle());
            bookHolder.mAuthorTextView.setText(book.getAuthor());
            if (book.isOwned()) {
                bookHolder.mOwnedView.setBackgroundResource(R.drawable.owned_book);
            } else {
                ViewUtil.setBackground(bookHolder.mOwnedView, null);
            }
            bookHolder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (mOnBookSelectListener != null) {
                        mOnBookSelectListener.onBookSelected(book);
                    }
                }
            });
            bookHolder.mOverflowView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(final View v) {
                    final PopupMenu popup = new PopupMenu(v.getContext(), v, Gravity.BOTTOM);
                    final MenuInflater inflater = popup.getMenuInflater();
                    inflater.inflate(R.menu.menu_book, popup.getMenu());
                    popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
                        @Override
                        public boolean onMenuItemClick(MenuItem menuItem) {
                            final Context context = v.getContext();
                            switch (menuItem.getItemId()) {
                                case R.id.action_buy:
                                    if (book.isOwned()) {
                                        Toast.makeText(context, context.getString(R.string.book_already_owned), Toast.LENGTH_SHORT).show();
                                    } else {
                                        context.startService(BookActionService.IntentBuilder.buy(context, book).build());
                                    }
                                    return true;
                                case R.id.action_sell:
                                    if (!book.isOwned()) {
                                        Toast.makeText(context, context.getString(R.string.book_not_owned), Toast.LENGTH_SHORT).show();
                                    } else {
                                        context.startService(BookActionService.IntentBuilder.sell(context, book).build());
                                    }
                                    return true;
                                default:
                                    return false;
                            }
                        }
                    });
                    popup.show();
                }
            });
        }

        public void setOnBookSelectListener(OnBookSelectListener listener) {
            this.mOnBookSelectListener = listener;
        }

        @Override
        public int getItemCount() {
            return mBooks.size();
        }

        @Override
        public long getItemId(int pos) {
            return mBooks.get(pos).getId();
        }

        public void swap(List<Book> books) {
            mBooks.clear();
            if (books != null) {
                mBooks.addAll(books);
            }
            notifyDataSetChanged();
        }
    }
}




Java Source Code List

com.alchemiasoft.book.ApplicationTest.java
com.alchemiasoft.book.activity.HomeActivity.java
com.alchemiasoft.book.fragment.BookDetailFragment.java
com.alchemiasoft.book.fragment.BooksFragment.java
com.alchemiasoft.book.fragment.base.RecyclerViewFragment.java
com.alchemiasoft.book.receiver.BootCompletedReceiver.java
com.alchemiasoft.book.receiver.SuggestionReceiver.java
com.alchemiasoft.book.service.BookActionService.java
com.alchemiasoft.book.service.SuggestionService.java
com.alchemiasoft.book.user.UserData.java
com.alchemiasoft.book.widget.SmartSwipeRefreshLayout.java
com.alchemiasoft.books.activity.BooksActivity.java
com.alchemiasoft.common.ApplicationTest.java
com.alchemiasoft.common.content.BookContentProvider.java
com.alchemiasoft.common.content.BookDBOpenHelper.java
com.alchemiasoft.common.content.BookDB.java
com.alchemiasoft.common.lib.Constants.java
com.alchemiasoft.common.model.Book.java
com.alchemiasoft.common.util.AlarmUtil.java
com.alchemiasoft.common.util.IOUtils.java
com.alchemiasoft.common.util.ResUtil.java
com.alchemiasoft.common.util.ViewUtil.java