2016-11-15 48 views
1

我需要在RecyclerView中添加标题视图,我使用的适配器来自Firebase ui。Firebase ui - 在android中设置FirebaseRecyclerView的设置标题视图

对于正常的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

所以,这是我能够升级我的适配器,它确实为我工作,但不知道它是否仍然是实现此目标的最佳方法。它会是巨大的,如果有人可以验证这一点还是可以提出一个更好更简单的解决方案

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); 
     } 
    }; 
+0

所以解决方案的问题在于,每次更改或插入通知时,Firebase发出的指向前一个项目都意味着更改应该是4,它与goto项目5并且还没有找到方法避免这种情况 –

0

更新(2016年12月6日):这一切都有点哈克,如果你需要检查空FirebaseRecyclerView,但到目前为止,这是我知道这样做的唯一途径。所以总结一下,你需要照顾两种情况。

  1. 当有列表中的项目 - 您可以添加一个项目装饰到回收站视图,使头时,有列表中的项目。 (如我原来的帖子,或as seen here)。如果您不需要担心空的回收站的意见,这是所有你需要做的。

  2. 当列表为空时 - Item Decorator无法显示,因此您可以添加在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(); 
    } 
} 

}

它的问题至今是一个空列表,没有项目装饰器。我正在调查Empty Views以获取回收站视图,我将在与Firebase合作时更新此视图。