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!