Pass data from RecyclerView to a Fragment - android

I have referred few links regarding this topic but I still couldn't understand how to pass data from a RecyclerView to a Fragment[opening a Fragment on Cardview click]. Following is my RecyclerView class:
public class PhotoAdapter extends RecyclerView.Adapter<PhotoAdapter.PhotosHolder>
{
static class PhotosHolder extends RecyclerView.ViewHolder
{
CardView cv;
ImageView photo_img;
PhotosHolder(final View itemView)
{
super(itemView);
cv = (CardView) itemView.findViewById(R.id.cv_photo);
photo_img = (ImageView) itemView.findViewById(R.id.thum_photo);
}
}
private List<PhotoInitialise> photo;
private Activity mContext;
public PhotoAdapter(List<PhotoInitialise> photos, Context mContext)
{
this.photo=photos;
this.mContext= (Activity) mContext;
}
#Override
public PhotosHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.phototab_layout,parent,false);
return new PhotosHolder(layoutView);
}
#Override
public void onBindViewHolder(PhotosHolder holder, final int position)
{
holder.photo_count.setText(photo.get(position).gettotalImages());
holder.cv.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view)
{
// want to pass the value to a Fragment here and invoke the Fragment
}
});
}
#Override
public int getItemCount()
{
return photo.size();
}
}
This is the XML Layout of the Fragment that should be displayed:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/photo_detail_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/photodetail_description"
android:textSize="20sp"
android:paddingLeft="5dp"
android:layout_marginTop="5dp"
android:paddingRight="5dp">
</RelativeLayout>
I already have an idea of how to pass the value to fragment but I never could able to invoke the layout. Now what should I write in my onClick() to initiate the Fragment Layout ?

Implement interface to handle the click in the specified Fragment.
Sample code structure will be like below. You can customize and use it according to your need:
public InterfaceListItemClickListener{
void listItemClickAction(<parameters to pass>);
}
In your fragment class implement this interface:
public class SampleFragment extends BaseFrgment implements InterfaceListItemClickListener{
#Override
public void listItemClickAction(<parameters to pass>) {
//override the interface function
//handle your click action here
}
//pass the instance of your interface to your adapter like below line
YourAdapter yourAdapter = new YourAdapter(otherParameters, this);
}
In constructor of your Adapter access the interface:
public YourAdapter(otherParameters, InterfaceListItemClickListener clickListenerInferface ){
//other assignations
this.clickListenerInferface = clickListenerInferface;
}
and then onClick callback you can call your onclick function:
clickListenerInferface.listItemClickAction(<parameter to pass>);

Related

Fragment in a Adapter of RecyclerView JAVA

I have a fragment Users which has 3 other fragments in it (tabs). For one tab ( called Friends2Fragment ) I made a recycler View and made an adapter for it. In each item of RecyclerView I have a button "Add friend" and I want to call it from Friends2Fragment, not to call it from the adapter because I can't use Firestore Database properly.
RecyclerViewInterface:
public interface RecyclerViewInterface {
void onItemClick(int position, String button_pressed);
}
Friends2Fragment.java :
public void onStart(){
super.onStart();
recyclerView = (RecyclerView) v.findViewById(R.id.recycler);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
friendslist = new ArrayList<>();
myAdapter = new MyAdapter(friendslist,v.getContext());
recyclerView.setAdapter(myAdapter);
------ Firestore operations ------
}
#Override
public void onItemClick(int position, String button_pressed) {
switch ( button_pressed ){
case "ADD_FRIEND":
Log.d(TAG, "item clicked: " + friendslist.get(position).username);
}
}
MyAdapter.java :
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.myViewHolder> {
Context context;
public ArrayList<User> userArrayList;
public MyAdapter(ArrayList<User> userArrayList, Context context) {
this.userArrayList = userArrayList;
this.context = context;
}
public Context getContext() {
return context;
}
public ArrayList<User> getUserArrayList() {
return userArrayList;
}
#NonNull
#Override
public MyAdapter.myViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
MyAdapter.myViewHolder myViewHolder = new MyAdapter.myViewHolder(v);
myViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
((Friends2Fragment)context).onItemClick(myViewHolder.getAdapterPosition(),"ADD_FRIEND");
}
});
return myViewHolder;
}
#Override
public void onBindViewHolder(#NonNull MyAdapter.myViewHolder holder, int position) {
User user = userArrayList.get(position);
holder.usernamerecycle.setText(user.username);
}
#Override
public int getItemCount() {
return userArrayList.size();
}
public void filterList(List<User> filteredList){
userArrayList = (ArrayList<User>) filteredList;
notifyDataSetChanged();
}
public class myViewHolder extends RecyclerView.ViewHolder{
TextView usernamerecycle;
Button addbutton;
View rootview;
public myViewHolder(#NonNull View itemView) {
super(itemView);
rootview = itemView;
usernamerecycle = itemView.findViewById(R.id.usernamerecycler);
addbutton = itemView.findViewById(R.id.addfriendbutton);
}
}
}
The problem is at this line : ((Friends2Fragment)context).onItemClick(myViewHolder.getAdapterPosition(),"ADD_FRIEND"); in onCreateViewHolder method in MyAdapter.
I have this error : Inconvertible types; cannot cast 'android.content.Context' to 'com.example.birthday.Fragments.Friends2Fragment'
Please help me ..
A Fragment isn't a Context (that's not one of its supertypes) so that cast is impossible, that's why you're getting the error.
I think you should organise it like this: your Adapter holds a bunch of User objects, right? It displays those, and you have a click listener on each ViewHolder that knows which index in the User list it's currently displaying, and it wants to inform some listener when it's clicked. That index is an internal detail really, it would make more sense to look up the actual User, and provide that to the listener.
The simplest way is to just provide your fragment as a listener. First store it in your adapter:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.myViewHolder> {
// store a reference to your fragment
private Friends2Fragment listener;
// add a function to provide that fragment
public void setListener(Friends2Fragment: listener) {
this.listener = listener
}
...
public MyAdapter.myViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
...
myViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (listener != null) {
// look up the actual user
User user = userArrayList.get(myViewHolder.getAdapterPosition());
// call a function on your fragment
listener.onItemClick(user, "ADD_FRIEND");
}
}
});
}
Then add the callback function your adapter uses, and also set your fragment on the adapter as a listener:
// Friends2Fragment
// You should REALLY be doing this in onViewCreated or something, so this setup happens once.
// You're losing all your state by creating a new adapter whenever the user returns to the app
public void onStart(){
...
myAdapter = new MyAdapter(friendslist,v.getContext());
// set the fragment as the listener
myAdapter.setListener(this);
recyclerView.setAdapter(myAdapter);
}
// now add the function the adapter calls
private void onItemClick(User user, String someString) {
// handle the clicked user
}
A better way is to create an interface with all the events that need to be handled, and make your Fragment implement those. It breaks the hard association with the Fragment since you could pass any object that implements those functions, and it's also clearer because the interface kinda documents all the data the adapter produces, and that a listener needs to be able to handle. Something like this:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.myViewHolder> {
// the listener is now something that implements the Callbacks interface
private Callbacks listener;
...
// nesting it inside MyAdapter makes the path MyAdapter.Callbacks, which makes it clear
// exactly what it is and what it relates to, and kinda gives the Adapter "ownership"
interface Callbacks {
void addFriend(User user)
}
And then you just make the Fragment implement that interface
public class Friends2Fragment() extends Fragment implements MyAdapter.Callbacks {
...
// implement all the callbacks you need to handle
override public void addFriend(User user) {
// do the thing
}
// set it in the same way, since this Fragment implements MyAdapter.Callbacks
myAdapter.setListener(this);
Which is a bit neater and cleaner, I think - but slightly more work. Also if you notice, I renamed the callback function from the generic handleItemClick to the more specific addFriend - so instead of having to pass a String saying what kind of click it is, you just have a function for each event you want to handle, and you can name them appropriately

Why is my recyclerView not displaying any data?

I have implemented a RecyclerView and customer Adapter many times, but for some reason I cannot get this one to display any data. I am feeding in data from JSON using retrofit and calling notifyDataSetChanged() once this has been loaded, yet it still remains blank. I have stripped this back to just one text view to try and simplify but still not getting anything. Can anyone see where I am going wrong here?
When I debug, I am getting the List to contain data so I am definitely parsing the data correctly, I just cant get it display in the recycler view. I have even checked the list.size() in the loadTrailerList method and it has data.
My Activity onCreate method:
trailerAdapter = new TrailerAdapter(this);
trailerRecyclerView = findViewById(R.id.trailer_recycler_view);
trailerRecyclerView.setLayoutManager(new LinearLayoutManager(this));
trailerRecyclerView.setAdapter(trailerAdapter);
Retrofit onResponse method:
if (response.body() != null) {
trailers = response.body().getTrailers();
}
trailerAdapter.loadTrailerList(response.body().getTrailers());
My custom adapter:
public class TrailerAdapter extends RecyclerView.Adapter<TrailerAdapter.TrailerViewHolder> {
private final List<Trailer> trailerList = new ArrayList<>();
private final TrailerClickListener listener;
public TrailerAdapter(TrailerClickListener listener) {
this.listener = listener;
}
#NonNull
#Override
public TrailerViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.trailer_list_item, viewGroup, false);
return new TrailerViewHolder(itemView, this);
}
#Override
public void onBindViewHolder(#NonNull TrailerViewHolder trailerViewHolder, int i) {
trailerViewHolder.trailerTitle.setText(trailerList.get(i).getName());
}
#Override
public int getItemCount() {
return trailerList.size();
}
public void loadTrailerList(List<Trailer> trailers) {
this.trailerList.clear();
if (trailers != null) {
trailers.addAll(trailers);
}
notifyDataSetChanged();
}
class TrailerViewHolder extends RecyclerView.ViewHolder {
final TrailerAdapter trailerAdapter;
private final TextView trailerTitle;
private TrailerViewHolder(#NonNull View itemView, TrailerAdapter trailerAdapter) {
super(itemView);
this.trailerAdapter = trailerAdapter;
trailerTitle = itemView.findViewById(R.id.text_view_trailer_title);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
listener.onTrailerClicked(trailerList.get(getAdapterPosition()));
}
});
}
}
}
My List Item XML
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="#+id/text_view_trailer_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Play Trailer" />
</LinearLayout>
the recycler view in my activity XML:
<android.support.v7.widget.RecyclerView
android:id="#+id/trailer_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorPrimary"
app:layout_constraintTop_toBottomOf="#+id/trailer_divider">
</android.support.v7.widget.RecyclerView>
I am grateful for anyone that can point me in the right direction
It is because you are sending a list to adapter but, you are not initializing your list which is used in the adapter.
try this.
public void loadTrailerList(List<Trailer> trailers) {
this.trailerList.clear();
if (trailers != null) {
trailerList = trailers;
}
notifyDataSetChanged();
}
Doh! I just realised what I was doing wrong:
In my loadTrailerList() method in my adapter, I was calling:
trailers.addAll(trailers);
instead of:
trailerList.addAll(trailers);
to load the list of items into the actual ArrayList! whoops!

Implementing Click In CardView in RecycleView

So I am trying to make my cards clickable and as they are clicked it opens a new activity (not implemented in the code below though), here is my code:
For Interface
import android.view.View;
public interface ClickListener {
public void itemClicked(View view , int position);
}
For Adapter:
public class RVAdapter extends RecyclerView.Adapter<RVAdapter.SensorViewHolder> {
private ClickListener clicklistener = null;
List<SensorData> sensors;
RVAdapter(List<SensorData> sensors) {
this.sensors = sensors;
}
public class SensorViewHolder extends RecyclerView.ViewHolder {
CardView cv;
TextView sensorName;
TextView sensorDesc;
ImageView sensorPhoto;
private LinearLayout main;
SensorViewHolder(final View itemView) {
super(itemView);
cv = (CardView) itemView.findViewById(R.id.cv);
sensorName = (TextView) itemView.findViewById(R.id.sensor_name);
sensorDesc = (TextView) itemView.findViewById(R.id.sensor_desc);
sensorPhoto = (ImageView) itemView.findViewById(R.id.sensor_photo);
main = (LinearLayout) itemView.findViewById(R.id.main);
main.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(itemView.getContext(), "Position:" + Integer.toString(getPosition()), Toast.LENGTH_SHORT).show();
if(clicklistener != null){
clicklistener.itemClicked(v, getAdapterPosition());
}
}
});
}
}
public void setClickListener(ClickListener clickListener){
this.clicklistener = clickListener;
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
#Override
public SensorViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false);
SensorViewHolder pvh = new SensorViewHolder(v);
return pvh;
}
#Override
public void onBindViewHolder(SensorViewHolder SensorViewHolder, int i) {
SensorViewHolder.sensorName.setText(sensors.get(i).name);
SensorViewHolder.sensorDesc.setText(sensors.get(i).descriptor);
SensorViewHolder.sensorPhoto.setImageResource(sensors.get(i).iconID);
}
#Override
public int getItemCount() {
return sensors.size();
}
}
and here is the code for MainActivity:
public class MainActivity extends AppCompatActivity {
private List<SensorData> sensorData;
private RecyclerView rv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Find the recycler view for the <code>
rv = (RecyclerView) findViewById(R.id.rv);
//Initialising a linear layout manager
final LinearLayoutManager llm = new LinearLayoutManager(this);
rv.setLayoutManager(llm);
rv.setHasFixedSize(true);
initializeData();
initializeAdapter();
rv.setClickListener(this);
}
private void initializeData() {
sensorData = new ArrayList<>();
sensorData.add(new SensorData("Accelerometer", "Measures the acceleration of a moving or vibrating body.", R.mipmap.ic_accl));
sensorData.add(new SensorData("GPS Sensor", "Provides real-time user location and time information.", R.mipmap.ic_gps));
sensorData.add(new SensorData("Proximity Sensor", "Provides ambient light and proximity sensing.", R.mipmap.ic_als));
}
private void initializeAdapter() {
RVAdapter adapter = new RVAdapter(sensorData);
rv.setAdapter(adapter);
}
}
And yet it seems I cannot access setClickListener. I must mention I am quite a beginner in this.
Where have I mistaken? Is this the correct way to implement clicks on a card or I am missing something?
Also here is the MainActivity XML if needed.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
android:id="#+id/main">
<android.support.v7.widget.RecyclerView
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="#+id/rv">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
and items.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/cv"
app:cardUseCompatPadding="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/sensor_photo"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginRight="16dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/sensor_name"
android:layout_toRightOf="#+id/sensor_photo"
android:layout_alignParentTop="true"
android:textSize="30sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/sensor_desc"
android:layout_toRightOf="#+id/sensor_photo"
android:layout_below="#+id/sensor_name" />
</RelativeLayout>
</android.support.v7.widget.CardView>
EDIT: Just to avoid confusion, **I want the use to be able to click the cards and go to a new activity. ** How can I implement that in the simplest possible way? I am really confused on how to do it in the RecyclerView.
Thanks a lot and regards.
Since there is a difference between the old ListView and the new RecyclerView component, I have a reusable piece of code that I use to handle click events (both regular clicks and LongClicks):
public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
#SuppressWarnings("CanBeFinal")
private GestureDetector mGestureDetector;
#SuppressWarnings("CanBeFinal")
private OnItemClickListener mListener;
public interface OnItemClickListener {
void onItemClick(View view, int position);
void onItemLongClick(View view, int position);
}
public RecyclerItemClickListener(Context context, final RecyclerView recyclerView, OnItemClickListener listener)
{
mListener = listener;
mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener()
{
#Override
public boolean onSingleTapUp(MotionEvent e)
{
return true;
}
#Override
public void onLongPress(MotionEvent e)
{
View childView = recyclerView.findChildViewUnder(e.getX(), e.getY());
if(childView != null && mListener != null)
{
mListener.onItemLongClick(childView, recyclerView.getChildAdapterPosition(childView));
}
}
});
}
#Override
public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e)
{
View childView = view.findChildViewUnder(e.getX(), e.getY());
if(childView != null && mListener != null && mGestureDetector.onTouchEvent(e))
{
mListener.onItemClick(childView, view.getChildAdapterPosition(childView));
}
return false;
}
#Override
public void onTouchEvent(RecyclerView view, MotionEvent motionEvent){}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
Then simply do this in your activity or fragment where you want to handle click events:
mRecyclerView.addOnItemTouchListener(new RecyclerItemClickListener(this, mRecyclerView, new RecyclerItemClickListener
.OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
//start new activity here
}
#Override
public void onItemLongClick(View view, int position) {
}
}));
That should be the easiest way to do it!
I hope this helps you! Good luck and happy coding!
Basically you need to set the listener in the Viewholder
public class SensorViewHolder extends RecyclerView.ViewHolder {
CardView cv;
TextView sensorName;
TextView sensorDesc;
ImageView sensorPhoto;
private LinearLayout main;
SensorViewHolder(final View itemView) {
super(itemView);
cv = (CardView) itemView.findViewById(R.id.cv);
//Add the following line below
cv.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//The intent firing goes here
}
});
sensorName = (TextView) itemView.findViewById(R.id.sensor_name);
sensorDesc = (TextView) itemView.findViewById(R.id.sensor_desc);
sensorPhoto = (ImageView) itemView.findViewById(R.id.sensor_photo);
main = (LinearLayout) itemView.findViewById(R.id.main);
main.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(itemView.getContext(), "Position:" + Integer.toString(getPosition()), Toast.LENGTH_SHORT).show();
if(clicklistener != null){
clicklistener.itemClicked(v, getAdapterPosition());
}
}
});
}
}
Hope it helps.
To fix the compiler error, the correct way to set a OnClickListener is with
rv.setOnClickListener()
Note that the error is because you are missing the word On. Generally, you should use autocomplete in Android Studio to help avoid these types of issues. If autocomplete doesn't pop up automatically, you can push Ctrl-Space to get it.
As a side note, you can build your project by clicking Build -> Make Project in the main menu. This will give a window with the error messages where you can copy and paste more easily than the usual error balloons.
first of all set tag for your card in onBindViewHolder:
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.cv.setTag(position);
}
then add on click listener for your card in your view holder in adapter:
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public CardLayout cv;
public ViewHolder(View itemView) {
super(itemView);
cv = (CardView) itemView.findViewById(Rid.cv);
cv.setOnClickListener(this);
}
#Override
public void onClick(View v) {
//for find item that hold in list
int postition = (Integer) v.getTag();
...
}
In your findViewById you are casting the view to a RecyclerView and therefore you are referring the standard RecyclerView implementation of the Android framework. So this would never work.
The next thing is you are trying to set a listener to the RecyclerView but define the setListener method inside your adapter.
So what you should do is to either get a reference to your adapter via:
((RvAdapter) rv.getAdapter()).setClickListener();
after setting it or even better set the listener before you call
rv.setAdapter()
via
RvAdapter adapter = new RvAdapter();
adapter.setClickListener(listener)

RecyclerView CardView onItemClick

Got stuck on this problem for few days hope to find the solution.
I am unable to pass the data written on the card (Card View) to the next activity.
For clicking card, I am implementing its onClickListner in its recyclerView Adapter.
I want to pass the position of the card clicked but since card View does not support onItemClickListner I am facing the problem.
RecyclerViewAdapter class
public class RVAdapter extends recyclerView.Adapter<RVAdapter.PersonViewHolder> implements View.OnClickListener, View.OnLongClickListener {
int position;
#Override
public void onBindViewHolder(PersonViewHolder holder, int i) {
setEventsForViews(holder, i);
}
private void setEventsForViews(PersonViewHolder holder, int i) {
position = i;
holder.cv.setOnClickListener(this);
}
#Override
public void onClick(View v) {
Navigator.toAddFriends(context, placeList.get(getPosition()).getPlaceId());
}
public static class PersonViewHolder extends RecyclerView.ViewHolder {
CardView cv;
PersonViewHolder(View itemView) {
super(itemView);
cv = (CardView) itemView.findViewById(R.id.cv);
}
}
I tried to set up a variable position and tried to pass its value but since onBindViewHolder is called intially for all items in the view and I end up in setting the value of position as last one. I know this is the wrong approach but as I am new to this card View thing please suggest me any good and clean way to do this.
Thanks in advance.
Create a new interface, like:
public interface RecyclerViewClickListener {
public void recyclerViewListClicked(View v, int position);
}
On your Fragment/Activity, implement the new interface:
public class MyFragment extends BaseFragment implements RecyclerViewClickListener { }
Now, you will be forced to implement the interface method recyclerViewListClicked(View v, int position) on your Fragment/Activity.
Do that so you can do whatever you want when one item is clicked. Do it like so:
#Override
public void recyclerViewListClicked(View v, int position) {
myList.get(position);
}
Now lets go to your Adapter.
On your adapter constructor, add a new listener parameter. It's type is the interface we have just created (don't forget to create a private static listener and set it on your constructor):
private static RecyclerViewClickListener mListener;
public myListAdapter(List<Thing> things, final Context context, RecyclerViewClickListener itemClickListener) {
mThings = things;
mContext = context;
mListener = itemClickListener;
}
Inside your adapter, on your ViewHolder, implement View.OnClickListener like:
public static class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
You will now be forced do #Override the onClickMethod inside your ViewHolder. Do it:
#Override
public void onClick(View v) { }
On your ViewHolder constructor, set the onClickListener of your view. Like:
public MyViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);
myCardViewLayout.setOnClickListener(this);
}
Now implement the behaviour to your ViewHolder onClickMethod. In this case, I call the recyclerViewListClicked method of the static listener we declared in our adapter. This method is the one we have #Overriden in our fragment/activity, so it requires the position parameter.
Get the position by calling getLayoutPosition() inside your view holder. It will look like this:
#Override
public void onClick(View v) {
mListener.recyclerViewListClicked(v, getLayoutPosition());
}
Finally, get back to your fragment/activity, and pass the listener to the adapter constructor with this (since now we implement the interface RecyclerViewClickListener it can just pass itself as a listener to the adapter):
mRecyclerView.setAdapter(new MyListAdapter(this.mList, this.getActivity(), this))
Now, when you click on a myCardViewLayout on your list items it's going to call the recyclerViewListClicked(View v, int position) of your Fragment/Activity and you will be able to work with the position parameter as you'd like.
You can do this to any layout you want to get a click event from inside your list. Just replace myCardViewLayout.setOnClickListener(this) inside your ViewHolder constructor with myDesiredToHaveOnClickListenerLayout.setOnClickListener(this).
Hope this helps.
#EDIT:
Some tips:
Remove implements View.OnClickListener, View.OnLongClickListener from your adapter.
And looks like you don't need to call setEventsForViews(holder, i) on your onBindViewHolder anymore. Confirm?
#UPDATE
This is how your ViewHolder will look like:
public static class PersonViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
CardView cv;
PersonViewHolder(View itemView) {
super(itemView);
cv = (CardView) itemView.findViewById(R.id.cv);
cv.setOnClickListener(this);
}
#Override
public void onClick(View v) {
mListener.recyclerViewListClicked(v, getLayoutPosition());
}
}

RecyclerView onLongClickListener refuse to trigger

I want to implement a long press of a CardView inside a RecyclerView
The layout:
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:scrollbars="vertical"
android:longClickable="true"
android:hapticFeedbackEnabled="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
I tried this:
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(Utils.context));
mRecyclerView.setOnLongClickListener(new AdapterView.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
Toast.makeText(Utils.context,"dsfd",Toast.LENGTH_LONG).show();
return true;
}
});
And I also tried to implement this event in the RecyclerView.ViewHolder class but nothing works. I have the long press effect but the event itself is not triggered. There is no onItemLongClickListener. I also tried this: RecyclerView onClick .
What am I missing?
You can create Interface where you should implement your onLongClicked(int position) method. And use it.
Follow this steps to create your onLongClickListener:
Create your Interface:
public interface IRecyclerViewClickListener {
void onLongClicked(int position);
}
Create listener object in your activity/fragment and pass this listener object to your adapter in the create adapter method. Example:
// ... some code ...
adapter = new MoviesListAdapter(getActivity(), list, listener);
rvDialogs.setAdapter(adapter);
// ... code ...
In your adapter in your owned ViewHolder constructor set long listener on itemView:
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView Title;
// ...
public MessageViewHolder(View itemView) {
super(itemView);
Title = (TextView) itemView.findViewById(R.id.tvDialogTitle);
// ...
itemView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
listener.onLongClicked(getAdapterPosition());
return false;
}
});
}
}
After in your activity/fragment setup your IListener:
listener = new IRecyclerViewClickListener() {
#Override
public void onLongClicked(int position) {
Toast.makeText(getActivity(), String.valueOf(position), Toast.LENGTH_SHORT).show();
}
};
Hope it help you! Good luck and sorry for my bad english ;)

Categories

Resources