问题
I am developing a job estimation app which stores information in a room database and holds a reference to it via a RecyclerView which user can use to access the data and make changes if needed.
I am retrieving a reference to the information using Live Data via a view model with Observer method inside a Fragment. This information is stored in a database when the user completes a form and presses the save button.
Currently I have developed two standard adapters, with different data sets and separate layouts.
public class HallDetailAdapter extends RecyclerView.Adapter<HallDetailAdapter.myViewHolder> {
private List<HallDetails> mHallDetails;
public void setHallDetails(final List<HallDetails> hallDetails) {
this.mHallDetails = hallDetails;
notifyDataSetChanged();
}
@NonNull
@Override
public HallDetailAdapter.myViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.cardview_design,parent,false);
return new myViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull final HallDetailAdapter.myViewHolder holder, final int position) {
if(mHallDetails != null){
HallDetails details = mHallDetails.get(position);
holder.mTextView.setText(details.getName());
}else{
holder.mTextView.setText("No Data Entry");
}
}
@Override
public int getItemCount() {
if(mHallDetails != null)
return mHallDetails.size();
else return 0;
}
class myViewHolder extends RecyclerView.ViewHolder{
private TextView mTextView;
public myViewHolder(@NonNull final View itemView) {
super(itemView);
mTextView = itemView.findViewById(R.id.display_name);
}
}
}
public class RoomDetailsAdapter extends RecyclerView.Adapter<RoomDetailsAdapter.myViewHolder> {
private List<RoomDetails> mRoomDetails;
public void setRoomDetails(final List<RoomDetails> roomDetails) {
this.mRoomDetails = roomDetails;
notifyDataSetChanged();
}
@NonNull
@Override
public RoomDetailsAdapter.myViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.cardview_design2,parent,false);
return new myViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull final RoomDetailsAdapter.myViewHolder holder, final int position) {
if(mRoomDetails != null) {
RoomDetails details = mRoomDetails.get(position);
holder.mTextView.setText(details.getName());
}else{
holder.mTextView.setText("No data entry");
}
}
@Override
public int getItemCount() {
if(mRoomDetails != null){
return mRoomDetails.size();
}else return 0;
}
public class myViewHolder extends RecyclerView.ViewHolder{
private TextView mTextView;
public myViewHolder(@NonNull final View itemView) {
super(itemView);
mTextView = itemView.findViewById(R.id.display_roomDetails);
}
}
On change methods called inside Fragment:
dataViewModel.getName().observe(getActivity(), new Observer<List<HallDetails>>() {
@Override
public void onChanged(final List<HallDetails> hallDetails) {
if(hallDetails != null) {
hallDetailAdapter.setHallDetails(hallDetails);
}
}
});
dataViewModel.getGetName2().observe(getActivity(), new Observer<List<RoomDetails>>() {
@Override
public void onChanged(final List<RoomDetails> roomDetails) {
if(roomDetails != null) {
roomDetailsAdapter.setRoomDetails(roomDetails);
}
}
});
My question is, how do I integrate multiple layouts to the RecyclerView while also adhering to these functionalities:
- Add and remove items from recycler view
- Have a click listener for each displayed item
- Show data inside corresponding layout which it has been referenced to inside adaptor, updated via Live Data.
Thank you for your help!
回答1:
To Display Multiple Layout in Single RecyclerView, You have to use multiple viewholder in your recyclerview adapter class.
For Example One view is use to Display Your Data and another view is use to Display Admob/facebook Ad between the data Item.So your Adapter Class look like Below Code.
public class StatusImageAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private ArrayList<String> images;
private String path;
private Context context;
OnIteamClickListner listner;
private String status;
private static final int AD_VIEW_HOLDER = 0;
private static final int CONTENT_VIEW_HOLDER = 1;
public StatusImageAdapter(Context context, ArrayList<String> images, String path, OnIteamClickListner listner, String status) {
this.images = images;
this.path = path;
this.context = context;
this.listner = listner;
this.status = status;
}
public interface OnIteamClickListner {
void onIteamClick(View view, String action, int position, String path);
}
@Override
public int getItemViewType(int position) {
if (position % Const.ITEMS_PER_AD == 0 && position>1)
return AD_VIEW_HOLDER;
return CONTENT_VIEW_HOLDER;
}
@Override
public int getItemCount() {
return images.size();
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
switch (viewType) {
case AD_VIEW_HOLDER:
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.admob_banner_row_item, parent, false);
return new AdViewHolder(itemView);
case CONTENT_VIEW_HOLDER:
// fall through
default:
View itemLayoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.image_item, null);
return new ContentViewHolder(itemLayoutView);
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, final int position) {
int viewType = getItemViewType(position);
switch (viewType) {
case AD_VIEW_HOLDER:
AdViewHolder adViewHolder= (AdViewHolder) holder;
adViewHolder.adView.setVisibility(View.GONE);
CommonMethods.loadAd(context,adViewHolder.adView);
break;
case CONTENT_VIEW_HOLDER:
ContentViewHolder contentViewHolder = (ContentViewHolder) holder;
Bitmap bitmap = BitmapFactory.decodeFile( images.get(position));
contentViewHolder.imageView.setImageBitmap(bitmap);
if (status.equals(Const.ONLINE)) {
contentViewHolder.img_download.setBackgroundResource(R.drawable.ic_download_black);
}
if (status.equals(Const.OFLINE)) {
contentViewHolder.img_download.setBackgroundResource(R.drawable.ic_delete);
}
contentViewHolder.imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
listner.onIteamClick(view, "View", position, path);
}
});
contentViewHolder.img_view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
listner.onIteamClick(view, "QuickView", position, path);
}
});
contentViewHolder.img_download.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (status.equals(Const.ONLINE)) {
listner.onIteamClick(view, "Download", position, path);
}
if (status.equals(Const.OFLINE)) {
listner.onIteamClick(view, "Delete", position, path);
}
}
});
contentViewHolder.img_share.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
listner.onIteamClick(view, "Share", position, path);
}
});
}
}
private class AdViewHolder extends RecyclerView.ViewHolder {
AdView adView;
public AdViewHolder(View itemView) {
super(itemView);
adView=itemView.findViewById(R.id.adView);
}
}
private class ContentViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
ImageView img_share, img_download, img_view;
public ContentViewHolder(View itemLayoutView) {
super(itemLayoutView);
imageView = itemView.findViewById(R.id.statusItem_imageView);
img_share = itemView.findViewById(R.id.img_share);
img_download = itemView.findViewById(R.id.img_download);
img_view = itemView.findViewById(R.id.img_view);
}
}
}
Call this adapter from your activity class file.
StatusImageAdapter statusImageAdapter = new StatusImageAdapter(context, imageFiles, hiddenpath.getAbsolutePath(), this, Const.ONLINE);
来源:https://stackoverflow.com/questions/58717944/recyclerview-with-multiple-layouts-insert-delete-function-and-click-listener