com.cuddlesoft.nori.fragment.SearchResultGridFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.cuddlesoft.nori.fragment.SearchResultGridFragment.java

Source

/*
 * This file is part of nori.
 * Copyright (c) 2014 vomitcuddle <shinku@dollbooru.org>
 * License: ISC
 */

package com.cuddlesoft.nori.fragment;

import android.app.Activity;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;

import com.cuddlesoft.nori.R;
import com.cuddlesoft.nori.widget.SquareImageView;
import com.cuddlesoft.norilib.Image;
import com.cuddlesoft.norilib.SearchResult;
import com.squareup.picasso.Picasso;

/** Shows images from a {@link SearchResult} as a scrollable grid of thumbnails. */
public class SearchResultGridFragment extends Fragment
        implements AdapterView.OnItemClickListener, AbsListView.OnScrollListener {
    /** Identifier used for saving currently displayed search result in {@link #onSaveInstanceState(android.os.Bundle)}. */
    private static final String BUNDLE_ID_SEARCH_RESULT = "com.cuddlesoft.nori.SearchResult";
    /** Interface used for communication with parent class. */
    private OnSearchResultGridFragmentInteractionListener mListener;
    /** GridView used to display the thumbnails. */
    private GridView gridView;
    /** Search result displayed by the SearchResultGridFragment. */
    private SearchResult searchResult;
    /** Adapter used by the GridView in this fragment. */
    private BaseAdapter gridAdapter = new BaseAdapter() {
        @Override
        public int getCount() {
            // Return count of images.
            if (searchResult == null) {
                return 0;
            }
            return searchResult.getImages().length;
        }

        @Override
        public Image getItem(int position) {
            // Return image at given position.
            return searchResult.getImages()[position];
        }

        @Override
        public long getItemId(int position) {
            return Long.valueOf(getItem(position).id);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            // Get image object at given position.
            Image image = getItem(position);
            // Create image view for given position.
            ImageView imageView = (ImageView) convertView;

            // Create a new image, if not recycled.
            if (imageView == null) {
                imageView = new SquareImageView(getActivity());
                imageView.setLayoutParams(new GridView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                        ViewGroup.LayoutParams.MATCH_PARENT));
            }

            int previewSize;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                // Resize thumbnails to actual GridView column width on Jelly Bean and above.
                previewSize = gridView.getColumnWidth();
            } else {
                // Fallback to requested column width on older versions.
                previewSize = getGridViewColumnWidth();
            }

            // Load image into view.
            Picasso.with(getActivity()).load(image.previewUrl).resize(previewSize, previewSize).centerCrop()
                    .placeholder(R.color.network_thumbnail_placeholder).into(imageView);

            return imageView;
        }
    };

    /** Required public empty constructor. */
    public SearchResultGridFragment() {
    }

    /**
     * Get search result displayed by this fragment.
     *
     * @return Search result shown in this fragment.
     */
    public SearchResult getSearchResult() {
        return this.searchResult;
    }

    /**
     * Update the SearchResult displayed by this fragment.
     *
     * @param searchResult Search result. Set to null to hide the current search result.
     */
    public void setSearchResult(SearchResult searchResult) {
        if (searchResult == null) {
            this.searchResult = null;
            gridAdapter.notifyDataSetInvalidated();
        } else {
            this.searchResult = searchResult;
            gridAdapter.notifyDataSetChanged();
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_search_result_grid, container, false);
        // Restore SearchResult from saved instance state to preserve search results across screen rotations.
        if (savedInstanceState != null && savedInstanceState.containsKey(BUNDLE_ID_SEARCH_RESULT)) {
            searchResult = savedInstanceState.getParcelable(BUNDLE_ID_SEARCH_RESULT);
        }
        // Set adapter for GridView.
        gridView = (GridView) view.findViewById(R.id.image_grid);
        gridView.setColumnWidth(getGridViewColumnWidth());
        gridView.setAdapter(gridAdapter);
        gridView.setOnScrollListener(this);
        gridView.setOnItemClickListener(this);

        // Return inflated view.
        return view;
    }

    /**
     * Get the grid view column size from the thumbnail size shared preference.
     *
     * @return Minimum column size, in pixels.
     */
    private int getGridViewColumnWidth() {
        // Get preference value from SharedPreference.
        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
        String previewSize = sharedPreferences.getString(getString(R.string.preference_previewSize_key),
                getString(R.string.preference_previewSize_default));

        // Return dimension for given preference value, in pixels.
        switch (previewSize) {
        case "small":
            return getResources().getDimensionPixelSize(R.dimen.previewSize_small);
        case "medium":
            return getResources().getDimensionPixelSize(R.dimen.previewSize_medium);
        case "large":
            return getResources().getDimensionPixelSize(R.dimen.previewSize_large);
        default:
            return getResources().getDimensionPixelSize(R.dimen.previewSize_medium);
        }

    }

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

        // Get a reference to parent activity, making sure that it implements the proper callback interface.
        try {
            mListener = (OnSearchResultGridFragmentInteractionListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        // Preserve currently displayed SearchResult.
        if (searchResult != null) {
            outState.putParcelable(BUNDLE_ID_SEARCH_RESULT, searchResult);
        }
    }

    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
        if (mListener != null) {
            // Notify parent activity that image has been clicked.
            mListener.onImageSelected((Image) gridAdapter.getItem(position), position);
        }
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        // Implement endless scrolling.
        // Fetch more images if near the end of the list and more images are available for the SearchResult.
        if ((totalItemCount - visibleItemCount) <= (firstVisibleItem + 10) && searchResult != null
                && searchResult.hasNextPage() && mListener != null) {
            mListener.fetchMoreImages(searchResult);
        }
    }

    public interface OnSearchResultGridFragmentInteractionListener {
        /**
         * Called when {@link com.cuddlesoft.norilib.Image} in the search result grid is selected by the user.
         *
         * @param image    Image selected.
         * @param position Index of the image in the {@link SearchResult}.
         */
        public void onImageSelected(Image image, int position);

        /**
         * Called when the user scrolls the thumbnail {@link android.widget.GridView} near the end and more images should be fetched
         * to implement "endless scrolling".
         *
         * @param searchResult Search result for which more images should be fetched.
         */
        public void fetchMoreImages(SearchResult searchResult);
    }

}