Java.lang.ClassCastException : android. widget. RelativeLayout$LayoutParams cannot be converted to android.support.v7.widget.RecyclerView$LayoutParams

Java.lang.ClassCastException : android. widget. RelativeLayout$LayoutParams cannot be converted to android.support.v7.widget.RecyclerView$LayoutParams … here is a solution to the problem.

Java.lang.ClassCastException : android. widget. RelativeLayout$LayoutParams cannot be converted to android.support.v7.widget.RecyclerView$LayoutParams

I used android RecycleView to replace ListLiew.

What I want

to do is enable onClick on one of my list items ImageView (imagine this list item has an image and a text, and I want to add an onClick listener to the image instead of the list item itself).

I create a RecycleView adapter using the following layout xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:paddingLeft="16dp"
    android:paddingRight="16dp"
    android:layout_height="48dp"
    android:background="@drawable/border_bottom">

<ImageView
    android:id="@+id/icon"        
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    android:src="@drawable/ic_action_play_dark"
    android:layout_centerVertical="true" />

<TextView
    android:id="@+id/title"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_marginLeft="56dp"
    android:text="Search"
    android:textColor="#333"
    android:textStyle="bold"
    android:layout_centerVertical="true"  
    android:gravity="center_vertical"/>

</RelativeLayout>

and my onCreateViewHolder

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) 
{
    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.drawer_list_item, parent, false);

ImageView icon = (ImageView)v.findViewById(R.id.icon);
    icon.setOnClickListener(listener);

PropertyViewHolder vh = new PropertyViewHolder(v);

return vh;
}

I want to bind the listener to the ImageView icon (a child of the View), not the View itself, however, it always throws an exception:

12-23 17:37:36.033: E/AndroidRuntime(5806): java.lang.ClassCastException:
android.widget.RelativeLayout$LayoutParams cannot be cast to
android.support.v7.widget.RecyclerView$LayoutParams
at android.support.v7.widget.RecyclerView.getChildPosition(RecyclerView.java:2589)
.....

When I click on the image, my onclickListner is here

@Override
public void onClick(View v) {

int itemPosition = getRecycleView().getChildPosition(v); 

Toast.makeText(getActivity(), "click ", Toast.LENGTH_SHORT).show();
}

Any ideas?

Solution

From the comments, you probably already know that it doesn’t work because your ImageView is not a View that resides in RecyclerView.

In this case, I recommend that you implement a listener in a ViewHolder and then pass a ViewHolder reference instead of View when the icon is clicked

I’ll provide an example below


Example RecyclerView

Notice how I allocated listeners in the constructors of MyRecyclerViewAdapter and MyViewHolder, which come from Activity or fragment . The activity or fragment will implement the MyViewHolderListener interface, which will provide the onIconClicked method.

Now notice that I provided the MyViewHolder.this reference in the onIconClicked method. Using the ViewHolder object, you can get the adapter location and then finally the actual Data object. I also provide an implementation of the onIconClicked method.

public class MyRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

private List<Object> mData;

private MyViewHolder.MyViewHolderListener mViewHolderListener;

public MyRecyclerViewAdapter(MyViewHolder.MyViewHolderListener listener) {
    mData = new ArrayList<>();
    mViewHolderListener = listener;
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
    return new MyViewHolder(view, mViewHolderListener);
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
    ((MyViewHolder) viewHolder).update(mData.get(position));
}

public void setData(@NonNull List<Object> newData) {
    mData.addAll(newData);
    notifyDataSetChanged();
}

public Object getItemAtPosition(int position) {
    try {
        return mData.get(position);
    } catch (IndexOutOfBoundsException e) {
        e.printStackTrace();
        return null;
    }
}

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

public void reset() {
    mData.clear();
    notifyDataSetChanged();
}

public static final class MyViewHolder extends RecyclerView.ViewHolder {

ImageView icon;

public MyViewHolder(View itemView, final MyViewHolderListener listener) {
        super(itemView);
        icon = (ImageView) itemView.findViewById(R.id.icon);
        icon.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                listener.onIconClicked(MyViewHolder.this);
            }
        });
    }

public void update(Object myObject) {
         update icon
    }

public interface MyViewHolderListener {
        void onIconClicked(MyViewHolder clickedViewHolder);
    }
}


Implement OnIconClicked in an activity or fragment

@Override
public void onIconClicked(MyRecyclerViewAdapter.MyViewHolder clickedViewHolder) {
    int adapterPosition = clickedViewHolder.getAdapterPosition();
    if(adapterPosition != RecyclerView.NO_POSITION) {
        Object selectedItem = mAdapter.getItemAtPosition(adapterPosition);
    }
}

I hope this solves your problem!

Related Problems and Solutions