IT

RecyclerView의 맨 아래로 스크롤하는 방법?

lottoking 2020. 6. 19. 07:55
반응형

RecyclerView의 맨 아래로 스크롤하는 방법? scrollToPosition이 작동하지 않습니다


활동을로드 한 후 RecyclerView 목록의 맨 아래로 스크롤하고 싶습니다.

GENERIC_MESSAGE_LIST = (ArrayList) intent.getExtras().getParcelableArrayList(ConversationsAdapter.EXTRA_MESSAGE);
conversationView = (RecyclerView) findViewById(R.id.list_messages);
conversationView.setHasFixedSize(true);
conversationViewLayoutManager = new LinearLayoutManager(this);
conversationView.setLayoutManager(conversationViewLayoutManager);
conversationViewAdapter = new ConversationAdapter(GENERIC_MESSAGE_LIST, this);
conversationView.setAdapter(conversationViewAdapter);

conversationView.scrollTo(...)RecyclerView에서 지원되지 않는 것에 대한 예외를 throw하고 conversationView.scrollToPosition(...)아무것도하지 않는 것 같습니다.

위의 코드 블록 뒤에 추가했습니다

conversationView.scrollToPosition(GENERIC_MESSAGE_LIST.size() + 1)

작동하지 않습니다. 에 30 개의 요소가 GENERIC_MESSAGE_LIST있습니다.


그냥 설정 setStackFromEnd=true또는 setReverseLayout=true너무 LLM은 끝에서 항목을 레이아웃 것이다.

이 두 가지의 차이점 setStackFromEnd은 마지막 요소를 표시하도록보기를 설정하고 레이아웃 방향이 동일하게 유지된다는 것입니다. (왼쪽에서 오른쪽으로 가로 리사이클 러보기에서 마지막 요소가 표시되고 왼쪽으로 스크롤하면 이전 요소가 표시됩니다)

반면 setReverseLayout어댑터가 추가 한 요소의 순서는 변경됩니다. 레이아웃은 LTR Recycler View에서 가장 왼쪽에있는 마지막 요소에서 시작한 다음 오른쪽으로 스크롤하면 이전 요소가 표시됩니다.

견본:

final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
linearLayoutManager.setReverseLayout(true);
_listView.setLayoutManager(linearLayoutManager);

자세한 내용은 설명서 를 참조하십시오.


답을 찾기 위해이 게시물을보고 있었지만 ...이 게시물의 모든 사람이 나와 같은 시나리오에 직면했다고 생각합니다 scrollToPosition(). 명백한 이유로 완전히 무시되었습니다.

내가 무엇을 사용하고 있었습니까?

recyclerView.scrollToPosition(items.size());

... 무슨 일 했어요 ?

recyclerView.scrollToPosition(items.size() - 1);

해결책을 알고 싶은 사람이 있다면 아래 답변이 늦습니다.

conversationView.smoothScrollToPosition(conversationView.getAdapter().getItemCount() - 1);

recyclerview의 임의의 위치에서 아래로 스크롤하려면

edittext.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                rv_commentList.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                      rv_commentList.scrollToPosition(rv_commentList.getAdapter().getItemCount() - 1);
                    }
                }, 1000);
            }
        });

메시지를 보낸 후와 서버에서 메시지를 받기 전에이 코드를 추가하십시오.

recyclerView.scrollToPosition(mChatList.size() - 1);

를 호출 setAdapter하면 화면에 항목을 즉시 배치하고 배치하지 않습니다 (단일 레이아웃 패스가 필요함) scrollToPosition(). 호출 할 때 스크롤 할 실제 요소가 없습니다.

대신 ViewTreeObserver.OnGlobalLayoutListener를 (에 의해 생성 된 addOnGlobalLayoutListner ()통해) 등록해야 첫 번째 레이아웃 통과 후까지 지연됩니다 .ViewTreeObserverconversationView.getViewTreeObserver()scrollToPosition()

conversationView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
  public void onGlobalLayout() {
    conversationView.scrollToPosition(GENERIC_MESSAGE_LIST.size();
    // Unregister the listener to only call scrollToPosition once
    conversationView.getViewTreeObserver().removeGlobalOnLayoutListener(this);

    // Use vto.removeOnGlobalLayoutListener(this) on API16+ devices as 
    // removeGlobalOnLayoutListener is deprecated.
    // They do the same thing, just a rename so your choice.
  }
});

코 틀린 솔루션 :

"recyclerView.adapter"를 설정 한 후 또는 "recyclerView.adapter.notifyDataSetChanged ()"후에 코드 아래에 적용

recyclerView.scrollToPosition(recyclerView.adapter.itemCount - 1)

class MyLayoutManager extends LinearLayoutManager {

  public MyLayoutManager(Context context) {
    super(context, LinearLayoutManager.VERTICAL, false);
  }

  @Override public void smoothScrollToPosition(RecyclerView recyclerView,
      final RecyclerView.State state, final int position) {

    int fcvip = findFirstCompletelyVisibleItemPosition();
    int lcvip = findLastCompletelyVisibleItemPosition();

    if (position < fcvip || lcvip < position) {
      // scrolling to invisible position

      float fcviY = findViewByPosition(fcvip).getY();
      float lcviY = findViewByPosition(lcvip).getY();

      recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {

        int currentState = RecyclerView.SCROLL_STATE_IDLE;

        @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) {

          if (currentState == RecyclerView.SCROLL_STATE_SETTLING
              && newState == RecyclerView.SCROLL_STATE_IDLE) {

            // recursive scrolling
            smoothScrollToPosition(recyclerView, state, position);
          }

          currentState = newState;
        }

        @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

          int fcvip = findFirstCompletelyVisibleItemPosition();
          int lcvip = findLastCompletelyVisibleItemPosition();

          if ((dy < 0 && fcvip == position) || (dy > 0 && lcvip == position)) {
            // stop scrolling
            recyclerView.setOnScrollListener(null);
          }
        }
      });

      if (position < fcvip) {
        // scroll up

        recyclerView.smoothScrollBy(0, (int) (fcviY - lcviY));
      } else {
        // scroll down

        recyclerView.smoothScrollBy(0, (int) (lcviY - fcviY));
      }
    } else {
      // scrolling to visible position

      float fromY = findViewByPosition(fcvip).getY();
      float targetY = findViewByPosition(position).getY();

      recyclerView.smoothScrollBy(0, (int) (targetY - fromY));
    }
  }
}

MyLayoutManager layoutManager = new MyLayoutManager(context);
recyclerView.setLayoutManager(layoutManager);

RecyclerView.Adapter adapter = new YourAdapter();
recyclerView.setAdapter(adapter);

recyclerView.smoothScrollToPosition(adapter.getItemCount() - 1);

위의 코드는 작동하지만 부드럽 지 않고 시원하지 않습니다.


recyclerView에 어댑터가 연결되어 있으면이 작업을 수행하십시오.

mRecyclerView.smoothScrollToPosition(mRecyclerView.getAdapter().getItemCount());


In my case where views do not have the same height, calling scrollToPosition on the LayoutManager worked to really scroll to the bottom and see fully the last item:

recycler.getLayoutManager().scrollToPosition(adapter.getItemCount() - 1);

Roc answer is a great help. I would like to add a small block to it:

mRecyclerView.scrollToPosition(mAdapter.getItemCount() - 1);

In Kotlin:

recyclerView.viewTreeObserver.addOnGlobalLayoutListener { scrollToEnd() }

private fun scrollToEnd() =
        (adapter.itemCount - 1).takeIf { it > 0 }?.let(recyclerView::smoothScrollToPosition)

This works perfectly fine for me:

AdapterChart adapterChart = new AdapterChart(getContext(),messageList);
recyclerView.setAdapter(adapterChart);
recyclerView.scrollToPosition(recyclerView.getAdapter().getItemCount()-1);

Only Ian's answer was able to make my RecyclerView scroll to a specified position. However, The RecyclerView was not able to scroll afterwards when I used scrollToPosition(). smoothScrollToPosition() worked but the initial animation made it too slow when the list was long. The reason was the listener was not removed. I used the code below to remove the current ViewTreeObserver and it worked as a charm.

    mRecyclerView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            mRecyclerView.scrollToPosition(mPosition);
            mRecyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        }
    });

this code will give you latest post first, i think this answer is helpful.

    mInstaList=(RecyclerView)findViewById(R.id.insta_list);
    mInstaList.setHasFixedSize(true);

    LinearLayoutManager layoutManager = new LinearLayoutManager(this);
    layoutManager.setOrientation(LinearLayoutManager.VERTICAL);

    mInstaList.setLayoutManager(layoutManager);
    layoutManager.setStackFromEnd(true);
    layoutManager.setReverseLayout(true);

Tried a method of @galex, it worked until refactoring. So I used an answer of @yanchenko and changed a bit. Probably this is because I called scrolling from onCreateView(), where a fragment view was built (and probably didn't have right size).

private fun scrollPhotosToEnd(view: View) {
    view.recycler_view.viewTreeObserver.addOnGlobalLayoutListener(object :
        ViewTreeObserver.OnGlobalLayoutListener {
        override fun onGlobalLayout() {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                view.recycler_view.viewTreeObserver.removeOnGlobalLayoutListener(this)
            } else {
                @Suppress("DEPRECATION")
                view.recycler_view.viewTreeObserver.removeGlobalOnLayoutListener(this)
            }
            adapter?.itemCount?.takeIf { it > 0 }?.let {
                view.recycler_view.scrollToPosition(it - 1)
            }
        }
    })
}

You can also add a check of viewTreeObserver.isAlive like in https://stackoverflow.com/a/39001731/2914140.


Firsttime scroll when entering in recycler view first time then use linearLayoutManager.scrollToPositionWithOffset(messageHashMap.size()-1,put in minus for scroll down for scroll up put in positive value);

if view is very big in height then scrolltoposition particular offset is used for top of view then you use

int overallXScroldl =chatMessageBinding.rvChat.computeVerticalScrollOffset(); chatMessageBinding.rvChat.smoothScrollBy(0, Math.abs(overallXScroldl));

참고URL : https://stackoverflow.com/questions/26580723/how-to-scroll-to-the-bottom-of-a-recyclerview-scrolltoposition-doesnt-work

반응형