Manage Multiple View Types - RecyclerView

。_饼干妹妹 提交于 2019-12-23 05:01:49

问题


I am using this library to display mutiple types of views inside a RecyclerView .

Here I am using EnumMapBindAdapter to display userposts list .

I have 4 DataBinder classes ,each binder has a list of size 3 (size may change depending on the user posts ) . I have problem with getEnumFromPosition() ,According to my assumptions number of executions of getEnumFromPosition() method should be equal to number of binders (4) . But it is not happening .I have total 4 binders and I assume getEnumFromPosition() method should execute 4 times only (0,1,2,3) ,but executions are being excedeed . My assumption may be wrong ,If I am wrong then how can I manage 4 binders inside getEnumFromPosition() for different positions . If I put else section inside getEnumFromPosition() method then it will return a single view when position exceeds .

Here is the code of SampleEnumMapAdapter.java

 public class SampleEnumMapAdapter extends EnumMapBindAdapter<SampleEnumMapAdapter.SampleViewType> {

    enum SampleViewType{
        TEXT,IMAGE_AND_TEXT, AUDIO_AND_TEXT, VIDEO_AND_TEXT
    }

    public SampleEnumMapAdapter(){
        putBinder(SampleViewType.TEXT, new TextBinder(this));
        putBinder(SampleViewType.IMAGE_AND_TEXT, new ImageAndTextBinder(this));
        putBinder(SampleViewType.AUDIO_AND_TEXT, new AudioAndTextBinder(this));
        putBinder(SampleViewType.VIDEO_AND_TEXT, new VideoAndTextBinder(this));
    }

    public void setData(List<TextData> dataSetText ,List<ImageAndTextData> dataSetTextAndImage ,List<AudioAndTextData> dataSetTextAndAudio ,List<VideoAndTextData> dataSetTextAndVideo ) {
        ((TextBinder) getDataBinder(SampleViewType.TEXT)).addAll(dataSetText);
        ((ImageAndTextBinder) getDataBinder(SampleViewType.IMAGE_AND_TEXT)).addAll(dataSetTextAndImage);
        ((AudioAndTextBinder) getDataBinder(SampleViewType.AUDIO_AND_TEXT)).addAll(dataSetTextAndAudio);
        ((VideoAndTextBinder) getDataBinder(SampleViewType.VIDEO_AND_TEXT)).addAll(dataSetTextAndVideo);
    }

    @Override
    public SampleViewType getEnumFromPosition(int position){
        if (position == 0) {
            return SampleViewType.TEXT;
        } else if (position == 1) {
            return SampleViewType.IMAGE_AND_TEXT;
        } else if(position == 2){
            return SampleViewType.AUDIO_AND_TEXT;
        }else if(position == 3){
            return SampleViewType.VIDEO_AND_TEXT;
        }
        return null;
    }

    @Override
    public SampleViewType getEnumFromOrdinal(int ordinal) {
        return SampleViewType.values()[ordinal];
    }
}

回答1:


I was working on the similar problem earlier , But I configured RecyclerView Adapter manually ,I have not used any library for this . I am giving you a sample code here . This is a complete Multile View Type Adapter

    public class UserPostAdapter extends RecyclerView.Adapter<UserPostAdapter.PostViewHolder> {

    private List<UserPostsListItem> postlist;
    Context conetxt;
    LayoutInflater inflater;
    private ViewClickListener mClickListener;
    private ItemViewClickListener itemViewClickListener;
    int count;

    public UserPostAdapter() {

    }

    public UserPostAdapter(Context conetxt, List<UserPostsListItem> postlist) {
        this.postlist = postlist;
        this.conetxt = conetxt;
        inflater = LayoutInflater.from(this.conetxt);
    }

    @Override
    public int getItemCount() {
        int size = 0;
        if (postlist != null)
            size = postlist.size();
        return size;
    }

    @Override
    public int getItemViewType(int position) {
        int viewTypePosition =0;

        String attachment_type = postlist.get(position).getAttachment_type();

        switch (attachment_type){

            case "text":
                viewTypePosition = 0 ;
                break;
            case "image":
                viewTypePosition = 1 ;
                break;
            case "audio":
                viewTypePosition = 2 ;
                break;
            case "video":
                viewTypePosition = 3 ;
                break;
            default:
        }

        return viewTypePosition;
    }

    @Override
    public void onBindViewHolder(final PostViewHolder videoViewHolder, final int position) {

        //Log.d("onBindViewHolder",Integer.toString(position));
        final UserPostsListItem item = postlist.get(position);

        switch (item.getAttachment_type()){
            case "audio":

                break;
            case "video":

                break;
            case "text":

                break;
            case "image":

                break;           
            default:
        }

        }catch (Exception e){
            e.printStackTrace();
        }

    }

    public interface ItemViewClickListener {
        void onItemChildClicked(int position ,String type);
    }

    public void setItemViewClickListener (ItemViewClickListener viewClickListener) {
        itemViewClickListener = viewClickListener;
    }


    public List<UserPostsListItem> getUserPostsList() {
        return postlist;
    }

    @Override
    public PostViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType){

        Log.d("ViewType", Integer.toString(viewType));
        switch (viewType) {
            case 0:
                View itemViewText = inflater.inflate(R.layout.userposts_listitem_text, viewGroup, false);
                return new PostViewHolder(itemViewText ,viewType);

            case 1:
                View itemViewTextImage = inflater.inflate(R.layout.userposts_listitem_textandimage, viewGroup, false);
                return new PostViewHolder(itemViewTextImage,viewType);

            case 2:
                View itemViewTextAudio = inflater.inflate(R.layout.userposts_listitem_audioandtext, viewGroup, false);
                return new PostViewHolder(itemViewTextAudio,viewType);

            case 3:
                View itemViewTextVideo = inflater.inflate(R.layout.userposts_listitem_videoandtext, viewGroup, false);
                return new PostViewHolder(itemViewTextVideo,viewType);

            default:
        }

        return null;

    }

    public interface ViewClickListener {
        void onVideoClicked(int position,View v);
    }

    public List<UserPostsListItem> getVideoItems() {
        return postlist;
    }

    public void setViewClickListener (ViewClickListener viewClickListener) {
        mClickListener = viewClickListener;
    }

    public static class PostViewHolder extends RecyclerView.ViewHolder {
        ImageView attachment;
        CircleImageView circleImageView;
        ImageView audio;
        public PostViewHolder(View v,int viewtype) {
            super(v);
            switch (viewtype){
                //For Audio
                case 2:                    
                    break;                  
                //For Video
                case 3:                    
                    break;
                //For Text only
                case 0:
                    break;
                //For Image
                case 1:                    
                    break;                
                default:

            }
        }
    }

}



回答2:


Don't manage binders by position, manage binders by type of data to be stored/shown at that position. Add a type field to SampleViewType and on every position match the type with its respective binder and load its respective data.

Example for explanation :-

You mainly need to change only one method inside your adapter. For the sake of explanation, let us assume you are inflating a List of data in your adapter. Let the list's name data. Your method getEnumFromPosition() would look something like this :-

@Override
public SampleViewType getEnumFromPosition(int position){
    return data.get(position).getViewType();
}

In the above lines of code, data is your list and get method gets one of the object from the list. This object is of type SampleViewType. In your class SampleViewType you would need to create a data member called type which will hold the type of each object of your class SampleViewType and will have a getter function named getViewType(). This getViewType() function will return the type of that particular SampleViewType object, like SampleViewType.TEXT etc like you returned with respect to position.

You might need to create a separate class named SampleView and inflate your adapter with it, while your class SampleViewType will hold important information for all types of your SampleViews.

I hope this example explains you what I want to convey, in case of any confusion please do feel free to ask.



来源:https://stackoverflow.com/questions/33894351/manage-multiple-view-types-recyclerview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!