কীভাবে একটি পুনর্ব্যবহারযোগ্যের নীচে স্ক্রোল করবেন? স্ক্রোলটোপজেশন কাজ করে না


161

ক্রিয়াকলাপটি লোড করার পরে আমি পুনর্ব্যবহারযোগ্য তালিকার নীচে স্ক্রোল করতে চাই।

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(...)রিসাইক্লিউউতে সমর্থিত না হওয়া সম্পর্কে একটি ব্যতিক্রম ছুঁড়ে ফেলেছে এবং conversationView.scrollToPosition(...)কিছুই করার মনে হচ্ছে না।

উপরের কোড ব্লকের পরে আমি যুক্ত করেছি

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

যা কাজ করে না সেখানে 30 টি উপাদান রয়েছে GENERIC_MESSAGE_LIST


আপনি scrollToPositionঅ্যাডাপ্টার সেট করার সাথে সাথে কল করছেন ?
ianhanniballake

@ianhanniballake হ্যাঁ, এটা ঠিক পর এর conversationView.setAdapter(conversationViewAdapter);
ওয়েলেইডওয়ান্ডারার

4
এটি সম্ভবত কারণ আপনি -1 এর পরিবর্তে +1 কল করছেন তাই 5 তম উপাদানটি অবস্থান হতে পারে [4] কারণ এটি 0 থেকে শুরু হয় +1 করা আপনাকে একটি অ্যারেআউটআউটবাউন্ডস দেয় ... এটি কি সেখানে ক্রাশ হয়নি?
আরসিবি

1
সেটডাপ্টারের পরে যুক্ত করুন
ওয়েবভেরিস

উত্তর:


194

কেবলমাত্র সেট করুন setStackFromEnd=trueবা setReverseLayout=trueযাতে এলএলএম শেষ থেকে আইটেমগুলি বিন্যাস করবে।

এই দুটিয়ের মধ্যে পার্থক্যটি এটি setStackFromEnd শেষ উপাদানটি দেখানোর জন্য ভিউ সেট করবে, বিন্যাসের দিকটি একই থাকবে। (সুতরাং, একটি বাম-থেকে-ডান অনুভূমিক পুনর্ব্যবহারযোগ্য ভিউতে, শেষ উপাদানটি প্রদর্শিত হবে এবং বামে স্ক্রোলিং পূর্ববর্তী উপাদানগুলি দেখিয়ে দেবে)

যেখানে setReverseLayoutঅ্যাডাপ্টারের দ্বারা যুক্ত উপাদানগুলির ক্রম পরিবর্তন হবে। লেআউটটি সর্বশেষ উপাদানটি থেকে শুরু হবে যা একটি এলটিআর রিসাইকেলার ভিউতে বাম-সর্বাধিক হবে এবং তারপরে ডানদিকে স্ক্রোলিং করা পূর্ববর্তী উপাদানগুলি প্রদর্শন করবে।

নমুনা:

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

বিশদ জন্য ডকুমেন্টেশন দেখুন ।


132
এটি ব্যবহারকারীর মতো কিছু হতে পারে তবে এটি যে প্রশ্ন করা হয়েছিল তার উত্তর দেয় বলে মনে হয় না।
জোসেফ

6
যদি আপনি উভয়ই স্ট্যাকফ্রমেড = সত্য এবং সেট রিভার্সলআউটআউট = সত্য সেট করেন তবে এটি কার্যকর হয় না। কেউ কি কোনও কাজের কথা জানে?
লুকাকাস কোরিয়া

10
চ্যাট দেখার জন্য রৈখিক লাইনআউট ম্যানেজ.সেটস্ট্যাকফ্রোমেন্ড (সত্য) কাজ করে।
মুনিব মীর্জা

7
এটি প্রশ্নটি মোটেই সমাধান করে না।
অরবিট

1
শুধুমাত্র দৃশ্যটি পূর্ণ না হওয়া পর্যন্ত কাজ করে। এটি স্ক্রোলের উদ্দেশ্যে নয়, কেবল নীচ থেকে স্ট্যাক করুন।
মিগুয়েলস্লভ

376

আমি উত্তরটি খুঁজতে এই পোস্টটির দিকে চেয়ে ছিলাম তবে ... আমি মনে করি এই পোস্টের প্রত্যেকেই আমার মতো একই দৃশ্যের মুখোমুখি scrollToPosition()হয়েছিল : একটি স্পষ্ট কারণের জন্য সম্পূর্ণ উপেক্ষা করা হয়েছিল।

আমি কি ব্যবহার করছিলাম?

recyclerView.scrollToPosition(items.size());

... কি কাজ ?

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

6
recyclerView.scrollToPosition(messages.size()-1);সত্যিই আমার জন্য কাজ করে, আমি কারণ কারণ অবাক।
ইঞ্জিন বাই

25
এটি আমার পক্ষে কাজ করেছে। এটি আসলে বোধগম্য কারণ জাভা তালিকাগুলি শূন্য ভিত্তিক। উদাহরণস্বরূপ [0,1,2] এর আকার 3 থাকে তবে শেষ অবস্থানটি 2 হয় কারণ এটি 0 দিয়ে শুরু হয়
ক্যালভিন

19
এফওয়াইআই, মসৃণ স্ক্রোলের জন্য রয়েছে smoothScrollToPosition(...)
ইভান মরগিলো

5
@ ইভান মরগিলো স্মলস্ক্রোলটোপোজিস্টটি মোটেও কাজ করে না: এস
সিজার্ড

2
@ ইভানমর্গিলো - আপনার উত্তরটি ফলাফল চেয়েছিল এবং আরও মসৃণ = ডি উভয়ই ভাল কাজ করছে বলে মনে হচ্ছে। মনে হচ্ছে পজিশনে স্ক্রোল করা আমার কাছে কিছুটা বগি (আমার
ধারণাটি হ'ল

54

আমি এখানে উত্তর দিতে দেরী জানি, এখনও যদি কেউ জানতে চান তবে সমাধান নীচে রয়েছে

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

8
conversationView.smoothScrollToPosition(conversationView.getAdapter().getItemCount() **-1**);তালিকার অবস্থানগুলি শূন্য-ভিত্তিক হওয়ায় এটি হওয়া উচিত ।
বের্ক

2
শেষ সারিটির উচ্চতা স্ক্রিনের উচ্চতা বেশি হলে এই সাহায্য করবে না।
অনুজ জিন্দাল

এই আমার প্রয়োজন ছিল। যদিও সবকিছু সঠিকভাবে কাজ করতে আমাকে একটি হ্যান্ডলারের পোস্টডেলে মুড়ে ফেলতে হয়েছিল।
মার্ক আলেকজান্ডার

18

পুনর্ব্যবহারযোগ্য পর্যায়ের যে কোনও অবস্থান থেকে নীচে স্ক্রোলডাউন করতে

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

15

বার্তা প্রেরণের পরে এবং সার্ভার থেকে বার্তা পাওয়ার আগে এই কোডটি যুক্ত করুন

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

10

আপনি যখন কল করেন তখন setAdapterতা স্ক্রিনে তাত্ক্ষণিকভাবে সজ্জা দেয় না এবং আইটেমগুলি অবস্থান করে না (যেটি একটি একক বিন্যাস পাস নেয়) সুতরাং আপনার scrollToPosition()কলটিতে কল করার সময় স্ক্রোল করার জন্য কোনও আসল উপাদান নেই।

পরিবর্তে, আপনি একটি ViewTreeObserver.OnGlobalLayoutListener ( addOnGlobalLayoutListner () এর মাধ্যমে নিবন্ধন করা উচিত A থেকে ViewTreeObserverদ্বারা নির্মিত conversationView.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.
  }
});

1
ধন্যবাদ, তবে এটি কাজ করে না। এটি কাজ করা থেকে ঝাঁকুনি থামিয়ে স্ক্রোলিং বিরতি দেয় এবং আপনি যদি টানেন তবে অদ্ভুতভাবে দ্রুত স্ক্রল করে।
ওয়েলেডওয়ান্ডারার

আপনার মতো শ্রোতাদের সরিয়ে দিচ্ছেন না। এটিকে কেবল একবার কল করা উচিত (উপাদানগুলির প্রথম নির্ধারিত হওয়ার পরে ডানদিকে) এবং স্ক্রল করার সময় মোটেও নয়।
ianhanniballake

OnGlobalLayoutListenerআপনি সন্ধান করছেন কারণ সম্ভবত অপসারণ করা হচ্ছে না vto.isAlive()। কারনটা জানার না, কিন্তু ViewTreeObserverকখনও কখনও একটি জন্য পরিবর্তিত হয় Viewতাই পরিবর্তে চেক এর isAliveআপনি ভাল বর্তমান পেতে ViewTreeObserverসঙ্গেconversationView.getViewTreeObserver().removeGlobalOnLayoutListener
দিমিত্রি Zaytsev

@ianhanniballake আমি এই সমস্যাটি সমাধান করার জন্য একটি সম্পাদনা প্রস্তাব করেছি।
সায়েত

6

কোটলিনের জন্য সমাধান :

"রিসাইক্লারভিউ.আডাপ্টার" সেট করার পরে বা "রিসাইক্লারভিউ.এডাপ্টার.নোটেফাই ডেটাসেট চেঞ্জড ()" এর পরে কোডের নীচে প্রয়োগ করুন

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

5

কোটলিনে:

recyclerView.viewTreeObserver.addOnGlobalLayoutListener { scrollToEnd() }

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

হাহ, ধন্যবাদ GlobalLayoutListener! রিফ্যাক্টরিংয়ের পরে আমাকে আপনার পদ্ধতিটি স্ক্রোল করতে ব্যবহার করতে হয়েছিল। শ্রোতাদের স্ট্যাকওভারফ্লো . com/ জিজ্ঞাসাগুলি / ২৮২131313139 / এর মতো অপসারণ করতে ভুলবেন না , বা আপনি পুনর্ব্যবহারযোগ্যভিউ শুরুতে ফিরে স্ক্রোল করবেন না।
কুলমাইন্ড

4
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);

উপরের কোডটি কাজ করে, তবে এটি মসৃণ এবং শীতল নয়।


4

যদি আপনার রিসাইকেলার ভিউয়ের সাথে অ্যাডাপ্টার সংযুক্ত থাকে তবে কেবল এটি করুন।

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


4

রকের উত্তর একটি দুর্দান্ত সাহায্য। আমি এটিতে একটি ছোট ব্লক যুক্ত করতে চাই:

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

4

আমার ক্ষেত্রে যেখানে দৃশ্যের সমান উচ্চতা নেই, লেআউটম্যানেজারে স্ক্রোলটোপজিশন কল করে সত্যিই নীচে স্ক্রোল করতে এবং শেষ আইটেমটি সম্পূর্ণরূপে দেখার জন্য কাজ করেছে:

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

2

এটি আমার পক্ষে পুরোপুরি সূক্ষ্মভাবে কাজ করে:

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

2

রিসাইক্লার ভিউতে প্রবেশের সময় প্রথমবার স্ক্রোল করুন প্রথমবার তারপরে ব্যবহার করুন

linearLayoutManager.scrollToPositionWithOffset(messageHashMap.size()-1

ইতিবাচক মান রেখে স্ক্রোল আপ জন্য ডাউন স্ক্রোল জন্য বিয়োগ করা;

যদি ভিউটি উচ্চতায় খুব বড় হয় তবে স্ক্রোলটোপপজিশনের বিশেষ অফসেটটি উপরে দেখার জন্য ব্যবহার করা হয় তবে আপনি ব্যবহার করুন

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

0

কেবল আয়ানের উত্তরই আমার RecyclerViewস্ক্রোলটিকে একটি নির্দিষ্ট অবস্থানে নিয়ে যেতে সক্ষম হয়েছিল । যাইহোক, RecyclerViewআমি যখন ব্যবহার করতাম তখন এর পরে স্ক্রোল করতে সক্ষম হইনি scrollToPosition()smoothScrollToPosition()কাজ করেছে তবে প্রাথমিক অ্যানিমেশনটি তালিকাটি দীর্ঘ হওয়ার পরে এটি খুব ধীর করেছে। কারণটি ছিল শ্রোতা সরানো হয়নি। আমি বর্তমানটি সরাতে নীচের কোডটি ব্যবহার করেছি ViewTreeObserverএবং এটি কবজ হিসাবে কাজ করেছে।

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

0

এই কোডটি আপনাকে সর্বশেষতম পোস্ট দেবে, আমি মনে করি এই উত্তরটি সহায়ক।

    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);

0

@ গ্যালেক্সের একটি পদ্ধতি চেষ্টা করে রিফ্যাক্টরিং পর্যন্ত এটি কাজ করে। সুতরাং আমি @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/2914140viewTreeObserver.isAliveলাইকের চেক যোগ করতে পারেন ।


0

যদি এগুলির কোনওটিই কাজ না করে,

আপনার ব্যবহার করার চেষ্টা করা উচিত:

ConstraintLayout targetView = (ConstraintLayout) recyclerView.findViewHolderForAdapterPosition(adapter.getItemCount()-1).itemView;
targetView.getParent().requestChildFocus(targetView, targetView);

এটি করে আপনি একটি নির্দিষ্ট কনস্ট্রেন্টলয়েট (বা যা কিছু আছে) প্রদর্শিত হওয়ার জন্য অনুরোধ করছেন। স্ক্রোলটি তাত্ক্ষণিক।

আমি দেখানো কীবোর্ড দিয়েও কাজ করি।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.