Ashish Yadav
Ashish Yadav

Reputation: 543

How to create heterogeneous layouts inside RecyclerView?

I want users to select images, pdf, any other documents in any order and put them in the recyclerView. I have different layouts for each of them.

So far I am getting the Uri and the filename from the selected image or pdf and putting them into list.

@Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);

            if(requestCode == CHOOSE_IMAGE && resultCode == Activity.RESULT_OK){
    if (data.getData()!=null){
                    uriDocument = data.getData();
    }
    String filename = getFilename(uriDocument);
                    fileNameList.add(filename);
                    mAdapter.notifyDataSetChanged();
    }else if (requestCode == PICK_ATTACHMENT && resultCode == RESULT_OK && data != null && data.getData() != null){
                uriDocument= data.getData();
                String filename = getFilename(uriDocument);
                fileNameList.add(filename);
                mAdapter.notifyDataSetChanged();
            }
        } 

And I have a adapter class which now only contains one layout:

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

This is getFilename() method:

public String getFilename(Uri uri){
        String result =null;
        if (uri.getScheme().equals("content")){
            Cursor cursor = getContentResolver().query(uri,null,null,null,null);
            try{
                if (cursor!=null&&cursor.moveToFirst()){
                    result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
                }
            }finally {
                cursor.close();
            }
        }
        if (result == null){
            result = uri.getPath();
            int cut = result.lastIndexOf("/");
            if (cut!=-1){
                result = result.substring(cut+1);
            }
        }
        return result;
    }

How to make two different layouts depending on the type of document it has i.e., image or a pdf?

Upvotes: 0

Views: 1150

Answers (2)

aminography
aminography

Reputation: 22832

You should have multiple view types. I suggest you to use PrimeAdapter to do this easier. Please see its examples, however you can write your classes like following:

DataHolders:

@DataHolder
public class PdfDataHolder extends PrimeDataHolder {

    private String mFilePath;
    // ... other fields

    public PdfDataHolder(String filePath){
        mFilePath = filePath;
    }

    public String getFilePath() {
        return mFilePath;
    }
}

@DataHolder
public class ImageDataHolder extends PrimeDataHolder {

    private String mFilePath;
    // ... other fields

    public ImageDataHolder(String filePath){
        mFilePath = filePath;
    }

    public String getFilePath() {
        return mFilePath;
    }
}

ViewHolders:

public class PdfViewHolder extends PrimeViewHolder<PdfDataHolder> {

    private TextView textView;

    public PdfViewHolder(@NotNull PrimeDelegate delegate) {
        super(delegate, R.layout.list_item_pdf);
        textView = itemView.findViewById(R.id.textView);
    }

    @Override
    protected void bindDataToView(@NotNull PdfDataHolder dataHolder) {
        textView.setText(dataHolder.getFilePath());
    }

} 

public class ImageViewHolder extends PrimeViewHolder<ImageDataHolder> {

    private ImageView imageView;

    public ImageViewHolder(@NotNull PrimeDelegate delegate) {
        super(delegate, R.layout.list_item_image);
        imageView = itemView.findViewById(R.id.imageView);
    }

    @Override
    protected void bindDataToView(@NotNull ImageDataHolder dataHolder) {
        Glide.with(getContext()).load(dataHolder.getFilePath()).into(imageView);
    }

} 

Adapter:

public class FileListAdapter extends PrimeAdapter {

    @Nullable
    @Override
    public PrimeViewHolder<?> makeViewHolder(@Nullable Class<?> dataHolderClass) {
        if (dataHolderClass == PdfDataHolder.class) {
            return new PdfViewHolder(this);
        } else if (dataHolderClass == ImageDataHolder.class) {
            return new ImageViewHolder(this);
        } else {
            return null;
        }
    }

}

Upvotes: 1

Arshdeep Singh
Arshdeep Singh

Reputation: 61

First of all, you must be clear that how would you differentiate for different files. i.e. from FileName or someother field.

Now you can use any of these two solutions : 1. Use multiple view types inside RecyclerView's Adapter. 2. If you have to just show different icons for different files, then you can do that just by adding some checks.

Upvotes: 1

Related Questions