favoritelist
@@ -1,5 +1,16 @@
|
|||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
|
apply plugin: 'android-apt'
|
||||||
|
|
||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
classpath 'com.android.tools.build:gradle:1.3.0'
|
||||||
|
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
|
||||||
|
}
|
||||||
|
}
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 23
|
compileSdkVersion 23
|
||||||
buildToolsVersion "23.0.1"
|
buildToolsVersion "23.0.1"
|
||||||
@@ -39,4 +50,7 @@ dependencies {
|
|||||||
compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'
|
compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'
|
||||||
|
|
||||||
compile 'com.jakewharton:butterknife:7.0.1'
|
compile 'com.jakewharton:butterknife:7.0.1'
|
||||||
|
|
||||||
|
apt 'net.simonvt.schematic:schematic-compiler:0.6.3'
|
||||||
|
compile 'net.simonvt.schematic:schematic:0.6.3'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,11 @@
|
|||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<provider
|
||||||
|
android:authorities="net.headlezz.udacityproject1.FavoriteProvider"
|
||||||
|
android:name="net.headlezz.udacityproject1.provider.FavoriteProvider"
|
||||||
|
android:exported="false" />
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import android.support.v4.app.FragmentManager;
|
|||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
|
|
||||||
|
import net.headlezz.udacityproject1.movielist.MovieListFragment;
|
||||||
import net.headlezz.udacityproject1.tmdbapi.Movie;
|
import net.headlezz.udacityproject1.tmdbapi.Movie;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import android.widget.ImageView;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import net.headlezz.udacityproject1.favorites.FavoriteProviderHelper;
|
||||||
import net.headlezz.udacityproject1.tmdbapi.Movie;
|
import net.headlezz.udacityproject1.tmdbapi.Movie;
|
||||||
import net.headlezz.udacityproject1.tmdbapi.TMDBApi;
|
import net.headlezz.udacityproject1.tmdbapi.TMDBApi;
|
||||||
import net.headlezz.udacityproject1.tmdbapi.Video;
|
import net.headlezz.udacityproject1.tmdbapi.Video;
|
||||||
@@ -51,6 +52,9 @@ public class MovieDetailsFragment extends Fragment implements Callback<VideoList
|
|||||||
Movie mMovie;
|
Movie mMovie;
|
||||||
VideoList mVideoList;
|
VideoList mVideoList;
|
||||||
|
|
||||||
|
FavoriteProviderHelper mProvderHelper;
|
||||||
|
boolean isFavorite;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hold a reference to the videolist download call so
|
* Hold a reference to the videolist download call so
|
||||||
* it can be canceled when stopping
|
* it can be canceled when stopping
|
||||||
@@ -69,9 +73,11 @@ public class MovieDetailsFragment extends Fragment implements Callback<VideoList
|
|||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
|
mProvderHelper = new FavoriteProviderHelper(getContext().getContentResolver());
|
||||||
if(getArguments().containsKey(BUNDLE_ARG_MOVIE)) {
|
if(getArguments().containsKey(BUNDLE_ARG_MOVIE)) {
|
||||||
mMovie = getArguments().getParcelable(BUNDLE_ARG_MOVIE);
|
mMovie = getArguments().getParcelable(BUNDLE_ARG_MOVIE);
|
||||||
Log.d(TAG, "Bundled movie: " + mMovie.getTitle());
|
Log.d(TAG, "Bundled movie: " + mMovie.getTitle());
|
||||||
|
isFavorite = mProvderHelper.isFavorite(mMovie); // TODO async?
|
||||||
} else
|
} else
|
||||||
throw new RuntimeException(TAG + " opened without bundled movie!");
|
throw new RuntimeException(TAG + " opened without bundled movie!");
|
||||||
|
|
||||||
@@ -165,6 +171,8 @@ public class MovieDetailsFragment extends Fragment implements Callback<VideoList
|
|||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||||
super.onCreateOptionsMenu(menu, inflater);
|
super.onCreateOptionsMenu(menu, inflater);
|
||||||
inflater.inflate(R.menu.movie_details_menu, menu);
|
inflater.inflate(R.menu.movie_details_menu, menu);
|
||||||
|
MenuItem favItem = menu.findItem(R.id.action_favorite);
|
||||||
|
favItem.setIcon(isFavorite ? R.drawable.ic_action_star_10 : R.drawable.ic_action_star_0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -172,11 +180,26 @@ public class MovieDetailsFragment extends Fragment implements Callback<VideoList
|
|||||||
if(item.getItemId() == R.id.action_share) {
|
if(item.getItemId() == R.id.action_share) {
|
||||||
shareTrailer();
|
shareTrailer();
|
||||||
return true;
|
return true;
|
||||||
|
} else if(item.getItemId() == R.id.action_favorite) {
|
||||||
|
switchFavorite();
|
||||||
|
item.setIcon(isFavorite ? R.drawable.ic_action_star_10 : R.drawable.ic_action_star_0);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* removes or adds the movie to stored favorites
|
||||||
|
*/
|
||||||
|
private void switchFavorite() { // TODO async?
|
||||||
|
if(isFavorite)
|
||||||
|
mProvderHelper.removeFavorite(mMovie);
|
||||||
|
else
|
||||||
|
mProvderHelper.addFavorite(mMovie);
|
||||||
|
isFavorite = !isFavorite;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fires an intent to share the trailer url of this movie
|
* Fires an intent to share the trailer url of this movie
|
||||||
* Code from http://www.techrepublic.com/blog/software-engineer/get-social-using-android-intents-to-share-a-link/
|
* Code from http://www.techrepublic.com/blog/software-engineer/get-social-using-android-intents-to-share-a-link/
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package net.headlezz.udacityproject1.favorites;
|
||||||
|
|
||||||
|
import net.simonvt.schematic.annotation.DataType;
|
||||||
|
import net.simonvt.schematic.annotation.NotNull;
|
||||||
|
import net.simonvt.schematic.annotation.PrimaryKey;
|
||||||
|
|
||||||
|
public interface FavoriteColumns {
|
||||||
|
|
||||||
|
@DataType(DataType.Type.INTEGER) @PrimaryKey String _ID = "_id";
|
||||||
|
|
||||||
|
@DataType(DataType.Type.TEXT) @NotNull String TITLE = "title";
|
||||||
|
|
||||||
|
@DataType(DataType.Type.TEXT) @NotNull String POSTERPATH = "posterpath";
|
||||||
|
|
||||||
|
@DataType(DataType.Type.REAL) @NotNull String AVRATING = "avrating";
|
||||||
|
|
||||||
|
@DataType(DataType.Type.INTEGER) @NotNull String RELEASEDATE = "release";
|
||||||
|
|
||||||
|
@DataType(DataType.Type.TEXT) @NotNull String OVERVIEW = "overview";
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package net.headlezz.udacityproject1.favorites;
|
||||||
|
|
||||||
|
import net.simonvt.schematic.annotation.Database;
|
||||||
|
import net.simonvt.schematic.annotation.Table;
|
||||||
|
|
||||||
|
@Database(version=FavoriteDatabase.VERSION, packageName="net.headlezz.udacityproject1.provider")
|
||||||
|
public class FavoriteDatabase {
|
||||||
|
|
||||||
|
public static final int VERSION = 1;
|
||||||
|
|
||||||
|
@Table(FavoriteColumns.class) public static final String favorites = "favorites";
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package net.headlezz.udacityproject1.favorites;
|
||||||
|
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
import net.simonvt.schematic.annotation.ContentProvider;
|
||||||
|
import net.simonvt.schematic.annotation.ContentUri;
|
||||||
|
import net.simonvt.schematic.annotation.TableEndpoint;
|
||||||
|
|
||||||
|
@ContentProvider(authority = FavoriteProvider.AUTHORITY, database = FavoriteDatabase.class, packageName="net.headlezz.udacityproject1.provider")
|
||||||
|
public class FavoriteProvider {
|
||||||
|
|
||||||
|
public static final String AUTHORITY = "net.headlezz.udacityproject1.FavoriteProvider";
|
||||||
|
static final Uri BASE_CONTENT_URI = Uri.parse("content://" + AUTHORITY);
|
||||||
|
|
||||||
|
@TableEndpoint(table = FavoriteDatabase.favorites)
|
||||||
|
public static class Favorites {
|
||||||
|
|
||||||
|
@ContentUri(
|
||||||
|
path = "favorites",
|
||||||
|
type = "vnd.android.cursor.dir/list",
|
||||||
|
defaultSort = FavoriteColumns.TITLE + " ASC")
|
||||||
|
public static final Uri FAVORITES_URI = Uri.parse("content://" + AUTHORITY + "/favorites");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package net.headlezz.udacityproject1.favorites;
|
||||||
|
|
||||||
|
import android.content.ContentResolver;
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.database.Cursor;
|
||||||
|
|
||||||
|
import net.headlezz.udacityproject1.tmdbapi.Movie;
|
||||||
|
|
||||||
|
public class FavoriteProviderHelper {
|
||||||
|
|
||||||
|
private ContentResolver mResolver;
|
||||||
|
|
||||||
|
public FavoriteProviderHelper(ContentResolver resolver) {
|
||||||
|
mResolver = resolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cursor getAllFavorites() {
|
||||||
|
String[] projection = {
|
||||||
|
FavoriteColumns._ID,
|
||||||
|
FavoriteColumns.TITLE,
|
||||||
|
FavoriteColumns.POSTERPATH,
|
||||||
|
FavoriteColumns.AVRATING,
|
||||||
|
FavoriteColumns.RELEASEDATE,
|
||||||
|
FavoriteColumns.OVERVIEW
|
||||||
|
};
|
||||||
|
return mResolver.query(FavoriteProvider.Favorites.FAVORITES_URI, projection, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFavorite(Movie movie) {
|
||||||
|
String[] projection = {FavoriteColumns._ID};
|
||||||
|
String selection = FavoriteColumns.TITLE + "=?";
|
||||||
|
String[] selectionArgs = new String[]{movie.getTitle()};
|
||||||
|
Cursor cursor = mResolver.query(FavoriteProvider.Favorites.FAVORITES_URI, projection, selection, selectionArgs, null);
|
||||||
|
if (cursor != null && cursor.getCount() > 0)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addFavorite(Movie movie) {
|
||||||
|
ContentValues values = new ContentValues();
|
||||||
|
values.put(FavoriteColumns._ID, movie.getId());
|
||||||
|
values.put(FavoriteColumns.TITLE, movie.getTitle());
|
||||||
|
values.put(FavoriteColumns.OVERVIEW, movie.getOverview());
|
||||||
|
values.put(FavoriteColumns.POSTERPATH, movie.getPosterPath());
|
||||||
|
values.put(FavoriteColumns.AVRATING, movie.getAvRating());
|
||||||
|
values.put(FavoriteColumns.RELEASEDATE, movie.getReleaseDate().getTime());
|
||||||
|
mResolver.insert(FavoriteProvider.Favorites.FAVORITES_URI, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeFavorite(Movie movie) {
|
||||||
|
mResolver.delete(FavoriteProvider.Favorites.FAVORITES_URI, FavoriteColumns._ID + "=?", new String[]{String.valueOf(movie.getId())});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package net.headlezz.udacityproject1;
|
package net.headlezz.udacityproject1.movielist;
|
||||||
|
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
@@ -6,20 +6,20 @@ import android.view.View;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
import net.headlezz.udacityproject1.MovieNavigation;
|
||||||
|
import net.headlezz.udacityproject1.R;
|
||||||
import net.headlezz.udacityproject1.tmdbapi.Movie;
|
import net.headlezz.udacityproject1.tmdbapi.Movie;
|
||||||
import net.headlezz.udacityproject1.tmdbapi.MovieList;
|
|
||||||
import net.headlezz.udacityproject1.tmdbapi.TMDBApi;
|
import net.headlezz.udacityproject1.tmdbapi.TMDBApi;
|
||||||
|
|
||||||
import java.util.List;
|
/**
|
||||||
|
* Abstract class for shwoing a list of movie posters
|
||||||
public class MovieListAdapter extends RecyclerView.Adapter<MovieListAdapter.MovieViewHolder>{
|
*/
|
||||||
|
public abstract class AbstractMovieListAdapter extends RecyclerView.Adapter<AbstractMovieListAdapter.MovieViewHolder> {
|
||||||
|
|
||||||
MovieNavigation mMovieNavigation;
|
MovieNavigation mMovieNavigation;
|
||||||
List<Movie> mMovies;
|
|
||||||
|
|
||||||
public MovieListAdapter(MovieNavigation mn, MovieList movieList) {
|
public AbstractMovieListAdapter(MovieNavigation mn) {
|
||||||
mMovieNavigation = mn;
|
mMovieNavigation = mn;
|
||||||
mMovies = movieList.getList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -30,13 +30,14 @@ public class MovieListAdapter extends RecyclerView.Adapter<MovieListAdapter.Movi
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(MovieViewHolder holder, int position) {
|
public void onBindViewHolder(MovieViewHolder holder, int position) {
|
||||||
holder.setMovie(mMovies.get(position));
|
holder.setMovie(getMovieForPosition(position));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public int getItemCount() {
|
* @param position of the list
|
||||||
return mMovies.size();
|
* @return the movie displayed for the given position
|
||||||
}
|
*/
|
||||||
|
protected abstract Movie getMovieForPosition(int position);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Viewholder for the movie items
|
* Viewholder for the movie items
|
||||||
@@ -62,5 +63,4 @@ public class MovieListAdapter extends RecyclerView.Adapter<MovieListAdapter.Movi
|
|||||||
TMDBApi.loadPoster(ivPoster, movie);
|
TMDBApi.loadPoster(ivPoster, movie);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
package net.headlezz.udacityproject1.movielist;
|
||||||
|
|
||||||
|
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.database.DataSetObserver;
|
||||||
|
|
||||||
|
import net.headlezz.udacityproject1.MovieNavigation;
|
||||||
|
import net.headlezz.udacityproject1.favorites.FavoriteColumns;
|
||||||
|
import net.headlezz.udacityproject1.tmdbapi.Movie;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MovieListAdapter implementation for showing movies from a cursor
|
||||||
|
* Modified version of https://gist.github.com/skyfishjy/443b7448f59be978bc59
|
||||||
|
*/
|
||||||
|
public class CursorMovieListAdapter extends AbstractMovieListAdapter {
|
||||||
|
|
||||||
|
private Cursor mCursor;
|
||||||
|
private boolean mDataValid;
|
||||||
|
private int mRowIdColumn;
|
||||||
|
private DataSetObserver mDataSetObserver;
|
||||||
|
|
||||||
|
public CursorMovieListAdapter(Cursor cursor, MovieNavigation mn) {
|
||||||
|
super(mn);
|
||||||
|
mCursor = cursor;
|
||||||
|
mDataValid = cursor != null;
|
||||||
|
mRowIdColumn = mDataValid ? mCursor.getColumnIndex(FavoriteColumns._ID) : -1;
|
||||||
|
mDataSetObserver = new NotifyingDataSetObserver();
|
||||||
|
if (mCursor != null) {
|
||||||
|
mCursor.registerDataSetObserver(mDataSetObserver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Movie getMovieForPosition(int position) {
|
||||||
|
if (!mDataValid) {
|
||||||
|
throw new IllegalStateException("this should only be called when the cursor is valid");
|
||||||
|
}
|
||||||
|
if (!mCursor.moveToPosition(position)) {
|
||||||
|
throw new IllegalStateException("couldn't move cursor to position " + position);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Movie.fromCurrentCursorPosition(mCursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
if (mDataValid && mCursor != null) {
|
||||||
|
return mCursor.getCount();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getItemId(int position) {
|
||||||
|
if (mDataValid && mCursor != null && mCursor.moveToPosition(position)) {
|
||||||
|
return mCursor.getLong(mRowIdColumn);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setHasStableIds(boolean hasStableIds) {
|
||||||
|
super.setHasStableIds(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class NotifyingDataSetObserver extends DataSetObserver {
|
||||||
|
@Override
|
||||||
|
public void onChanged() {
|
||||||
|
super.onChanged();
|
||||||
|
mDataValid = true;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInvalidated() {
|
||||||
|
super.onInvalidated();
|
||||||
|
mDataValid = false;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
//There is no notifyDataSetInvalidated() method in RecyclerView.Adapter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package net.headlezz.udacityproject1.movielist;
|
||||||
|
|
||||||
|
import net.headlezz.udacityproject1.MovieNavigation;
|
||||||
|
import net.headlezz.udacityproject1.tmdbapi.Movie;
|
||||||
|
import net.headlezz.udacityproject1.tmdbapi.MovieList;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MovieListAdapter implementation for showing movies from a list of movies
|
||||||
|
*/
|
||||||
|
public class MovieListAdapter extends AbstractMovieListAdapter {
|
||||||
|
|
||||||
|
List<Movie> mMovies;
|
||||||
|
|
||||||
|
public MovieListAdapter(MovieNavigation mn, MovieList movieList) {
|
||||||
|
super(mn);
|
||||||
|
mMovies = movieList.getList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return mMovies.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Movie getMovieForPosition(int position) {
|
||||||
|
return mMovies.get(position);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
package net.headlezz.udacityproject1;
|
package net.headlezz.udacityproject1.movielist;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
|
import android.database.Cursor;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v7.widget.GridLayoutManager;
|
import android.support.v7.widget.GridLayoutManager;
|
||||||
@@ -16,6 +17,9 @@ import android.view.ViewGroup;
|
|||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import net.headlezz.udacityproject1.MovieNavigation;
|
||||||
|
import net.headlezz.udacityproject1.R;
|
||||||
|
import net.headlezz.udacityproject1.favorites.FavoriteProviderHelper;
|
||||||
import net.headlezz.udacityproject1.tmdbapi.MovieList;
|
import net.headlezz.udacityproject1.tmdbapi.MovieList;
|
||||||
import net.headlezz.udacityproject1.tmdbapi.TMDBApi;
|
import net.headlezz.udacityproject1.tmdbapi.TMDBApi;
|
||||||
|
|
||||||
@@ -42,7 +46,11 @@ public class MovieListFragment extends Fragment implements Callback<MovieList> {
|
|||||||
* The currently selected sorting order of the list
|
* The currently selected sorting order of the list
|
||||||
* @see TMDBApi
|
* @see TMDBApi
|
||||||
*/
|
*/
|
||||||
private int mSortingOrder = TMDBApi.SORT_ORDER_MOST_POPULAR;
|
private int mSortingOrder = SORT_ORDER_MOST_POPULAR;
|
||||||
|
|
||||||
|
public static final int SORT_ORDER_MOST_POPULAR = TMDBApi.SORT_ORDER_MOST_POPULAR;
|
||||||
|
public static final int SORT_ORDER_HIGHEST_RATED = TMDBApi.SORT_ORDER_HIGHEST_RATED;
|
||||||
|
public static final int SORT_ORDER_FAVORITES = 3;
|
||||||
|
|
||||||
private MovieList mMovieList;
|
private MovieList mMovieList;
|
||||||
|
|
||||||
@@ -120,11 +128,15 @@ public class MovieListFragment extends Fragment implements Callback<MovieList> {
|
|||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.action_sort_popularity:
|
case R.id.action_sort_popularity:
|
||||||
mSortingOrder = TMDBApi.SORT_ORDER_MOST_POPULAR;
|
mSortingOrder = SORT_ORDER_MOST_POPULAR;
|
||||||
loadMovieList();
|
loadMovieList();
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_sort_rating:
|
case R.id.action_sort_rating:
|
||||||
mSortingOrder = TMDBApi.SORT_ORDER_HIGHEST_RATED;
|
mSortingOrder = SORT_ORDER_HIGHEST_RATED;
|
||||||
|
loadMovieList();
|
||||||
|
return true;
|
||||||
|
case R.id.action_sort_favorites:
|
||||||
|
mSortingOrder = SORT_ORDER_FAVORITES;
|
||||||
loadMovieList();
|
loadMovieList();
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
@@ -138,9 +150,18 @@ public class MovieListFragment extends Fragment implements Callback<MovieList> {
|
|||||||
*/
|
*/
|
||||||
private void loadMovieList() {
|
private void loadMovieList() {
|
||||||
stopLoadingMovies(); // stop any running query before starting a new one
|
stopLoadingMovies(); // stop any running query before starting a new one
|
||||||
mProgressBar.setVisibility(View.VISIBLE);
|
if(mSortingOrder != SORT_ORDER_FAVORITES) {
|
||||||
mMovieListCall = TMDBApi.discoverMovies(mSortingOrder, getString(R.string.api_key));
|
mProgressBar.setVisibility(View.VISIBLE);
|
||||||
mMovieListCall.enqueue(this);
|
mMovieListCall = TMDBApi.discoverMovies(mSortingOrder, getString(R.string.api_key));
|
||||||
|
mMovieListCall.enqueue(this);
|
||||||
|
} else
|
||||||
|
loadMovieListFromFavorites();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadMovieListFromFavorites() {
|
||||||
|
// TODO async?
|
||||||
|
Cursor cursor = new FavoriteProviderHelper(getContext().getContentResolver()).getAllFavorites();
|
||||||
|
mMovieGridView.setAdapter(new CursorMovieListAdapter(cursor,(MovieNavigation) getActivity()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -190,7 +211,7 @@ public class MovieListFragment extends Fragment implements Callback<MovieList> {
|
|||||||
@Override
|
@Override
|
||||||
public void onSaveInstanceState(Bundle outState) {
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
outState.putInt("sort_order", mSortingOrder);
|
outState.putInt("sort_order", mSortingOrder);
|
||||||
if(mMovieList != null)
|
if(mMovieList != null && mSortingOrder != SORT_ORDER_FAVORITES)
|
||||||
outState.putParcelable("movielist", mMovieList);
|
outState.putParcelable("movielist", mMovieList);
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,13 @@
|
|||||||
package net.headlezz.udacityproject1.tmdbapi;
|
package net.headlezz.udacityproject1.tmdbapi;
|
||||||
|
|
||||||
|
import android.database.Cursor;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
import net.headlezz.udacityproject1.favorites.FavoriteColumns;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -55,6 +58,17 @@ public class Movie implements Parcelable {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Movie fromCurrentCursorPosition(Cursor cursor) {
|
||||||
|
Movie movie = new Movie();
|
||||||
|
movie.id = cursor.getLong(cursor.getColumnIndex(FavoriteColumns._ID));
|
||||||
|
movie.title = cursor.getString(cursor.getColumnIndex(FavoriteColumns.TITLE));
|
||||||
|
movie.posterPath = cursor.getString(cursor.getColumnIndex(FavoriteColumns.POSTERPATH));
|
||||||
|
movie.overview = cursor.getString(cursor.getColumnIndex(FavoriteColumns.OVERVIEW));
|
||||||
|
movie.releaseDate = new Date(cursor.getLong(cursor.getColumnIndex(FavoriteColumns.RELEASEDATE)));
|
||||||
|
movie.avRating = cursor.getDouble(cursor.getColumnIndex(FavoriteColumns.AVRATING));
|
||||||
|
return movie;
|
||||||
|
}
|
||||||
|
|
||||||
/**** Parcelable stuff *****/
|
/**** Parcelable stuff *****/
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
BIN
app/src/main/res/drawable-hdpi/ic_action_star_0.png
Normal file
|
After Width: | Height: | Size: 765 B |
BIN
app/src/main/res/drawable-hdpi/ic_action_star_10.png
Normal file
|
After Width: | Height: | Size: 539 B |
BIN
app/src/main/res/drawable-ldpi/ic_action_star_0.png
Normal file
|
After Width: | Height: | Size: 381 B |
BIN
app/src/main/res/drawable-ldpi/ic_action_star_10.png
Normal file
|
After Width: | Height: | Size: 301 B |
BIN
app/src/main/res/drawable-mdpi/ic_action_star_0.png
Normal file
|
After Width: | Height: | Size: 497 B |
BIN
app/src/main/res/drawable-mdpi/ic_action_star_10.png
Normal file
|
After Width: | Height: | Size: 385 B |
BIN
app/src/main/res/drawable-tvdpi/ic_action_star_0.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
app/src/main/res/drawable-tvdpi/ic_action_star_10.png
Normal file
|
After Width: | Height: | Size: 932 B |
BIN
app/src/main/res/drawable-xhdpi/ic_action_star_0.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
app/src/main/res/drawable-xhdpi/ic_action_star_10.png
Normal file
|
After Width: | Height: | Size: 737 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_action_star_0.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_action_star_10.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
app/src/main/res/drawable-xxxhdpi/ic_action_star_0.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
app/src/main/res/drawable-xxxhdpi/ic_action_star_10.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
@@ -2,4 +2,5 @@
|
|||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
<item android:icon="@drawable/ic_action_share" android:id="@+id/action_share" android:title="Share" app:showAsAction="ifRoom" />
|
<item android:icon="@drawable/ic_action_share" android:id="@+id/action_share" android:title="Share" app:showAsAction="ifRoom" />
|
||||||
|
<item android:id="@+id/action_favorite" android:title="Add/Remove Favorite" app:showAsAction="ifRoom" />
|
||||||
</menu>
|
</menu>
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
|
xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
|
||||||
<item android:id="@+id/action_sort_popularity" android:title="Sort by popularity" app:showAsAction="never" />
|
<item android:id="@+id/action_sort_popularity" android:title="Popular movies" app:showAsAction="never" />
|
||||||
<item android:id="@+id/action_sort_rating" android:title="Sort by av. rating" app:showAsAction="never" />
|
<item android:id="@+id/action_sort_rating" android:title="Highest av. rating" app:showAsAction="never" />
|
||||||
|
<item android:id="@+id/action_sort_favorites" android:title="Favorites" app:showAsAction="never" />
|
||||||
</menu>
|
</menu>
|
||||||
|
|||||||