添加新项目时Android Firebase聊天RecyclerView自动滚动到底部

Posted

技术标签:

【中文标题】添加新项目时Android Firebase聊天RecyclerView自动滚动到底部【英文标题】:Android Firebase chat RecyclerView auto scroll to bottom when new item is added 【发布时间】:2017-04-09 09:48:21 【问题描述】:

我正在使用 firebase 开发一个 android 聊天。

我试图研究这个问题,但我找不到好的解决方案。

希望有人可以帮助我。

我的问题是,如果添加了新项目,我希望 RecyclerView 自动滚动。

这是我的代码。

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    View rootView = inflater.inflate(R.layout.chatlayoutchat, container, false);

    Connectivity connectivity=new Connectivity();
    if(connectivity.isConnected(getActivity())) 
        if(getArguments() != null) 
            Firebase.setAndroidContext(this.getActivity());
            String ccustomersid = getArguments().getString("customersid");
            String creferralae = getArguments().getString("referralae");
            String ccustomersname = getArguments().getString("customersname");

            customersid = ccustomersid;
            referralae = creferralae;
            customersname = ccustomersname;

            Firebase.setAndroidContext(this.getActivity());


            editText = (EditText) rootView.findViewById(R.id.editText);

            sendbutton = (Button) rootView.findViewById(R.id.button);
            mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
            RecyclerView.LayoutManager layoutmgr = new LinearLayoutManager(getActivity());
            mRecyclerView.setLayoutManager(layoutmgr);
            mRecyclerView.setItemAnimator(new DefaultItemAnimator());

            final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
            //linearLayoutManager.setReverseLayout(true);
            linearLayoutManager.setStackFromEnd(true);
            mRecyclerView.setLayoutManager(linearLayoutManager);

            from_user = customersid;
            to_user = referralae;
            LoggedInUser = customersname;


            //Log.v("NODE CREATED:", from_user + " " + to_user);


            ref_chatchildnode1 = firebase_chatnode.child(from_user + " " + to_user);

            //ref_chatchildnode2 = firebase_chatnode.child(to_user + " " + from_user);
            sendbutton.setOnClickListener(new View.OnClickListener() 
                @Override
                public void onClick(View view) 
                    newmsg = editText.getText().toString().trim();
                    ChatModel m = new ChatModel();
                    m.setSender(LoggedInUser);
                    m.setMessage(newmsg);
                    ref_chatchildnode1.push().setValue(m);
                    //ref_chatchildnode2.push().setValue(m);
                    editText.setText("");


                
            );
            ref_chatchildnode1.addChildEventListener(new ChildEventListener() 
                @Override
                public void onChildAdded(DataSnapshot dataSnapshot, String s) 
                    ChatModel chatmsg = dataSnapshot.getValue(ChatModel.class);
                    chatmsgsList.add(chatmsg);
                

                @Override
                public void onChildChanged(DataSnapshot dataSnapshot, String s) 

                

                @Override
                public void onChildRemoved(DataSnapshot dataSnapshot) 

                

                @Override
                public void onChildMoved(DataSnapshot dataSnapshot, String s) 

                

                @Override
                public void onCancelled(FirebaseError firebaseError) 

                
            );

        

    else
        nointernet();
    

    showGlobalContextActionBar();

    return rootView;


@Override
public void onStart() 
    super.onStart();
    mFirebaseAdapter1 = new FirebaseRecyclerAdapter<ChatModel, ChatMessageViewHolder>(ChatModel.class,
            R.layout.textview,
            ChatMessageViewHolder.class,
            ref_chatchildnode1) 
        @Override
        protected void populateViewHolder(ChatMessageViewHolder chatMessageViewHolder, ChatModel m, int i) 



            chatMessageViewHolder.sender.setText(m.getSender());
            chatMessageViewHolder.msg.setText(m.getMessage());

        
    ;
    mRecyclerView.setAdapter(mFirebaseAdapter1);


【问题讨论】:

【参考方案1】:

试试下面的代码:

         @Override
            public void onStart() 
                super.onStart();
                mFirebaseAdapter1 = new FirebaseRecyclerAdapter<ChatModel, ChatMessageViewHolder>(ChatModel.class,
                        R.layout.textview,
                        ChatMessageViewHolder.class,
                        ref_chatchildnode1) 
                    @Override
                    protected void populateViewHolder(ChatMessageViewHolder chatMessageViewHolder, ChatModel m, int i) 



                        chatMessageViewHolder.sender.setText(m.getSender());
                        chatMessageViewHolder.msg.setText(m.getMessage());

                    
                ;
                mRecyclerView.setAdapter(mFirebaseAdapter1);

        if (mFirebaseAdapter1 != null)  
                    mRecyclerView.postDelayed(new Runnable() 
                     @Override
                     public void run()  
                         mRecyclerView.smoothScrollToPosition(mFirebaseAdapter1.getItemCount() - 1);
                     
                  , 5); 
              
            

【讨论】:

在 RecyclerView 中设置适配器后添加它。 Sorry.. setSelection 替换为 smoothScrollToPosition 和 getCount 替换为 getItemCount() 我收到错误 java.lang.IllegalArgumentException: Invalid target position 看这里:***.com/questions/33229806/… 让我们continue this discussion in chat.【参考方案2】:

看看step 6 of the Firebase codelab for Android,它为此使用了AdapterDataObserver

mFirebaseAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() 
   @Override
   public void onItemRangeInserted(int positionStart, int itemCount) 
       super.onItemRangeInserted(positionStart, itemCount);
       int friendlyMessageCount = mFirebaseAdapter.getItemCount();
       int lastVisiblePosition =
              mLinearLayoutManager.findLastCompletelyVisibleItemPosition();
       // If the recycler view is initially being loaded or the 
       // user is at the bottom of the list, scroll to the bottom 
       // of the list to show the newly added message.
       if (lastVisiblePosition == -1 ||
               (positionStart >= (friendlyMessageCount - 1) &&
                       lastVisiblePosition == (positionStart - 1))) 
           mMessageRecyclerView.scrollToPosition(positionStart);
       
   
);

【讨论】:

如果您添加 1 条新消息,它将滚动。如果您有 6 条未读消息并单击阅读它们,它将显示第一条未读消息,其余 5 条您必须手动滚动才能查看到底部 使用if (lastVisiblePosition == -1 || positionStart &gt;= (friendlyMessageCount - 1)) 解决了这个问题!【参考方案3】:

我知道这是一个旧线程,但也许这会有所帮助。

在您添加新消息的地方:

yourRVAdapter.addMessage("New message")
val position = yourRVAdapter.itemCount.minus(1) // itemCount will return the size of RV items 
//Now just call your recyclerView.scrollToPosition(int)
chatRV.scrollToPosition(position)

【讨论】:

这并不总是有效:添加基础不是即时的,所以最有可能发生的情况是它会在添加之前使用数字并滚动到该项目而不是项目 +1【参考方案4】:
adapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() 
        override fun onItemRangeInserted(positionStart: Int, itemCount: Int) 
            
         CommentRv.scrollToPosition(adapter.itemCount.minus(1))
        
    )

【讨论】:

工作得很好。没有其他答案有效。

以上是关于添加新项目时Android Firebase聊天RecyclerView自动滚动到底部的主要内容,如果未能解决你的问题,请参考以下文章

使用 Firebase 的聊天应用程序:收到新消息时获取通知 - Android

使用 Firebase 的 Android 聊天应用程序,但未在 firebase 中存储数据

尝试从 Android Studio 添加 Firebase 项目时出错

android firebase 一对一聊天应用

Firebase Android 聊天示例:无法弹回输入

在android studio中将firebase添加到flutter时出错:插件项目:firebase_core_web未找到。请更新 settings.gradle [重复]