アクティビティを読み込んだ後、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でサポートされていないという例外を投げ、そしてconversationView.scrollToPosition(...)
は何もしないようです。
上記のコードブロックの後に、私は追加しました
conversationView.scrollToPosition(GENERIC_MESSAGE_LIST.size() + 1)
これはうまくいきません。 GENERIC_MESSAGE_LIST
には30個の要素があります。
LLMが項目を最後からレイアウトするようにsetStackFromEnd=true
またはsetReverseLayout=true
を設定するだけです。
これら2つの違いは、setStackFromEnd
はビューに最後の要素を表示するように設定し、レイアウトの方向は同じままであるということです。 (したがって、左から右への横方向のリサイクルビューでは、最後の要素が表示され、左にスクロールすると前の要素が表示されます)
setReverseLayout
は、アダプタによって追加された要素の順序を変更します。レイアウトは最後の要素から開始します。最後の要素はLTRリサイクルビューで一番左に表示され、次に右にスクロールすると前の要素が表示されます。
サンプル:
final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
linearLayoutManager.setReverseLayout(true);
_listView.setLayoutManager(linearLayoutManager);
詳しくは documentation を参照してください。
答えを見つけるためにこの記事を見ていましたが...私はこの記事のすべての人が私と同じシナリオに直面していたと思います。明らかな理由で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);
}
});
setAdapter
name__を呼び出しても、すぐにはレイアウトされず、画面上に項目が配置されません(1回のレイアウトパスが必要です)。したがって、scrollToPosition()
呼び出しには、呼び出すときにスクロールする実際の要素はありません。
代わりに、 ViewTreeObserver.OnGlobalLayoutListener を登録する必要があります( addOnGlobalLayoutListner() を使用)。最初のレイアウトパスが終わるまでconversationView.getViewTreeObserver()
を遅らせるscrollToPosition()
)によって作成されたViewTreeObserver
name__から:
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.scrollToPosition(mChatList.size() - 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());
ビューの高さが同じではない私の場合は、LayoutManagerで scrollToPosition を呼び出すと、実際には下にスクロールして最後の項目を完全に見てください。
recycler.getLayoutManager().scrollToPosition(adapter.getItemCount() - 1);
Kotlinの解決策:
"recyclerView.adapter"の設定後または "recyclerView.adapter.notifyDataSetChanged()"の後に、コードの下に適用
recyclerView.scrollToPosition(recyclerView.adapter.itemCount - 1)
Roc answerは大いに役立ちます。小さなブロックを追加したいと思います。
mRecyclerView.scrollToPosition(mAdapter.getItemCount() - 1);
これは私にとっては完全にうまくいきます:
AdapterChart adapterChart = new AdapterChart(getContext(),messageList);
recyclerView.setAdapter(adapterChart);
recyclerView.scrollToPosition(recyclerView.getAdapter().getItemCount()-1);
コトリンでは:
recyclerView.viewTreeObserver.addOnGlobalLayoutListener { scrollToEnd() }
private fun scrollToEnd() =
(adapter.itemCount - 1).takeIf { it > 0 }?.let(recyclerView::smoothScrollToPosition)
@ galex の方法を試してみましたが、リファクタリングまではうまくいきました。そこで、私は @ yanchenko の答えを使い、少し変更しました。おそらくこれは、フラグメントビューが構築された(そしておそらく正しいサイズではなかった)onCreateView()
からスクロールを呼び出したためです。
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)
}
}
})
}
https://stackoverflow.com/a/39001731/291414 のようにviewTreeObserver.isAlive
のチェックを追加することもできます。
このコードは最初にあなたに最新の投稿をするでしょう、私はこの答えが役に立つと思います。
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);
私のRecyclerView
を指定された位置にスクロールさせることができたのは、Ianの答えだけでした。しかし、私がscrollToPosition()
を使用したとき、RecyclerView
はその後スクロールできませんでした。 smoothScrollToPosition()
は動作しましたが、最初のアニメーションではリストが長いときは遅すぎました。その理由はリスナーが削除されなかったことです。私は現在のViewTreeObserver
を削除するために以下のコードを使用しました、そしてそれは魅力として働きました。
mRecyclerView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
mRecyclerView.scrollToPosition(mPosition);
mRecyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
初めてリサイクラービューに入るときにはじめてスクロールしてからlinearLayoutManager.scrollToPositionWithOffset(messageHashMap.size() - 1、上にスクロールするにはマイナスに、正の値に入れる)を使用します);を使用します。
ビューの高さが非常に大きい場合は、scrolltopositionの特定のオフセットがビューの上部に使用されます。
int overallXScroldl = chatMessageBinding.rvChat.computeVerticalScrollOffset();chatMessageBinding.rvChat.smoothScrollBy(0、Math.abs(overallXScroldl));