ValarMorghulis ValarMorghulis - 4 months ago 24
Android Question

RecyclerView.Adapter onClick

I am having trouble implementing

view.OnClickListener
in my
RecyclerView.Adapter
. I am trying to implement multi-pane layout (landscape tablet layout version with
RecyclerView
and detail side by side). I have so far created this
Activity
:

public class MovieListActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_movie_list);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

MovieListFragment movieListFragment = new MovieListFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.recycler_view_fragment, movieListFragment);
transaction.addToBackStack(null);

transaction.commit();

}

}


which starts a
Fragment
:

public class MovieListFragment extends Fragment {

@BindView(R.id.recyclerView)
RecyclerView mRecyclerView;
private MoviesAdapter mAdapter;

public MovieListFragment() {
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAdapter = new MoviesAdapter(getContext());

}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_movie_list, container, false);
ButterKnife.bind(this,view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
mRecyclerView.setAdapter(mAdapter);
return view;
}

@Override
public void onStart() {
super.onStart();
getPopularMovies();
}

private void getPopularMovies() {
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("http://api.themoviedb.org")
.setLogLevel(RestAdapter.LogLevel.FULL)
.build();
MoviesApiService service = restAdapter.create(MoviesApiService.class);
service.getPopularMovies(new Callback<Movie.MovieResult>() {
@Override
public void success(Movie.MovieResult movieResult, Response response) {
mAdapter.setMovieList(movieResult.getResults());
}

@Override
public void failure(RetrofitError error) { error.printStackTrace(); }
});
}

@Override
public void onAttach(Context context) {
super.onAttach(context);

}

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

}


which calls the
RecyclerView.Adapter
:

public class MoviesAdapter extends RecyclerView.Adapter<MovieViewHolder> {

private List<Movie> mMovieList;
private LayoutInflater mInflater;
private Context mContext;

public MoviesAdapter(Context context) {
this.mContext = context;
this.mInflater = LayoutInflater.from(context); //
}

@Override
public MovieViewHolder onCreateViewHolder(ViewGroup parent, final int viewType) {
View view = mInflater.inflate(R.layout.movie_row_item, parent, false);
final MovieViewHolder viewHolder = new MovieViewHolder(view);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {

int position = viewHolder.getAdapterPosition();
Intent intent = new Intent(mContext, MovieDetailActivity.class);
intent.putExtra(MovieDetailActivity.MOVIE_EXTRA, mMovieList.get(position));
mContext.startActivity(intent);


}
});
return viewHolder;
}

@Override
public void onBindViewHolder(MovieViewHolder holder, int position) {
Movie movie = mMovieList.get(position);
Picasso.with(mContext)
.load(movie.getPoster())
.placeholder(R.color.colorAccent)
.into(holder.thumbnail);
holder.movieTitle.setText(movie.getTitle());
holder.rating.setText(movie.getRating());

}

@Override
public int getItemCount() {
return (mMovieList == null) ? 0 : mMovieList.size();
}

public void setMovieList(List<Movie> movieList) {
this.mMovieList = new ArrayList<>();
this.mMovieList.addAll(movieList);
notifyDataSetChanged();
}
}


Here in
onClick
I need to decide whether to start a new
Activity
(like in my code) or update content of detail
Fragment
(in my tablet landscape layout).
According to this link, you should decide based on fact if your DetailFragment is != null in activity like this:

public void onItemSelected(int position) {
DisplayFragment displayFrag = (DisplayFragment) getFragmentManager()
.findFragmentById(R.id.display_frag);
if (displayFrag == null) {
// DisplayFragment (Fragment B) is not in the layout (handset layout),
// so start DisplayActivity (Activity B)
// and pass it the info about the selected item
Intent intent = new Intent(this, DisplayActivity.class);
intent.putExtra("position", position);
startActivity(intent);
} else {
// DisplayFragment (Fragment B) is in the layout (tablet layout),
// so tell the fragment to update
displayFrag.updateContent(position);
}
}


But I'm not able to check this in Adapter. Any help would be highly appreciated!
Thank you.

Answer

Created the custom interface click action to get the control in fragment class

i hope it will works for you

public class MoviesAdapter extends RecyclerView.Adapter {

MoviesAdapterCallback moviesAdapterCallback;
private List<Movie> mMovieList;
private LayoutInflater mInflater;
private Context mContext;

public MoviesAdapter(Context context,MoviesAdapterCallback moviesAdapterCallback) {
    this.mContext = context;
    this.moviesAdapterCallback =moviesAdapterCallback;
    this.mInflater = LayoutInflater.from(context); //
}

@Override
public MovieViewHolder onCreateViewHolder(ViewGroup parent, final int viewType) {
    View view = mInflater.inflate(R.layout.movie_row_item, parent, false);
    final MovieViewHolder viewHolder = new MovieViewHolder(view);
    view.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

           /* int position = viewHolder.getAdapterPosition();
            Intent intent = new Intent(mContext, MovieDetailActivity.class);
            intent.putExtra(MovieDetailActivity.MOVIE_EXTRA, mMovieList.get(position));
            mContext.startActivity(intent);

*/ moviesAdapterCallback.MovieClicked(view);

        }
    });
    return viewHolder;
}

@Override
public void onBindViewHolder(MovieViewHolder holder, int position) {
    Movie movie = mMovieList.get(position);
    Picasso.with(mContext)
            .load(movie.getPoster())
            .placeholder(R.color.colorAccent)
            .into(holder.thumbnail);
    holder.movieTitle.setText(movie.getTitle());
    holder.rating.setText(movie.getRating());

}

@Override
public int getItemCount() {
    return (mMovieList == null) ? 0 : mMovieList.size();
}

public void setMovieList(List<Movie> movieList) {
    this.mMovieList = new ArrayList<>();
    this.mMovieList.addAll(movieList);
    notifyDataSetChanged();
}

public interface MoviesAdapterCallback {
    void MovieClicked(View view);
}

}

in Fragment Class

public class MovieListFragment extends Fragment {

@BindView(R.id.recyclerView)
RecyclerView mRecyclerView;
private MoviesAdapter mAdapter;

public MovieListFragment() {
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);


}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_movie_list, container, false);
    ButterKnife.bind(this,view);
    mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
    mAdapter = new MoviesAdapter(getContext(), new MoviesAdapter.MoviesAdapterCallback(){
        @Override
        public void MovieClicked(View view) {
            DisplayFragment displayFrag = (DisplayFragment) getFragmentManager()
                    .findFragmentById(R.id.display_frag);
            if (displayFrag == null) {
                // DisplayFragment (Fragment B) is not in the layout (handset layout),
                // so start DisplayActivity (Activity B)
                // and pass it the info about the selected item
                Intent intent = new Intent(this, DisplayActivity.class);
                intent.putExtra("position", position);
                startActivity(intent);
            } else {
                // DisplayFragment (Fragment B) is in the layout (tablet layout),
                // so tell the fragment to update
                displayFrag.updateContent(position);
            }
        }
    });
    mRecyclerView.setAdapter(mAdapter);
    return view;
}

@Override
public void onStart() {
    super.onStart();
    getPopularMovies();
}

private void getPopularMovies() {
    RestAdapter restAdapter = new RestAdapter.Builder()
            .setEndpoint("http://api.themoviedb.org")
            .setLogLevel(RestAdapter.LogLevel.FULL)
            .build();
    MoviesApiService service = restAdapter.create(MoviesApiService.class);
    service.getPopularMovies(new Callback<Movie.MovieResult>() {
        @Override
        public void success(Movie.MovieResult movieResult, Response response) {
            mAdapter.setMovieList(movieResult.getResults());
        }

        @Override
        public void failure(RetrofitError error) { error.printStackTrace(); }
    });
}

@Override
public void onAttach(Context context) {
    super.onAttach(context);

}

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

}