I have a RecyclerView
inside a RecyclerView
. When I init my view everything is ok and fine. But when I update my RecyclerView (parent) my view is automatic scroll to first child RecyclerView I do not see an item in parent RecyclerView (is only a TextView
). I do not know why it happend. When I create a view for first time all is ok.
Layout of main view
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/top_panel"
android:layout_marginTop="20sp" />
</RelativeLayout>
</RelativeLayout>
This is how I put and update a main view:
private fun initRecyclerView(
context: Context,
interaction: TestAdapter.Interaction
) {
rvList.run {
testAdapter= TestAdapter(
context
)
adapter = testAdapter
isNestedScrollingEnabled = true
setHasFixedSize(true)
layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
}
}
And this is how I put on item :
itemView.rvList.apply {
val testAdapter= TestAdapter(
context
)
adapter = testAdapter
layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
isNestedScrollingEnabled = true
setHasFixedSize(true)
}
The best approach in this case is to use RecyclerView with multiple view type (multiple view holder).
You can create multiple classes inheriting same class (or implementing same interface. For this example I will create 2 of them ("name" and "photo"):
class NameViewHolder extends RecyclerView.ViewHolder {
private TextView name;
NameViewHolder(@NonNull View itemView) {
super(itemView);
name = itemView.findViewById(R.id.name_text_view);
}
}
and
class PhotoViewHolder extends RecyclerView.ViewHolder {
private ImageView image;
PhotoViewHolder(@NonNull View itemView) {
super(itemView);
image = itemView.findViewById(R.id.image_avatar);
}
}
You have to prepare numbers (positions) to those items, e.g.:
private static int TYPE_NAME = 1;
private static int TYPE_PHOTO = 2;
And in your adapter, base on some logic return which type do you need. Here you are returning "for which position from list, which view holder"
@Override
public int getItemViewType(int position) {
// Add here your logic!
if (people.get(position).hasPhoto()) {
return TYPE_PHOTO;
} else {
return TYPE_NAME;
}
}
Next inside onCreateViewHolder()
(in your adapter) you have to inflate proper layout:
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
View view;
if (viewType == TYPE_PHOTO) {
view = LayoutInflater.from(context).inflate(R.layout.item_photo, viewGroup, false);
return new PhotoViewHolder(view);
} else { // for email layout
view = LayoutInflater.from(context).inflate(R.layout.item_name, viewGroup, false);
return new NameViewHolder(view);
}
}
And fill them properly (in onBindViewHolder()
):
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
Person person = people.get(position);
if (getItemViewType(position) == TYPE_PHOTO) {
((PhotoViewHolder) viewHolder).bind(person);
} else {
((NameViewHolder) viewHolder).bind(person);
}
}