我需要在RecyclerView
中添加标题视图,而我使用的适配器来自Firebase ui。
对于普通的RecyclerView
适配器,我只需处理不同的视图类型并处理一些计数/位置偏移。
但在FirebaseAdapter
中遵循相同的方法似乎是一种不好的做法,在这种情况下最好的方法是什么。
这是我能得到的最接近的。
mAdapter = new FirebaseRecyclerAdapter<Comment, RecyclerView.ViewHolder>(Comment.class,
R.layout.item_comment, CommentHolder.class, ref) {
final static int TYPE_HEADER = 0;
final static int TYPE_ITEM = 1;
@Override
protected void populateViewHolder(RecyclerView.ViewHolder viewHolder, Comment comment, int position) {
//cast to comment holder
final CommentHolder commentViewHolder = (CommentHolder) viewHolder;
//initialize view
commentViewHolder.setComment(comment.getComment());
commentViewHolder.setTime(comment.getTimestamp());
//get user details and set view
DatabaseReference ref = FirebaseDatabase.getInstance().getReference(FireContract.PATH_USER_PROFILE)
.child(comment.getUserKey());
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
User user = dataSnapshot.getValue(User.class);
if(user != null) {
commentViewHolder.setName(user.getName());
commentViewHolder.setUsername("@" + user.getUsername());
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
//return header view holder is type is header else return super from firebase ui
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if(viewType == TYPE_HEADER){
View view = LayoutInflater.from(getActivity()).inflate(R.layout.post_details,
parent, false);
return new PostViewHolder(view);
}
else
return super.onCreateViewHolder(parent, viewType);
}
//initialize post details as header if position is 0 else call super with position less
//by one to cater for the header offset
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
if(position == 0)
initializePostDetails((PostViewHolder) viewHolder);
else
super.onBindViewHolder(viewHolder, position - 1);
}
//return view type header if position is 0 else call super from firebase ui
@Override
public int getItemViewType(int position) {
if(position == 0)
return TYPE_HEADER;
return super.getItemViewType(position - 1);
}
//set count equal to 1 plus actual list items, 1 is added for header view
@Override
public int getItemCount() {
return super.getItemCount() + 1;
}
};
但这会产生cannot resolve constructor
问题,但即使解决了这个问题,它也可能无效。
答案 0 :(得分:1)
所以,这是我能够升级我的适配器,它确实适用于我但不确定它是否仍然是实现此目标的最佳方法。如果有人可以验证这一点或者可能提出更简单的解决方案,那将会很棒
mAdapter = new FirebaseRecyclerAdapter<Comment, RecyclerView.ViewHolder>(Comment.class,
R.layout.item_comment, RecyclerView.ViewHolder.class, ref) {
final static int TYPE_HEADER = 0;
final static int TYPE_ITEM = 1;
@Override
protected void populateViewHolder(RecyclerView.ViewHolder viewHolder, Comment comment, int position) {
Log.d(TAG, "running populateViewHolder");
}
//return header view holder is type is header else return super from firebase ui
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if(viewType == TYPE_HEADER){
View view = LayoutInflater.from(getActivity()).inflate(R.layout.post_details,
parent, false);
return new PostViewHolder(view);
}
//if type is not header its item view, so return commentHolder instance
else{
View view = LayoutInflater.from(getActivity()).inflate(R.layout.item_comment,
parent, false);
return new CommentHolder(view);
}
}
//initialize post details as header if position is 0 else call super with position less
//by one to cater for the header offset
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
//if holder is post view holder, initialize header
if(viewHolder instanceof PostViewHolder)
initializePostDetails((PostViewHolder) viewHolder);
else{
//cast to comment holder
final CommentHolder commentViewHolder = (CommentHolder) viewHolder;
Comment comment = getItem(position);
//initialize view
commentViewHolder.setComment(comment.getComment());
commentViewHolder.setTime(comment.getTimestamp());
//get user details and set view
DatabaseReference ref = FirebaseDatabase.getInstance().getReference(FireContract.PATH_USER_PROFILE)
.child(comment.getUserKey());
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
User user = dataSnapshot.getValue(User.class);
if(user != null) {
commentViewHolder.setName(user.getName());
commentViewHolder.setUsername("@" + user.getUsername());
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
//return view type header if position is 0 else call super from firebase ui
@Override
public int getItemViewType(int position) {
if(position == 0)
return TYPE_HEADER;
return TYPE_ITEM;
}
//set count equal to 1 plus actual list items, 1 is added for header view
@Override
public int getItemCount() {
return super.getItemCount() + 1;
}
//return comment item, decrement 1 from position to avoid out of rand exception as it was
//incremented for adding header
@Override
public Comment getItem(int position) {
return super.getItem(position - 1);
}
};
答案 1 :(得分:0)
更新(2016年12月6日):如果您需要检查一个空的FirebaseRecyclerView,这一切都有点hacky,但到目前为止,这是我知道的唯一方法。 总而言之,你需要照顾两个案例。
当列表中有项目时 - 您可以将项目装饰器添加到Recycler视图,以便在列表中有项目时创建标题。 (正如我在原帖中所写,或as seen here)。如果您不需要担心空的回收者视图,这就是您需要做的全部。
当列表为空时 - 项目装饰器无法显示,因此您可以添加在View.VISIBLE(对于空列表)和View.GONE(对于填充列表)之间切换的视图。 (有关详细信息,请查看this link)
View emptyView = findViewById(R.id.empty_view);
dataBaseReference.addListenerValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.hasChildren()) {
emptyView.setVisibility(View.GONE);
} else {
emptyView.setVisibility(View.VISIBLE);
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
因此,一旦列表中有内容,我们就会删除该空视图,并显示项目装饰器,它将随着回收器视图的滚动而移动。
**原始邮寄**
我最近遇到了同样的困境。我使用了一个普通的RecyclerViewAdapter解决方案,它可以很好地工作here,这只是将一个ItemDecorator添加到recyclerView本身,如下所示:
recyclerView.addItemDecoration(new HeaderDecoration(this,
recyclerView, R.layout.test_header));
从这里开始制作自定义物品装饰器。如果你需要水平或任何东西,你会搞乱那里的值(大多数引用顶部需要引用左边的东西):
public class HeaderDecoration extends RecyclerView.ItemDecoration {
private View mLayout;
public HeaderDecoration(final Context context, RecyclerView parent, @LayoutRes int resId) {
// inflate and measure the layout
mLayout = LayoutInflater.from(context).inflate(resId, parent, false);
mLayout.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDraw(c, parent, state);
// layout basically just gets drawn on the reserved space on top of the first view
mLayout.layout(parent.getLeft(), 0, parent.getRight(), mLayout.getMeasuredHeight());
for (int i = 0; i < parent.getChildCount(); i++) {
View view = parent.getChildAt(i);
if (parent.getChildAdapterPosition(view) == 0) {
c.save();
final int height = mLayout.getMeasuredHeight();
final int top = view.getTop() - height;
c.translate(0, top);
mLayout.draw(c);
c.restore();
break;
}
}
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
if (parent.getChildAdapterPosition(view) == 0) {
outRect.set(0, mLayout.getMeasuredHeight(), 0, 0);
} else {
outRect.setEmpty();
}
}
}
到目前为止,它的问题是,使用空列表,没有项目装饰器。我正在查看关于回收站视图的空视图,当我使用Firebase时,我会更新此信息。