Java tutorial
/* * Copyright 2014 Uwe Trottmann * * 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.battlelancer.seriesguide.ui; import android.content.Intent; import android.database.Cursor; import android.os.Bundle; import android.support.v4.app.ActivityCompat; import android.support.v4.app.ActivityOptionsCompat; import android.support.v4.app.Fragment; import android.support.v4.app.LoaderManager.LoaderCallbacks; import android.support.v4.content.Loader; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.view.inputmethod.EditorInfo; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; import android.widget.GridView; import android.widget.PopupMenu; import android.widget.TextView; import android.widget.TextView.OnEditorActionListener; import butterknife.ButterKnife; import butterknife.InjectView; import com.battlelancer.seriesguide.R; import com.battlelancer.seriesguide.adapters.MoviesAdapter; import com.battlelancer.seriesguide.loaders.TmdbMoviesLoader; import com.battlelancer.seriesguide.provider.SeriesGuideContract; import com.battlelancer.seriesguide.settings.SearchSettings; import com.battlelancer.seriesguide.util.MovieTools; import com.battlelancer.seriesguide.util.SearchHistory; import com.battlelancer.seriesguide.util.Utils; import com.uwetrottmann.androidutils.AndroidUtils; import com.uwetrottmann.tmdb.entities.Movie; import java.util.List; /** * Allows searching for movies on themoviedb.org, displays results in a nice grid. */ public class MoviesSearchFragment extends Fragment implements LoaderCallbacks<List<Movie>>, OnItemClickListener, MoviesAdapter.PopupMenuClickListener { private static final String SEARCH_QUERY_KEY = "search_query"; protected static final String TAG = "Movies Search"; private MoviesAdapter resultsAdapter; private SearchHistory searchHistory; private ArrayAdapter<String> searchHistoryAdapter; @InjectView(R.id.containerMoviesSearchContent) View resultsContainer; @InjectView(R.id.progressBarMoviesSearch) View progressBar; @InjectView(android.R.id.list) GridView resultsGridView; @InjectView(R.id.emptyViewMoviesSearch) TextView emptyView; @InjectView(R.id.editTextMoviesSearch) AutoCompleteTextView searchBox; @InjectView(R.id.buttonMoviesSearchClear) View clearButton; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRetainInstance(true); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.fragment_movies_search, container, false); ButterKnife.inject(this, v); // setup grid view resultsGridView.setEmptyView(emptyView); resultsGridView.setOnItemClickListener(this); // setup search box searchBox.setThreshold(1); searchBox.setOnEditorActionListener(new OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if (actionId == EditorInfo.IME_ACTION_SEARCH || (event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) { search(); return true; } return false; } }); searchBox.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { ((AutoCompleteTextView) v).showDropDown(); } }); searchBox.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { search(); } }); // set in code as XML is overridden searchBox.setImeOptions(EditorInfo.IME_ACTION_SEARCH); searchBox.setInputType(EditorInfo.TYPE_CLASS_TEXT); // setup clear button clearButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { searchBox.setText(null); searchBox.requestFocus(); } }); setProgressVisible(false, false); return v; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // setup adapter resultsAdapter = new MoviesAdapter(getActivity(), this); resultsGridView.setAdapter(resultsAdapter); // setup search history if (searchHistory == null || searchHistoryAdapter == null) { searchHistory = new SearchHistory(getActivity(), SearchSettings.KEY_SUFFIX_TMDB); searchHistoryAdapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_dropdown_item_1line, searchHistory.getSearchHistory()); searchBox.setAdapter(searchHistoryAdapter); } getLoaderManager().initLoader(MoviesActivity.SEARCH_LOADER_ID, null, this); setHasOptionsMenu(true); } @Override public void onDestroyView() { super.onDestroyView(); ButterKnife.reset(this); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.search_history_menu, menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { int itemId = item.getItemId(); if (itemId == R.id.menu_action_search_clear_history) { if (searchHistory != null && searchHistoryAdapter != null) { searchHistory.clearHistory(); searchHistoryAdapter.clear(); } return true; } return super.onOptionsItemSelected(item); } private void search() { String query = searchBox.getText().toString(); Bundle args = new Bundle(); args.putString(SEARCH_QUERY_KEY, query); getLoaderManager().restartLoader(MoviesActivity.SEARCH_LOADER_ID, args, this); // update history if (searchHistory.saveRecentSearch(query)) { searchHistoryAdapter.clear(); searchHistoryAdapter.addAll(searchHistory.getSearchHistory()); } } private void setProgressVisible(boolean visible, boolean animate) { if (animate) { Animation out = AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_out); Animation in = AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_in); resultsContainer.startAnimation(visible ? out : in); progressBar.startAnimation(visible ? in : out); } resultsContainer.setVisibility(visible ? View.GONE : View.VISIBLE); progressBar.setVisibility(visible ? View.VISIBLE : View.GONE); } @Override public Loader<List<Movie>> onCreateLoader(int loaderId, Bundle args) { setProgressVisible(true, false); String query = null; if (args != null) { query = args.getString(SEARCH_QUERY_KEY); } return new TmdbMoviesLoader(getActivity(), query); } @Override public void onLoadFinished(Loader<List<Movie>> loader, List<Movie> data) { if (AndroidUtils.isNetworkConnected(getActivity())) { emptyView.setText(R.string.movies_empty); } else { emptyView.setText(R.string.offline); } resultsAdapter.setData(data); setProgressVisible(false, true); } @Override public void onLoaderReset(Loader<List<Movie>> loader) { resultsAdapter.setData(null); } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Movie movie = resultsAdapter.getItem(position); // launch details activity Intent i = new Intent(getActivity(), MovieDetailsActivity.class); i.putExtra(MovieDetailsFragment.InitBundle.TMDB_ID, movie.id); ActivityCompat.startActivity(getActivity(), i, ActivityOptionsCompat .makeScaleUpAnimation(view, 0, 0, view.getWidth(), view.getHeight()).toBundle()); } private void fireTrackerEvent(String label) { Utils.trackAction(getActivity(), TAG, label); } @Override public void onPopupMenuClick(View v, final int movieTmdbId) { PopupMenu popupMenu = new PopupMenu(v.getContext(), v); popupMenu.inflate(R.menu.movies_popup_menu); // check if movie is already in watchlist or collection boolean isInWatchlist = false; boolean isInCollection = false; Cursor movie = getActivity().getContentResolver().query( SeriesGuideContract.Movies.buildMovieUri(movieTmdbId), new String[] { SeriesGuideContract.Movies.IN_WATCHLIST, SeriesGuideContract.Movies.IN_COLLECTION }, null, null, null); if (movie != null) { if (movie.moveToFirst()) { isInWatchlist = movie.getInt(0) == 1; isInCollection = movie.getInt(1) == 1; } movie.close(); } Menu menu = popupMenu.getMenu(); menu.findItem(R.id.menu_action_movies_watchlist_add).setVisible(!isInWatchlist); menu.findItem(R.id.menu_action_movies_watchlist_remove).setVisible(isInWatchlist); menu.findItem(R.id.menu_action_movies_collection_add).setVisible(!isInCollection); menu.findItem(R.id.menu_action_movies_collection_remove).setVisible(isInCollection); popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { switch (item.getItemId()) { case R.id.menu_action_movies_watchlist_add: { MovieTools.addToWatchlist(getActivity(), movieTmdbId); fireTrackerEvent("Add to watchlist"); return true; } case R.id.menu_action_movies_watchlist_remove: { MovieTools.removeFromWatchlist(getActivity(), movieTmdbId); fireTrackerEvent("Remove from watchlist"); return true; } case R.id.menu_action_movies_collection_add: { MovieTools.addToCollection(getActivity(), movieTmdbId); fireTrackerEvent("Add to collection"); return true; } case R.id.menu_action_movies_collection_remove: { MovieTools.removeFromCollection(getActivity(), movieTmdbId); fireTrackerEvent("Remove from collection"); return true; } } return false; } }); popupMenu.show(); } }