FirebaseRecyclerAdapter无法将第一个布局识别为位置

时间:2018-06-09 19:22:39

标签: android firebase firebase-realtime-database android-recyclerview firebaseui

我的标题有点难以理解,但基本上当我在我的数据库中添加项目时,应该在RecyclerView中显示它。现在在我的RecyclerView中我有两个布局,但问题是我的数据库的第一个项目落后于我的其他布局中的第一个项目。因此,如果我的数据库中有3个项目,它只显示数据库中的2个项目,第一个项目隐藏在RecyclerView中的第一个项目后面,这是一个根本不使用数据库的不同布局。

这是我的代码:

 FirebaseRecyclerOptions<Event> firebaseRecyclerOptions = new FirebaseRecyclerOptions.Builder<Event>()
            .setQuery(query1, Event.class).build();
    AccAdapter = new FirebaseRecyclerAdapter<Event, RecyclerView.ViewHolder>(firebaseRecyclerOptions){

        final static int TYPE_HEADER = 0;
        final static int TYPE_ITEM = 1;


        @Override
        public int getItemViewType(int position) {
            if (position == 0) return TYPE_HEADER;
            return TYPE_ITEM;
        }

        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

            if (viewType == TYPE_HEADER){
                View view = LayoutInflater.from(getActivity()).inflate(R.layout.recycler_view_row_add_items,
                        parent, false);
                return new ProdudctHolder3(view);
            } else {
                View view = LayoutInflater.from(getActivity()).inflate(R.layout.recycler_view_row_acc,
                        parent, false);
                return new ProductHolder2(view);
            }
        }

        @Override
        protected void onBindViewHolder(final RecyclerView.ViewHolder holder, int position, final Event model) {
            if (holder instanceof ProdudctHolder3){
                ((ProdudctHolder3) holder).addBackground.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        startActivity(new Intent(getActivity(), AccAddItems.class ));
                    }
                });
            } else{

                final ProductHolder2 productHolder2 = (ProductHolder2) holder;


                productHolder2.mName.setText(model.getName());
                productHolder2.view.setBackgroundResource(getBackgroundDrawable(Integer.valueOf(model.getProductAmount())));
                productHolder2.mbackground.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {

                        dialog = new Dialog(getActivity());
                        dialog.setContentView(R.layout.popup_edit_product);

                        SeekBar amountSeekBar = dialog.findViewById(R.id.amountSeekBar);
                        amountSeekBar.setMax(100);
                        amountSeekBar.setProgress(Integer.valueOf(model.getProductAmount()));
                        amountSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
                            @Override
                            public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
                                progress = i;
                            }

                            @Override
                            public void onStartTrackingTouch(SeekBar seekBar) {

                            }

                            @Override
                            public void onStopTrackingTouch(SeekBar seekBar) {
                                getRef(holder.getAdapterPosition()).child("productAmount").setValue(String.valueOf(progress));
                                dialog.dismiss();

                            }
                        });

                        dialog.show();

                    }
                });

                productHolder2.mbackground.setOnLongClickListener(new View.OnLongClickListener() {
                    @Override
                    public boolean onLongClick(View view) {
                        final PopupMenu popupMenu = new PopupMenu(getActivity(), productHolder2.mbackground);

                        popupMenu.inflate(R.menu.menu_acc);
                        popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
                            @Override
                            public boolean onMenuItemClick(MenuItem menuItem) {
                                switch (menuItem.getItemId()){
                                    case R.id.deleteProduct:
                                        getRef(productHolder2.getAdapterPosition()).removeValue();
                                        popupMenu.dismiss();
                                        return true;

                                    default:
                                        return false;
                                }
                            }
                        });

                        popupMenu.show();

                        return true;
                    }
                });

            }
        }

    };

    mAccRecyclerViewRef.setAdapter(AccAdapter);

我的两个产品持有人

私有类ProdudctHolder3扩展了RecyclerView.ViewHolder {

    private RelativeLayout addBackground;

    public ProdudctHolder3(View itemView) {
        super(itemView);
        addBackground = itemView.findViewById(R.id.mBackground2);
    }
}

private class ProductHolder2 extends RecyclerView.ViewHolder{

    private TextView mName;
    private RelativeLayout mbackground;
    private View view;

    public ProductHolder2(View itemView) {
        super(itemView);

        mName = itemView.findViewById(R.id.ItemName);
        mbackground = itemView.findViewById(R.id.mBackground1);
        view = itemView.findViewById(R.id.amountIndicator);

    }
}

2 个答案:

答案 0 :(得分:2)

理想的解决方案是在单个RecyclerView上设置两个适配器,但不幸的是,这是不可能的。 但是,您可以创建一个处理两种类型项的自定义适配器。我将通过举例来解释这一点。

假设您需要显示两种类型的对象humansaliens。您的对象需要完全不同的布局和完全不同的ViewHolders。请参阅以下代码ViewHolders

public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private static class HumanViewHolder extends RecyclerView.ViewHolder {
        public HumanViewHolder(View itemView) {
            super(itemView);

            //Prepare your ViewHolder
        }

        public void bind(Human human) {

            //Display your human object
        }
    }

    private static class AlienViewHolder extends RecyclerView.ViewHolder {
        public AlienViewHolder(View itemView) {
            super(itemView);

            //Prepare your ViewHolder
        }

        public void bind(Alien alien) {

            //Display your alien object
        }
    }
}

首先,您需要向适配器添加两个不同的常量,表示两种类型的视图:

private static final int ITEM_TYPE_HUMAN;
private static final int ITEM_TYPE_ALIEN;

为了简单起见,我们还假设您将对象存储在列表中:

private List<Object> items = new ArrayList<>();

public MyAdapter(List<Object> items) {
    this.items.addAll(items);

    //Other stuff if needed
}

现在,您需要做的第一件事就是实现getItemViewType()方法:

@Override
public int getItemViewType(int position) {
    if (items.get(position) instanceof Human) {
        return ITEM_TYPE_HUMAN;
    } else {
        return ITEM_TYPE_ALIEN;
    }
} 

其次,您需要在onCreateViewHolder()方法中使用项目类型,如下所示:

@Override 
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)  {
    LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());

    if (viewType == ITEM_TYPE_HUMAN) {
        View view = layoutInflater.inflate(R.layout.item_human, parent, false);

        return new HumanViewHolder(view);
    } else {      
        View view = layoutInflater.inflate(R.layout.item_alien, parent, false);

        return new AlienViewHolder(view);
    } 
} 

最后,您只需要绑定正确的视图持有者,如下所示:

@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
    Object item = items.get(position);

    if (viewHolder instanceof HumanViewHolder) {
        ((HumanViewHolder) viewHolder).bind((Human) item);
    } else {
        ((AlienViewHolder) viewHolder).bind((Alien) item);
    } 
} 

答案 1 :(得分:0)

为什么在您可以轻松制作自定义适配器时使用Firebase Recycler Adapter?如果我理解你想要一个项目固定在0(标题),而其他项目将被添加到第一个项目下方,对吧?如果是这样,这是我喜欢使用的解决方案:

public interface ViewType {
    public int getViewType();
}

public interface ViewTypeDelegateAdapter {
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent);
    public void onBindViewHolder(RecyclerView.ViewHolder holder, ViewType item);
}

public class ViewTypes {
    public static int HEADER = 0
    public static int ITEM = 1
}

public class ProductDelegateAdapter implements ViewTypeDelegateAdapter {

    private int resID;
    private Context context;

    public ProductDelegateAdapter(int resID, Context context) {
        this.resID = resID;
        this.context = context;
    }

    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent) {
        return new ProductHolder(LayoutInflater.from(parent.context).inflate(resID, parent, false));
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, ViewType item) {
        (holder as ProductHolder).bind("test");
    }

    class ProductHolder extends RecyclerView.ViewHolder {

        public ProductHolder(View view) {
            super(view);
        }

        public void bind(String test) {

        }

    }

}

public class HeaderDelegateAdapter implements ViewTypeDelegateAdapter {

    private int resID;
    private Context context;

    public ProductDelegateAdapter(int resID, Context context) {
        this.resID = resID;
        this.context = context;
    }

    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent) {
        return new HeaderHolder(LayoutInflater.from(parent.context).inflate(resID, parent, false));
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, ViewType item) {
        (holder as HeaderHolder).bind("test");
    }

    class HeaderHolder extends RecyclerView.ViewHolder {

        public HeaderHolder(View view) {
            super(view);
        }

        public void bind(String test) {

        }

    }

}

public class AccAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    private Context context;
    private List<ViewType> items;
    private SparseArrayCompat<ViewTypeDelegateAdapter> delegateAdapters;
    private ViewType headerItem;

    public AccAdapter(Context context) {
        this.context = context;
        this.items = new ArrayList();
        this.delegateAdapters = new SparseArrayCompat();
        this.headerItem = new ViewType() {
            @Override
            public int getViewType() {
                return ViewTypes.HEADER;
            }
        };

        this.items.add(this.headerItem);
        this.delegateAdapters.put(ViewTypes.HEADER, HeaderDelegateAdapter(R.id.test, this.context));
        this.delegateAdapters.put(ViewTypes.ITEM, ProductDelegateAdapter(R.id.test, this.context));
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, Int viewType) {
        return delegateAdapters.get(viewType).onCreateViewHolder(parent);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, Int position) {
        delegateAdapters.get(getItemViewType(position)).onBindViewHolder(holder, items[position])
    }

    @Override
    public Int getItemViewType(Int position) {
        return items.get(position).getViewType();
    }

    @Override
    public Int getItemCount() {
        return items.getSize();
    }

    public void add(ViewType viewType) {
        val initPosition = this.items.size - 1
        this.items.add(item)
        notifyItemRangeChanged(initPosition, this.items.size + 1)
    }

}

public class Event implements ViewType {

    private String id;

    @Override
    public int getViewType() {
        return ViewTypes.ITEM;
    }

}

请原谅我的一些语法错误,我已经从Kotlin翻译成Java来帮助你。希望它有所帮助!