Search code examples
androidandroid-recyclerviewfirebase-realtime-databasesmooth-scrollingfirebaseui

RecyclerView scroll in incorrect direction when new element is inserted


I use smoothScrollToPosition to scroll RecyclerView. It does scroll every time a new entry is inserted; but to the top, not to the bottom, which is the direction i want.

    list_chat = (RecyclerView) findViewById(R.id.list_chat);
    //Set up Layout Manager
    linearLayoutManager = new LinearLayoutManager(this);
    linearLayoutManager.setStackFromEnd(true);
    list_chat.setLayoutManager(linearLayoutManager);
    //set adapter
    list_chat.setAdapter(adapter);
    //set scroll
    list_chat.post(new Runnable() {
        @Override
        public void run() {
            list_chat.smoothScrollToPosition(adapter.getItemCount());
        }
    });

The adapter is from Firebase

adapter = new FirebaseRecyclerAdapter<ChatItem, ChatRecylerViewHolder>(ChatItem.class,R.layout.chat_item
        ,ChatRecylerViewHolder.class,queryChat  ) {
        @Override
        protected void populateViewHolder(ChatRecylerViewHolder viewHolder, ChatItem model, int position) {
            viewHolder.tvAuthorChat.setText(model.chatAuthor);
            viewHolder.tvContentChat.setText(model.chatContent);
        }
    };

Solution

  • Ok. I found the answer. First, the old problem with my question: i thought list_chat.post is called whenever an item is inserted (turn out that is wrong). The reason for it keeps scrolling top is linearLayoutManager.setStackFromEnd(true); Thus, the question comes down to Where to call the scrolling ? The answer is : Since adapter manages data, it makes sense to guess that adapter will notify the insertion. Here is the code

    adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
            @Override
            public void onItemRangeInserted(int positionStart, int itemCount) {
                super.onItemRangeInserted(positionStart, itemCount);
                list_chat.smoothScrollToPosition(adapter.getItemCount());
            }
        });