রিসাইক্লিউউয়ের সাথে অন্তহীন তালিকা কীভাবে প্রয়োগ করা যায়?


346

আমি পরিবর্তন করতে চান ListViewকরতে RecyclerView। আমি ব্যবহার করতে চান onScrollএর OnScrollListenerমধ্যে RecyclerViewএকটি ব্যবহারকারী তালিকার শেষে স্ক্রল যদি নির্ধারণ।

যদি কোনও ব্যবহারকারী তালিকার শেষের দিকে স্ক্রোল করে থাকে তবে আমি কীভাবে জানতে পারি যে আমি একটি আরইএসটি পরিষেবা থেকে নতুন ডেটা আনতে পারি?


এই লিঙ্কে এটা আপনাকে সাহায্য করবে দয়া করে চেক করুন .. stackoverflow.com/questions/26293461/...
সংসদ

32
প্রশ্নটি মনোযোগ দিয়ে পড়ুন! আমি তালিকাভিউ দিয়ে এটি কীভাবে করব তা জানি তবে এটি কীভাবে একটি রিসাইক্ল ভিউ দিয়ে প্রয়োগ করা যায়
এরদনা

অ্যান্ড্রয়েড.ডাটাতে লোডমোর অনস্ক্রোলিসটনার কীভাবে প্রয়োগ করা যায় তা বিদ্যমান ডেটাতে লোড করা হয় তবে আপডেট হয় দয়া করে আমাকে সহায়তা করুন
হর্ষ

2
আপনি এই গ্রন্থাগারটি ব্যবহার করতে পারেন: github.com/rockerhieu/rv-adapter-endless । এটা তোলে ধারণার উপর ভিত্তি করে তৈরি cwac-endlessজন্য ListView
হাইউ রকার

উত্তর:


422

@ কুশলকে ধন্যবাদ এবং আমি এটি এটি বাস্তবায়ন করেছি

private boolean loading = true;
int pastVisiblesItems, visibleItemCount, totalItemCount;

mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        if (dy > 0) { //check for scroll down
            visibleItemCount = mLayoutManager.getChildCount();
            totalItemCount = mLayoutManager.getItemCount();
            pastVisiblesItems = mLayoutManager.findFirstVisibleItemPosition();

            if (loading) {
                if ((visibleItemCount + pastVisiblesItems) >= totalItemCount) {
                    loading = false;
                    Log.v("...", "Last Item Wow !");
                    // Do pagination.. i.e. fetch new data
                }
            }
        }
    }
});

যুক্ত করতে ভুলবেন না

LinearLayoutManager mLayoutManager;
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);

11
আমি কী করতে পারিStaggeredGridLayoutManager
প্রতীক বুটানি

16
কী সম্পর্কেmLayoutManager.findLastCompletelyVisibleItemPosition()==mLayoutManager.getItemCount()-1
লাটপু

45
যারা findFirstVisibleItemPosition()সমাধান করেনি তাদের সকলের জন্য আপনাকে পরিবর্তন RecyclerView.LayoutManagerকরতে হবেLinearLayoutManager
আমর মোহাম্মদ

26
loading = trueআবার বানানোর শর্ত কোথায় ?
ভড়গব

10
অংশ loading = trueপরে যোগ করতে ভুলবেন না //Do pagination। অন্যথায় এই কোডটি একবারে চলবে এবং আপনি আরও আইটেম লোড করতে পারবেন না।
শায়শব জোগানী

165

এই পরিবর্তনশীল করুন।

private int previousTotal = 0;
private boolean loading = true;
private int visibleThreshold = 5;
int firstVisibleItem, visibleItemCount, totalItemCount;

পুনর্ব্যবহারযোগ্য দর্শনের জন্য স্ক্রোল সেট করুন।

mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {

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

        visibleItemCount = mRecyclerView.getChildCount();
        totalItemCount = mLayoutManager.getItemCount();
        firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition();

        if (loading) {
            if (totalItemCount > previousTotal) {
                loading = false;
                previousTotal = totalItemCount;
            }
        }
        if (!loading && (totalItemCount - visibleItemCount) 
            <= (firstVisibleItem + visibleThreshold)) {
            // End has been reached

            Log.i("Yaeye!", "end called");

            // Do something

            loading = true;
        }
    }
});

দ্রষ্টব্য: আপনি LinearLayoutManagerলেআউট ম্যানেজার হিসাবে ব্যবহার করছেন তা নিশ্চিত করুন RecyclerView

LinearLayoutManager mLayoutManager;
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);

এবং একটি গ্রিড জন্য

GridLayoutManager mLayoutManager;
mLayoutManager = new GridLayoutManager(getActivity(), spanCount);
mRecyclerView.setLayoutManager(mLayoutManager);

আপনার অন্তহীন স্ক্রোলগুলি সাথে মজা করুন !! ^। ^

আপডেট: এমআরসিক্র্লারভিউ। setOnScrolListener () কেবলমাত্র এর সাথে প্রতিস্থাপন করুন mRecyclerView.addOnScrollListener()এবং সতর্কতাটি চলে যাবে! আপনি এই এসও প্রশ্নটি থেকে আরও পড়তে পারেন ।

যেহেতু অ্যান্ড্রয়েড এখন আনুষ্ঠানিকভাবে কোটলিনকে সমর্থন করে, তাই এখানে তার আপডেট রয়েছে -

অনস্ক্রোললিস্টনার করুন

class OnScrollListener(val layoutManager: LinearLayoutManager, val adapter: RecyclerView.Adapter<RecyclerAdapter.ViewHolder>, val dataList: MutableList<Int>) : RecyclerView.OnScrollListener() {
    var previousTotal = 0
    var loading = true
    val visibleThreshold = 10
    var firstVisibleItem = 0
    var visibleItemCount = 0
    var totalItemCount = 0

    override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
        super.onScrolled(recyclerView, dx, dy)

        visibleItemCount = recyclerView.childCount
        totalItemCount = layoutManager.itemCount
        firstVisibleItem = layoutManager.findFirstVisibleItemPosition()

        if (loading) {
            if (totalItemCount > previousTotal) {
                loading = false
                previousTotal = totalItemCount
            }
        }

        if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) {
            val initialSize = dataList.size
            updateDataList(dataList)
            val updatedSize = dataList.size
            recyclerView.post { adapter.notifyItemRangeInserted(initialSize, updatedSize) }
            loading = true
        }
    }
}

এবং এটি আপনার রিসাইক্লার ভিউতে এটি যুক্ত করুন

recyclerView.addOnScrollListener(OnScrollListener(layoutManager, adapter, dataList))

একটি সম্পূর্ণ কোড উদাহরণের জন্য, এই গিথুব রেপো নির্দ্বিধায় নির্দ্বিধায় ।


14
গ্রিডলাউটম্যানেজারের সাথে এই সমাধানটি কীভাবে প্রয়োগ করা যায় তার কোনও ধারণা? যেহেতু findFirstVisibleItemPosition()পদ্ধতিটি কেবল লিনিয়ারলআউটআউট ম্যানেজারের সাথে উপলভ্য, তাই কীভাবে এটি কাজ করা যায় তা আমি বুঝতে পারি না।
ম্যাথিউমারি

1
অতিরিক্ত তথ্য: এই ক্ষেত্রে, ব্যবহার visibleItemCount = mLayoutManager.getChildCount();আচরণ করবে একই ব্যবহার visibleItemCount = mRecyclerView.getChildCount();
জিং লি

3
OnScrolled () পদ্ধতির পরিবর্তে কোডটি oncrolStateChanged () পদ্ধতিতে রাখুন।
অনিরুধ

2
@ toobsco42 আপনি এটি ব্যবহার করতে পারেন:int[] firstVisibleItemPositions = new int[yourNumberOfColumns]; pastVisiblesItems = layoutManager.findFirstVisibleItemPositions(firstVisibleItemPositions)[0];
ম্যাথিউমারি

1
এই সন্ধানটি কী ফার্স্টভিজিবল আইটেম পজিশন () সমাধান করা হয়নি
সুরেশ শর্মা

72

যারা কেবল শেষ আইটেমটি সম্পূর্ণ দেখানো হয় তখনই বিজ্ঞপ্তি পেতে চান, আপনি ব্যবহার করতে পারেন View.canScrollVertically()

আমার বাস্তবায়ন এখানে:

public abstract class OnVerticalScrollListener
        extends RecyclerView.OnScrollListener {

    @Override
    public final void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        if (!recyclerView.canScrollVertically(-1)) {
            onScrolledToTop();
        } else if (!recyclerView.canScrollVertically(1)) {
            onScrolledToBottom();
        } else if (dy < 0) {
            onScrolledUp();
        } else if (dy > 0) {
            onScrolledDown();
        }
    }

    public void onScrolledUp() {}

    public void onScrolledDown() {}

    public void onScrolledToTop() {}

    public void onScrolledToBottom() {}
}

দ্রষ্টব্য: আপনি recyclerView.getLayoutManager().canScrollVertically()<< 14 টি API সমর্থন করতে চাইলে আপনি ব্যবহার করতে পারেন ।


এটি একটি দুর্দান্ত এবং সাধারণ উত্তর! ধন্যবাদ!
Andranik

2
একই ধরণের সমাধানটি টানতে রিফ্রেশ করার জন্য চেক করে ব্যবহার করা যেতে পারে! রিসাইক্লারভিউ।
লর্ড পার্সলে

সেখানে সেরা সমাধান। ধন্যবাদ দোস্ত!
অ্যাংমার

1
@ লর্ডপার্সলে ধন্যবাদ, আপডেট হয়েছে। রিফ্রেশ করার জন্য টানতে সোয়াইপরিফ্রেশলআউট চেক করার উপায় এটি।
হাই ঝাং

1
@ এপিকপান্ডাফোরস আপনি যদি ব্যবহার করছেন তবে RecyclerViewআপনি আবার ভাগ্যবান হবেন, কারণ View.canScrollVertically()সম্পর্কিত পদ্ধতিগুলি সুরক্ষিত না হয়ে পাবলিক চিহ্নিত করা হওয়ায় আপনি কেবল একটি স্থির অনুলিপি তৈরি করতে পারেন RecyclerView। আপনি চাইলে RecyclerViewপুনরায় বাস্তবায়নের ক্ষেত্রেও প্রসারিত canScrollVertically()করতে পারেন। তৃতীয় এবং সহজ উপায় হল কল করা recyclerView.getLayoutManager().canScrollVertically()। আমার উত্তরে সম্পাদিত।
হাই ঝাং

67

এখানে অন্য পদ্ধতির। এটি যে কোনও লেআউট ম্যানেজারের সাথে কাজ করবে।

  1. অ্যাডাপ্টার বর্গ বিমূর্ত করুন
  2. তারপরে অ্যাডাপ্টার শ্রেণিতে একটি বিমূর্ত পদ্ধতি তৈরি করুন (উদাঃ লোড ())
  3. ইন onBindViewHolder অবস্থান পরীক্ষা করে গত এবং কল লোড ()
  4. আপনার ক্রিয়াকলাপ বা খণ্ডে অ্যাডাপ্টার অবজেক্ট তৈরি করার সময় লোড () ফাংশনটিকে ওভাররাইড করুন।
  5. অতিরিক্ত লোড ফাংশনে আপনার লোডমোর কলটি প্রয়োগ করুন implement

বিস্তারিত বোঝার জন্য আমি একটি ব্লগ পোস্ট লিখেছিলাম এবং উদাহরণস্বরূপ প্রকল্পটি এটি এখানে পান http://sab99r.com/blog/recyclerview-endless-load-more/

MyAdapter.java

public abstract class MyAdapter extends RecyclerView.Adapter<ViewHolder>{

        @Override
        public void onBindViewHolder(ViewHolder holder, int position) {
            //check for last item
            if ((position >= getItemCount() - 1))
                load();
        }

        public abstract void load();
}

MyActivity.java

public class MainActivity extends AppCompatActivity {
    List<Items> items;
    MyAdapter adapter;

   @Override
    protected void onCreate(Bundle savedInstanceState) {
    ...
    adapter=new MyAdapter(items){
            @Override
            public void load() {
                //implement your load more here
                Item lastItem=items.get(items.size()-1);
                loadMore();
            }
        };
   }
}

3
সমাধানটির মতো আপনাকে নিজের অ্যাডাপ্টারটি বিমূর্ত করতে হবে না, পরিবর্তে আপনি আপনার অ্যাডাপ্টারে একটি ইন্টারফেস তৈরি করতে পারবেন এবং আপনার ক্রিয়াকলাপটিকে নমনীয় এবং মার্জিত রাখার মাধ্যমে এটি প্রয়োগ করতে পারবেন, যেমন: আইটেমডিসপ্লেলিস্টার => অন আইটেম ডিসপ্লাইড (ইন পজিশন)। এইভাবে আপনি যে কোনও পজিশনে লোড করতে পারবেন: এন, এন -1, এন -2 এ ..
সমীর

1
@ এমসিওয়াইজে একটি বুলিয়ান সমাপ্ত করুন = মিথ্যা; আপনি যখন শেষের দিকে পৌঁছেছেন তখন শেষ করুন = সত্য করুন .. যদি বর্তমান অবস্থার পরিবর্তন করুন তবে ((অবস্থান> = getItemCount () - 1) এবং& (! সমাপ্ত))
সাবীর মোহাম্মদ

1
এটি সঠিক উত্তর হিসাবে চিহ্নিত করা উচিত। এটি মার্জিত এবং সহজ।
গ্রেগ এনিস

2
প্রথম সমাধানটির জনপ্রিয়তার অধীনে উত্তম সমাধানের একটি ভাল উদাহরণ। খুব প্রায়শই, শেষ সারিটি পৃথক ভিউ টাইপের সাথে আবদ্ধ হবে যা "লোডিং ..." ব্যানার হিসাবে কাজ করে। যখন এই ভিউ টাইপটি একটি বাইন্ড কল আসে, এটি একটি কলব্যাক সেট আপ করবে যা আরও ডেটা উপলভ্য হলে ডেটা পরিবর্তন বিজ্ঞপ্তি ট্রিগার করে। স্ক্রোল শ্রোতাদের জড়িত করার স্বীকৃত উত্তর অপ্রয়োজনীয় এবং সম্ভবত অন্যান্য লেআউট প্রকারের জন্য কাজ করে না।
মাইকেল হেজে

3
@ এমসিওয়াই কেবলমাত্র অবিরাম কল করবে যদি ব্যবহারকারী সক্রিয়ভাবে শেষ আইটেমটিতে সরিয়ে স্ক্রোল করে। অনবিন্দ ভিউহোল্ডারটি একবারে একবারে ভিউ স্ক্রিনে প্রবেশ করে এবং নিয়মিত কল করে না it
ডেভিড লিউ

18

আমার উত্তরটি নুরের পরিবর্তিত সংস্করণ। আমি ListViewযেখানে ছিলাম সেখান থেকে চলে গেলাম EndlessScrollListener(যে আপনি খুব সহজেই এসও তে অনেক উত্তর পেতে পারেন) RecyclerViewতাই আমি EndlessRecyclScrollListenerআমার অতীতের শ্রোতাদের সহজেই আপডেট করতে চেয়েছিলাম ।

সুতরাং কোডটি এখানে রয়েছে আশা করি এটি সহায়তা করে:

public abstract class EndlessScrollRecyclListener extends RecyclerView.OnScrollListener
{
    // The total number of items in the dataset after the last load
    private int previousTotalItemCount = 0;
    private boolean loading = true;
    private int visibleThreshold = 5;
    int firstVisibleItem, visibleItemCount, totalItemCount;
    private int startingPageIndex = 0;
    private int currentPage = 0;

    @Override
    public void onScrolled(RecyclerView mRecyclerView, int dx, int dy)
    {
        super.onScrolled(mRecyclerView, dx, dy);
        LinearLayoutManager mLayoutManager = (LinearLayoutManager) mRecyclerView
                .getLayoutManager();

        visibleItemCount = mRecyclerView.getChildCount();
        totalItemCount = mLayoutManager.getItemCount();
        firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition();
        onScroll(firstVisibleItem, visibleItemCount, totalItemCount);
    }

    public void onScroll(int firstVisibleItem, int visibleItemCount, int totalItemCount)
    {
        // If the total item count is zero and the previous isn't, assume the
        // list is invalidated and should be reset back to initial state
        if (totalItemCount < previousTotalItemCount)
        {
            this.currentPage = this.startingPageIndex;
            this.previousTotalItemCount = totalItemCount;
            if (totalItemCount == 0)
            {
                this.loading = true;
            }
        }
        // If it’s still loading, we check to see if the dataset count has
        // changed, if so we conclude it has finished loading and update the current page
        // number and total item count.
        if (loading && (totalItemCount > previousTotalItemCount))
        {
            loading = false;
            previousTotalItemCount = totalItemCount;
            currentPage++;
        }

        // If it isn’t currently loading, we check to see if we have breached
        // the visibleThreshold and need to reload more data.
        // If we do need to reload some more data, we execute onLoadMore to fetch the data.
        if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem +
                visibleThreshold))
        {
            onLoadMore(currentPage + 1, totalItemCount);
            loading = true;
        }
    }

    // Defines the process for actually loading more data based on page
    public abstract void onLoadMore(int page, int totalItemsCount);

}

1
আপনার বাস্তবায়নের জন্য লিনিয়ারলিওআউট ম্যানেজারটি ব্যবহার করার জন্য পুনর্ব্যবহারযোগ্য ভিউ প্রয়োজন। খারাপ ধারণা!
ওরি

@ ওরি আপনি দয়া করে ব্যাখ্যা করতে পারেন কেন? ধন্যবাদ!
ফেদেরিকো পঞ্জি

1
আপনার অনস্ক্রোলে আপনি লেআউটম্যানাজারটি পুনর্ব্যবহারযোগ্য থেকে লিনিয়ারলআউটআউট ম্যানেজারে কাস্ট করেছেন। এটি স্ট্যাগগ্রিডগ্রিডলআউট বা অ্যান্থিংয়ের জন্য কাজ করছে না। স্ট্যাগ্রডগ্রিডগ্রিড লেআউটতে ফার্স্টভিজিবল আইটেম পজিশন () নেই।
ওরি

@ ওরি এটি নির্দেশ করার জন্য ধন্যবাদ! তবে আমি মনে করি না যে এটি এতটা খারাপ ধারণা, যেহেতু এটি আমার এবং, অন্যান্য বিষয়গুলির উপর ভিত্তি করে কাজ করেছিল :)
ফেডেরিকো পঞ্জি

10

আমার জন্য, এটি খুব সহজ:

     private boolean mLoading = false;

     mList.setOnScrollListener(new RecyclerView.OnScrollListener() {

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

            int totalItem = mLinearLayoutManager.getItemCount();
            int lastVisibleItem = mLinearLayoutManager.findLastVisibleItemPosition();

            if (!mLoading && lastVisibleItem == totalItem - 1) {
                mLoading = true;
                // Scrolled to bottom. Do something here.
                mLoading = false;
            }
        }
    });

অ্যাসিক্রোনাস জবসের সাথে সাবধানতা অবলম্বন করুন: অ্যাসিঙ্ক্রোনাস কাজ শেষে এম লোডিং অবশ্যই পরিবর্তন করা উচিত। আশা করি এটি সহায়ক হবে!


মূলতঃ আমার নিজের প্রশ্ন করার দিন পরে আমি এই উত্তরটি পেয়েছি। এটি সেরা সমাধান, ইমো।
wsgeorge

দয়া করে লোডমোর পৃষ্ঠা নম্বর অ্যান্ড্রয়েড দিয়ে পুনর্ব্যবহারের জন্য কিছু সমাধান দিন
হর্শা

getWebServiceData (); mStoresAdapterData.setOnLoadMoreListener (new StoreAdapter.OnLoadMoreListener () {@ ওভাররাইড পাবলিক বায়ু onLoadMore () add // নাল যুক্ত করুন, সুতরাং অ্যাডাপ্টারটি ভিউ_টাইপ পরীক্ষা করবে এবং নীচে স্টোরস্টিস্টস্টিস্ট.এলটিএসটিএসটিএসটিএসটিএসটিএসটিএসটিএসটিএসটিএসপিএর স্টোরগুলিতে প্রগতি বার দেখায়; () - 1); ++ পৃষ্ঠা নম্বর; getWebServiceData ();}}); উভয়ই একের পর এক কল করে অবশেষে ২ য় পৃষ্ঠার ডেটা কেবল দৃশ্যমান হয়েছে দয়া করে সহায়তা করুন
হর্ষ

আমি রিসাইক্লার ভিউ পৃষ্ঠাটি অনেক বাস্তবায়নের চেষ্টা করেছি কিন্তু তাদের কেউই কাজ করেনি, এই ব্যতীত আপনারা আমার
উপনীত

9

সর্বাধিক উত্তর অভিমানী হয় RecyclerViewএকটি ব্যবহার LinearLayoutManagerকরুন, অথবা GridLayoutManager, অথবা এমনকি StaggeredGridLayoutManager, অথবা অভিমানী যে স্ক্রলিং উল্লম্ব বা horyzontal, কিন্তু কোন এক একটি একদম জেনেরিক উত্তর পোস্ট করেছে

ViewHolderএর অ্যাডাপ্টার ব্যবহার করা স্পষ্টত কোনও ভাল সমাধান নয়। একটি অ্যাডাপ্টারের কাছে RecyclerViewএটির বেশি ব্যবহার থাকতে পারে। এটি তাদের বিষয়বস্তুগুলিকে "অ্যাডাপ্ট" করে। এটি পুনর্ব্যবহারযোগ্য ভিউ হওয়া উচিত (যা বর্তমানে এক শ্রেণীর যা ব্যবহারকারীকে প্রদর্শিত হবে তার জন্য দায়বদ্ধ, এবং অ্যাডাপ্টার যা কেবলমাত্র সামগ্রী সরবরাহের জন্য দায়বদ্ধ নয় RecyclerView) যা আপনার সিস্টেমকে অবহিত করতে হবে যে আরও আইটেমের প্রয়োজন বোঝা).

এখানে আমার সমাধানটি রয়েছে, রিসাইক্লার ভিউ (রিসাইরভিউ.লায়আউটম্যানেজার এবং রিসিকারভিউ.এডাপ্টার) এর বিমূর্ত শ্রেণিবদ্ধতা ব্যতীত অন্য কিছুই ব্যবহার করে:

/**
 * Listener to callback when the last item of the adpater is visible to the user.
 * It should then be the time to load more items.
 **/
public abstract class LastItemListener extends RecyclerView.OnScrollListener {

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

      // init
      RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
      RecyclerView.Adapter adapter = recyclerView.getAdapter();

      if (layoutManager.getChildCount() > 0) {
        // Calculations..
        int indexOfLastItemViewVisible = layoutManager.getChildCount() -1;
        View lastItemViewVisible = layoutManager.getChildAt(indexOfLastItemViewVisible);
        int adapterPosition = layoutManager.getPosition(lastItemViewVisible);
        boolean isLastItemVisible = (adapterPosition == adapter.getItemCount() -1);

        // check
        if (isLastItemVisible)
          onLastItemVisible(); // callback
     }
   }

   /**
    * Here you should load more items because user is seeing the last item of the list.
    * Advice: you should add a bollean value to the class
    * so that the method {@link #onLastItemVisible()} will be triggered only once
    * and not every time the user touch the screen ;)
    **/
   public abstract void onLastItemVisible();

}


// --- Exemple of use ---

myRecyclerView.setOnScrollListener(new LastItemListener() {
    public void onLastItemVisible() {
         // start to load more items here.
    }
}

1
আপনার উত্তরটি সঠিক এবং এটি LayoutManagersকেবল একটি মুহুর্তের জন্য সকলের জন্য কাজ করেছে : আপনার গণনার কোডটিকে অন্য স্ক্রোললিস্টনার পদ্ধতিতে সরান - onScrollStateChangedপরিবর্তে এটিকে সরান onScrolled। এবং onScrollStateChangedকেবল চেক ইন:if(newState == RecyclerView.SCROLL_STATE_IDLE) { // calculation code }
ট্রান্সার

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

6

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

final LinearLayoutManager layoutManager = new LinearLayoutManager(context);
feedsRecyclerView.setLayoutManager(layoutManager);

feedsRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);

        if (dy > 0) {   
            if ((layoutManager.getChildCount() + layoutManager.findFirstVisibleItemPosition()) >= layoutManager.getItemCount()) {
                Log.d("TAG", "End of list");
                //loadMore();
            }
        }
    }
});

1
কখনও কখনও আমার লোডমোর () পদ্ধতিটি তিনবার অনস্ক্রোলড () এ বলা হয়, কেন এটি তিনবার বলা হয় এবং কীভাবে একাধিকবার কল করা বন্ধ করা যায় সে সম্পর্কে কোনও ধারণা।
ved

dy> 0 সর্বদা মিথ্যা
দুষ্যন্ত সুথার

@ved এর কারণ হচ্ছে যে স্ক্রোলিংয়ের 3 টি স্থিতি রয়েছে: স্ক্রোলিং, স্ক্রোলড, অলস। আপনি উপযুক্ত চয়ন করুন।
TheRealChx101

5

যদিও প্রশ্নের অনেকগুলি উত্তর রয়েছে তবে আমি অন্তহীন তালিকার দৃষ্টিভঙ্গি তৈরির অভিজ্ঞতাটি আমাদের ভাগ করে নিতে চাই। আমরা সম্প্রতি কাস্টম ক্যারোসেল লেআউটম্যানাজার বাস্তবায়ন করেছি যা তালিকায় অসীম পাশাপাশি কিছু নির্দিষ্ট বিন্দু পর্যন্ত স্ক্রোল করে চক্রটিতে কাজ করতে পারে। এখানে গিটহাব সম্পর্কিত একটি বিশদ বর্ণনা রয়েছে

আমি আপনাকে কাস্টম লেআউট ম্যানেজারগুলি তৈরি করার বিষয়ে সংক্ষিপ্ত তবে মূল্যবান প্রস্তাবনাগুলি সহ এই নিবন্ধটি একবার দেখে নিন: http://cases.azoft.com/create-custom-layoutmanager-android/


5

কোটলিনের এক্সটেনশন ফাংশনগুলির শক্তি সহ, কোডটি আরও অনেক মার্জিত দেখতে পারে। এটি আপনি যে কোনও জায়গায় রেখে দিন (আমার কাছে এটি একটি এক্সটেনশনফিউশনস.কেটি ফাইলের মধ্যে রয়েছে):

/**
 * WARNING: This assumes the layout manager is a LinearLayoutManager
 */
fun RecyclerView.addOnScrolledToEnd(onScrolledToEnd: () -> Unit){

    this.addOnScrollListener(object: RecyclerView.OnScrollListener(){

        private val VISIBLE_THRESHOLD = 5

        private var loading = true
        private var previousTotal = 0

        override fun onScrollStateChanged(recyclerView: RecyclerView,
                                          newState: Int) {

            with(layoutManager as LinearLayoutManager){

                val visibleItemCount = childCount
                val totalItemCount = itemCount
                val firstVisibleItem = findFirstVisibleItemPosition()

                if (loading && totalItemCount > previousTotal){

                    loading = false
                    previousTotal = totalItemCount
                }

                if(!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)){

                    onScrolledToEnd()
                    loading = true
                }
            }
        }
    })
}

এবং তারপরে এটি ব্যবহার করুন:

youRecyclerView.addOnScrolledToEnd {
    //What you want to do once the end is reached
}

এই সমাধানটি কুশল শর্মার উত্তরের ভিত্তিতে তৈরি। তবে এটি কিছুটা ভাল কারণ:

  1. এটি এর onScrollStateChangedপরিবর্তে ব্যবহার করে onScroll। এটি আরও ভাল কারণ onScrollপ্রতিবারই রিসাইক্লিউউয়ে কোনও ধরণের চলাচল করার সময় বলা হয়, যখন onScrollStateChangedকেবল তখনই বলা হয় যখন পুনর্ব্যবহারযোগ্য দর্শনটি পরিবর্তন করা হয়। ব্যবহার করা onScrollStateChangedআপনাকে সিপিইউ সময় এবং এর ফলে ব্যাটারি সাশ্রয় দেয়।
  2. যেহেতু এটি এক্সটেনশন ফাংশন ব্যবহার করে, এটি আপনার যে কোনও পুনর্ব্যবহারযোগ্য ভিউতে ব্যবহৃত হতে পারে। ক্লায়েন্ট কোডটি মাত্র 1 লাইন।

আমি যখন SwipeRefreshLayout's setOnRefreshListener the addOnScrolledToEnd is not working ব্যক্তিগত অভ্যন্তরীণ শ্রেণিটি পুল টিটোরআরফ্রেশ পুলটি করলাম: সোয়াইপ রিফ্রেশলআউটআউটআরআরফ্রিশলাইস্টনার {ওভাররাইড মজুরআরফ্র্যাশ () b পিবিভিউমোর !!! দৃশ্যমানতা = দেখুন.জোন পৃষ্ঠা পাতা, গণনা 0 কোর্সলিস্টিস্টিকেল () এখানে এসিঙ্ক্টাস্কিংকে এখানে কল করা হয়েছে .স্রলনোমাইজেশান.প্রজ্যতদ্বৈতদ্বৈপজিক্রেশকটিআউটলাইটআউটআউটআউটআল্টআউটআউটআউট! নতুন প্রকারভেজাআউটআউটআউট! ! .আইস রিফ্রেশিং = ভুয়া} ave
নবীন কুমার এম

5

আমি এটি সহজ এবং সংক্ষিপ্তভাবে এটি করি:

    recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener()
    {
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy)
        {
            if(!recyclerView.canScrollVertically(1) && dy != 0)
            {
                // Load more results here

            }
        }
    });

3

ঠিক আছে, আমি রিসাইক্লারভিউ.এডাপ্টারের অনবিন্দভিউহোল্ডার পদ্ধতিটি ব্যবহার করে এটি করেছি

নাটক:

public interface OnViewHolderListener {
    void onRequestedLastItem();
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {

    ...

    if (position == getItemCount() - 1) onViewHolderListener.onRequestedLastItem();
}

খণ্ড (বা ক্রিয়াকলাপ) :

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    contentView = inflater.inflate(R.layout.comments_list, container, false);
    recyclerView = (RecyclerView) mContentView.findViewById(R.id.my_recycler_view);
    adapter = new Adapter();
    recyclerView.setAdapter(adapter);

    ...

    adapter.setOnViewHolderListener(new Adapter.OnViewHolderListener() {
        @Override
        public void onRequestedLastItem() {
            //TODO fetch new data from webservice
        }
    });
    return contentView;
}

1
অনবিন্দের উপর নির্ভর করা খুব ভাল ধারণা নয়। পুনর্ব্যবহারযোগ্য ভিউ ক্যাশে ভিউগুলি করে + কিছু লেআউট ম্যানেজারের জিনিসগুলি প্রাক-ক্যাশে করার উপায় রয়েছে। আমি একটি স্ক্রোল শ্রোতা সেট করার পরামর্শ দিচ্ছি এবং যখন স্ক্রোল শ্রোতা থামে, লেআউট ম্যানেজারের থেকে শেষ দৃশ্যমান আইটেমের অবস্থানটি পান। আপনি যদি ডিফল্ট লেআউট ম্যানেজার ব্যবহার করে থাকেন তবে তাদের সকলের কাছে লাস্টভিজিবল ** পদ্ধতি রয়েছে।
ইজিগিত

@ ইউজিট রিসাইক্লার ভিউ থেকে দূরে জিনিসগুলি চেষ্টা করার চেষ্টা করবে? আপনার যদি 500 টি আইটেম থাকে তবে আমি সত্যিই সন্দেহ করি যে এটি এতদূর পর্যন্ত ক্যাশে হয়ে যাবে (অন্যথায় এটি কেবল পারফরম্যান্সের এক বিশাল অপচয়)। যখন এটি প্রকৃতপক্ষে ক্যাশে করা শুরু করবে (আমরা যখন 480 উপাদান থাকা অবস্থায়ও থাকি) এর অর্থ যে কোনওভাবেই অন্য ব্যাচটি লোড করার সময়।
অ্যালেক্স অরলভ

1
এটি কোনও দূরবর্তী স্থানে মসৃণ স্ক্রোলিং না করে এটি প্রাক-ক্যাচ জিনিসগুলিতে কাজ করে না। সেক্ষেত্রে, এলএলএম (ডিফল্টরূপে) একের পরিবর্তে দুটি পৃষ্ঠাগুলি বিন্যাস করে যাতে এটি লক্ষ্যবস্তুটি খুঁজে পেতে পারে এবং এতে হ্রাস পেতে পারে। এটি ক্যাশে দর্শনগুলি সীমা ছাড়িয়ে যায়। ডিফল্টরূপে, এই ক্যাশের আকার 2 এবং সেটআইটেমক্যাশ সাইজের মাধ্যমে কনফিগার করা যায়।
ইজিগিত

1
@ আইজিট কেবল সমস্যার মধ্য দিয়ে ভাবছেন আমি দেখি না যে এখানে ক্যাশে কীভাবে কোনও সমস্যা উপস্থাপন করতে পারে; "শেষ" আইটেমগুলি যেভাবেই আবদ্ধ করা হয় কেবলমাত্র আমরা তাতে আগ্রহী! যখন লেআউট ম্যানেজার ইতিমধ্যে আবদ্ধ ছিল এমন ক্যাশেড ভিউ পুনরায় ব্যবহার করে অনবিন্দভিউহোল্ডারের কাছে কল মিস করা কেবল তখনই সমস্যা নয় যখন আমরা তালিকার শেষে আরও ডেটাতে পেজিংয়ে আগ্রহী interesting সঠিক?
গ্রেগ এনিস

2
আমার ফ্লেক্সিবলএডাপ্টার লাইব্রেরিতে আমি কলটির সাথে অন্তহীন স্ক্রোলটি গ্রহণ করা বেছে নিয়েছিলাম onBindViewHolder(), এটি একটি কবজির মতো কাজ করে। বাস্তবায়নটি স্ক্রোল শ্রোতার তুলনায় খুব ছোট এবং এটি ব্যবহার করা সহজ।
ডেভিডাস

3

লোডিং ইভেন্টটি সনাক্ত করার আমার উপায়টি স্ক্রোলিং সনাক্তকরণ নয়, তবে শেষের ভিউটি সংযুক্ত ছিল কিনা তা শোনার জন্য। যদি সর্বশেষ ভিউটি সংযুক্ত থাকে, তবে আমি আরও লিখিত সামগ্রী লোড করার সময় হিসাবে বিবেচনা করি।

class MyListener implements RecyclerView.OnChildAttachStateChangeListener {
    RecyclerView mRecyclerView;

    MyListener(RecyclerView view) {
        mRecyclerView = view;
    }

    @Override
    public void onChildViewAttachedToWindow(View view) {

    RecyclerView.Adapter adapter = mRecyclerView.getAdapter();
    RecyclerView.LayoutManager mgr = mRecyclerView.getLayoutManager();
    int adapterPosition = mgr.getPosition(view);

    if (adapterPosition == adapter.getItemCount() - 1) {
        // last view was attached
        loadMoreContent();
    }

    @Override
    public void onChildViewDetachedFromWindow(View view) {}
}

2

আমি ব্যবহৃত LayoutManager(যেমন LinearLayoutManager) এবং ওভাররাইড scrollVerticallyBy()পদ্ধতি প্রসারিত করার চেষ্টা করব । প্রথমত, আমি প্রথমে কল করব superএবং তারপরে প্রত্যাশিত পূর্ণসংখ্যার মানটি পরীক্ষা করব। মানটি যদি সমান হয় 0তবে নীচে বা শীর্ষ সীমানায় পৌঁছে যায়। তারপরে আমি findLastVisibleItemPosition()কোন সীমান্তে পৌঁছেছে তা অনুসন্ধান করার জন্য পদ্ধতিটি ব্যবহার করব এবং প্রয়োজনে আরও ডেটা লোড করব। শুধু একটি ধারণা।

এছাড়াও, আপনি সেই পদ্ধতিটি থেকে ওভারসক্রোলকে অনুমতি প্রদান করে এবং "লোডিং" সূচক দেখিয়েও আপনার মানটি ফিরিয়ে দিতে পারেন।


2
 recyclerList.setOnScrollListener(new RecyclerView.OnScrollListener() 
            {
                @Override
                public void onScrolled(RecyclerView recyclerView, int dx,int dy)
                {
                    super.onScrolled(recyclerView, dx, dy); 
                }

                @Override
                public void onScrollStateChanged(RecyclerView recyclerView,int newState) 
                {
                    int totalItemCount = layoutManager.getItemCount();
                    int lastVisibleItem = layoutManager.findLastVisibleItemPosition();

                    if (totalItemCount> 1) 
                    {
                        if (lastVisibleItem >= totalItemCount - 1) 
                        {
                            // End has been reached
                            // do something 
                        }
                    }          
                }
            });  

1
onScrollStateChanged()কাজ করবে না যেহেতু কেবল তখনই বলা হবে যখন আপনি স্ক্রোলের অবস্থা পরিবর্তন করবেন এবং আপনি যখন স্ক্রল করছেন তখন না। আপনার অবশ্যই onScrolled()পদ্ধতিটি ব্যবহার করা উচিত ।
mradzinski

2

আমি onBindViewHolderআমার RecyclerView.Adapterক্লাসের পদ্ধতিতে এই যুক্তিটি ব্যবহার করে অসীম স্ক্রোলিং ধরণের বাস্তবায়ন অর্জন করেছি ।

    if (position == mItems.size() - 1 && mCurrentPage <= mTotalPageCount) {
        if (mCurrentPage == mTotalPageCount) {
            mLoadImagesListener.noMorePages();
        } else {
            int newPage = mCurrentPage + 1;
            mLoadImagesListener.loadPage(newPage);
        }
    }

এই কোডটির সাথে যখন রিসাইক্লারভিউ শেষ আইটেমটি পায়, এটি বর্তমান পৃষ্ঠা এবং কলব্যাকগুলিকে একটি ইন্টারফেসে বাড়িয়ে তোলে যা এপিআই থেকে আরও ডেটা লোড করার জন্য এবং অ্যাডাপ্টারে নতুন ফলাফল যুক্ত করার জন্য দায়ী।

আমি আরও সম্পূর্ণ উদাহরণ পোস্ট করতে পারি যদি এটি পরিষ্কার না হয়?


আমি জানি এই পোস্টটি সত্যিই পুরানো, তবে আমি কিছুটা নতুন হয়ে গেছি এবং আপনি কী তুলনা করছেন ভেরিয়েবলগুলি পাবেন তা জানেন না। এমকোয়ারেন্টপেজ এবং এমটোটেলপেজকাউন্টগুলি আমি অনুমান করি এমন আপনার ডেটা সেটটিকে রেফার করছে, এবং এমআইটেমগুলি তালিকা আইটেমগুলির অ্যারেলিস্ট, তবে আমি কীভাবে অবস্থানটি পাই?
বুলিয়ানচিজ

আপনি দেখতে পাচ্ছেন যে আমি কীভাবে আমার পুনর্ব্যবহারযোগ্য ভিউ.এডাপ্টারটি
স্পিডিএনমডস

2

যে সকল লোকেরা এখানে স্ট্যাজার্ডগ্রিডগ্রিডলআউটম্যানেজার ব্যবহার করেন তাদের জন্য আমার বাস্তবায়ন এটি আমার পক্ষে কাজ করে।

 private class ScrollListener extends RecyclerView.OnScrollListener {
    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

        firstVivisibleItems = mLayoutManager.findFirstVisibleItemPositions(firstVivisibleItems);

        if(!recyclerView.canScrollVertically(1) && firstVivisibleItems[0]!=0) {
            loadMoreImages();
        }

    }

    private boolean loadMoreImages(){
        Log.d("myTag", "LAST-------HERE------");
        return true;
    }
}

@ সুদীশমোহন এখানে পূর্ণাঙ্গ শ্রেণি, এটি ছোট) আমার প্রকল্পে আমি গতিশীলভাবে স্প্যান গণনা পরিবর্তন করি এবং এটি 1 এবং 2 স্প্যানের জন্য কাজ করবে
ডেনিস জিনকভস্কি

রিসাইক্লারভিউ.ক্যানস্ক্রোল ভার্টিক্যালি (১) এটি করবে তবে এটির জন্য এপিআই 14 দরকার ::(
সুধীশ মোহন

2

এই নামী প্যাগিনেটের জন্য লাইব্রেরি ব্যবহারের সহজ উপায় রয়েছে । লিস্টভিউ এবং রিসাইক্লারভিউ উভয়কেই সমর্থন করে (লিনিয়ারলআউট, গ্রিডলাউট এবং স্ট্যাগার্ডেড গ্রিডলআউট)।

গিথুবের প্রকল্পের লিঙ্কটি এখানে


2
  1. একটি বিমূর্ত শ্রেণি তৈরি করুন এবং পুনর্ব্যবহারযোগ্য ভিউ.অনস্ক্রোললিস্টনার প্রসারিত করুন

    public abstract class EndlessRecyclerOnScrollListener extends RecyclerView.OnScrollListener {
    private int previousTotal = 0;
    private boolean loading = true;
    private int visibleThreshold;
    private int firstVisibleItem, visibleItemCount, totalItemCount;
    private RecyclerView.LayoutManager layoutManager;
    
    public EndlessRecyclerOnScrollListener(RecyclerView.LayoutManager layoutManager, int visibleThreshold) {
    this.layoutManager = layoutManager; this.visibleThreshold = visibleThreshold;
    }
    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
    super.onScrolled(recyclerView, dx, dy);
    
    visibleItemCount = recyclerView.getChildCount();
    totalItemCount = layoutManager.getItemCount();
    firstVisibleItem = ((LinearLayoutManager)layoutManager).findFirstVisibleItemPosition();
    
    if (loading) {
        if (totalItemCount > previousTotal) {
            loading = false;
            previousTotal = totalItemCount;
        }
    }
    if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) {
        onLoadMore();
        loading = true;
    }
      }
    
    public abstract void onLoadMore();}
  2. ক্রিয়াকলাপে (বা টুকরো টুকরো) রিসাইকেলার ভিউতে অ্যাডঅনস্ক্রোললিস্টনার যুক্ত করুন

    LinearLayoutManager mLayoutManager = new LinearLayoutManager(this);
    recyclerView.setLayoutManager(mLayoutManager);
    recyclerView.addOnScrollListener(new EndlessRecyclerOnScrollListener(mLayoutManager, 3) {
        @Override
        public void onLoadMore() {
            //TODO
            ...
        }
    });

1

আমার কাছে কীভাবে একটি পুনর্ব্যবহারযোগ্য ভিউতে প্যাগেট করা যায় তার একটি বিস্তৃত বিশদ উদাহরণ রয়েছে have একটি উচ্চ স্তরে, আমার কাছে একটি সেট PAGE_SIZE রয়েছে, 30 বলতে দিন। তাই আমি 30 টি আইটেমের জন্য অনুরোধ করছি এবং যদি আমি 30 ফিরে পাই তবে আমি পরবর্তী পৃষ্ঠার জন্য অনুরোধ করব। আমি যদি 30 টিরও কম আইটেম পাই তবে আমি শেষের পৃষ্ঠায় পৌঁছে গেছে তা বোঝাতে একটি পরিবর্তনশীলটিকে পতাকাঙ্কিত করি এবং তারপরে আমি আরও পৃষ্ঠাগুলির জন্য অনুরোধ করা বন্ধ করি। এটি পরীক্ষা করে দেখুন এবং আপনার কী মনে হয় তা আমাকে জানান।

https://medium.com/@etiennelawlor/pagination-with-recyclerview-1cb7e66a502b


1

ওয়েবটিতে AsyncListUtil ব্যবহার করে আমার সমাধানটি এখানে বলেছে: নোট করুন যে এই শ্রেণিটি ডেটা লোড করার জন্য একটি একক থ্রেড ব্যবহার করে, তাই এটি মাধ্যমিক স্টোরেজ যেমন ডিস্কের থেকে ডেটা লোড করার উপযুক্ত, তবে নেটওয়ার্ক থেকে নয়। তবে আমি ডেটা পড়তে ও সূক্ষ্মভাবে কাজ করতে ওডাটা ব্যবহার করছি। আমি উদাহরণস্বরূপ ডেটা সত্তা এবং নেটওয়ার্ক পদ্ধতিগুলি মিস করি। আমি কেবল উদাহরণ অ্যাডাপ্টার অন্তর্ভুক্ত।

public class AsyncPlatoAdapter extends RecyclerView.Adapter {

    private final AsyncPlatoListUtil mAsyncListUtil;
    private final MainActivity mActivity;
    private final RecyclerView mRecyclerView;
    private final String mFilter;
    private final String mOrderby;
    private final String mExpand;

    public AsyncPlatoAdapter(String filter, String orderby, String expand, RecyclerView recyclerView, MainActivity activity) {
        mFilter = filter;
        mOrderby = orderby;
        mExpand = expand;
        mRecyclerView = recyclerView;
        mActivity = activity;
        mAsyncListUtil = new AsyncPlatoListUtil();

    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext()).
                inflate(R.layout.plato_cardview, parent, false);

        // Create a ViewHolder to find and hold these view references, and
        // register OnClick with the view holder:
        return new PlatoViewHolderAsync(itemView, this);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        final Plato item = mAsyncListUtil.getItem(position);
        PlatoViewHolderAsync vh = (PlatoViewHolderAsync) holder;
        if (item != null) {
            Integer imagen_id = item.Imagen_Id.get();
            vh.getBinding().setVariable(BR.plato, item);
            vh.getBinding().executePendingBindings();
            vh.getImage().setVisibility(View.VISIBLE);
            vh.getProgress().setVisibility(View.GONE);
            String cacheName = null;
            String urlString = null;
            if (imagen_id != null) {
                cacheName = String.format("imagenes/imagen/%d", imagen_id);
                urlString = String.format("%s/menusapi/%s", MainActivity.ROOTPATH, cacheName);
            }
            ImageHelper.downloadBitmap(mActivity, vh.getImage(), vh.getProgress(), urlString, cacheName, position);
        } else {
            vh.getBinding().setVariable(BR.plato, item);
            vh.getBinding().executePendingBindings();
            //show progress while loading.
            vh.getImage().setVisibility(View.GONE);
            vh.getProgress().setVisibility(View.VISIBLE);
        }
    }

    @Override
    public int getItemCount() {
        return mAsyncListUtil.getItemCount();
    }

    public class AsyncPlatoListUtil extends AsyncListUtil<Plato> {
        /**
         * Creates an AsyncListUtil.
         */
        public AsyncPlatoListUtil() {
            super(Plato.class, //my data class
                    10, //page size
                    new DataCallback<Plato>() {
                        @Override
                        public int refreshData() {
                            //get count calling ../$count ... odata endpoint
                            return countPlatos(mFilter, mOrderby, mExpand, mActivity);
                        }

                        @Override
                        public void fillData(Plato[] data, int startPosition, int itemCount) {
                            //get items from odata endpoint using $skip and $top
                            Platos p = loadPlatos(mFilter, mOrderby, mExpand, startPosition, itemCount, mActivity);
                            for (int i = 0; i < Math.min(itemCount, p.value.size()); i++) {
                                data[i] = p.value.get(i);
                            }

                        }
                    }, new ViewCallback() {
                        @Override
                        public void getItemRangeInto(int[] outRange) {
                            //i use LinearLayoutManager in the RecyclerView
                            LinearLayoutManager layoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager();
                            outRange[0] = layoutManager.findFirstVisibleItemPosition();
                            outRange[1] = layoutManager.findLastVisibleItemPosition();
                        }

                        @Override
                        public void onDataRefresh() {
                            mRecyclerView.getAdapter().notifyDataSetChanged();
                        }

                        @Override
                        public void onItemLoaded(int position) {
                            mRecyclerView.getAdapter().notifyItemChanged(position);
                        }
                    });
            mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
                @Override
                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                    onRangeChanged();
                }
            });
        }
    }
}

1

@ কুশাল @ আবদুলাজিজ

পরিবর্তে এই যুক্তি ব্যবহার করবেন না কেন?

public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
    int totalItemCount, lastVisibleItemPosition;

    if (dy > 0) {
      totalItemCount = _layoutManager.getItemCount();
      lastVisibleItemPosition = _layoutManager.findLastVisibleItemPosition();

      if (!_isLastItem) {
        if ((totalItemCount - 1) == lastVisibleItemPosition) {
          LogUtil.e("end_of_list");

          _isLastItem = true;
        }
      }
    }
  }

আমার অনস্ক্রোলার () একক আইটেমের জন্য তিনবার ডেকেছে তাই আমি তিনবার end_of_list এবং আমার পৃষ্ঠাগুলি যুক্তিটি তিনবার পাই। পৃষ্ঠা একবারে কল করতে কীভাবে এটি সংশোধন করবেন।
ved

@ ওয়েবে এমনটি হওয়ার কথা নয়। উপরের কোডটি নিশ্চিত করে যে end_of_listশর্তটি কেবল একবার কল করা হবে। _isLastItemক্রিয়াকলাপে পতাকাটি একটি গ্লোবাল ভেরিয়েবল যাটির ডিফল্ট মান থাকে false। আমি যা করেছি তা হল তালিকার শেষ শনাক্ত করার পরে একটি পটভূমি কাজ সম্পাদন করা, পরের পৃষ্ঠাটি পুনরুদ্ধার করে নতুন ডেটাসেটের অ্যাডাপ্টারকে অবহিত করা এবং অবশেষে _isLastItemআবার মিথ্যাতে সেট করা।
লিওনপস

1

নীচে চেষ্টা করুন:

import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.LayoutManager;

/**
 * Abstract Endless ScrollListener
 * 
 */
public abstract class EndlessScrollListener extends
        RecyclerView.OnScrollListener {
    // The minimum amount of items to have below your current scroll position
    // before loading more.
    private int visibleThreshold = 10;
    // The current offset index of data you have loaded
    private int currentPage = 1;
    // True if we are still waiting for the last set of data to load.
    private boolean loading = true;
    // The total number of items in the data set after the last load
    private int previousTotal = 0;
    private int firstVisibleItem;
    private int visibleItemCount;
    private int totalItemCount;
    private LayoutManager layoutManager;

    public EndlessScrollListener(LayoutManager layoutManager) {
        validateLayoutManager(layoutManager);
        this.layoutManager = layoutManager;
    }

    public EndlessScrollListener(int visibleThreshold,
            LayoutManager layoutManager, int startPage) {
        validateLayoutManager(layoutManager);
        this.visibleThreshold = visibleThreshold;
        this.layoutManager = layoutManager;
        this.currentPage = startPage;
    }

    private void validateLayoutManager(LayoutManager layoutManager)
            throws IllegalArgumentException {
        if (null == layoutManager
                || !(layoutManager instanceof GridLayoutManager)
                || !(layoutManager instanceof LinearLayoutManager)) {
            throw new IllegalArgumentException(
                    "LayoutManager must be of type GridLayoutManager or LinearLayoutManager.");
        }
    }

    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
        visibleItemCount = recyclerView.getChildCount();
        totalItemCount = layoutManager.getItemCount();
        if (layoutManager instanceof GridLayoutManager) {
            firstVisibleItem = ((GridLayoutManager) layoutManager)
                    .findFirstVisibleItemPosition();
        } else if (layoutManager instanceof LinearLayoutManager) {
            firstVisibleItem = ((LinearLayoutManager) layoutManager)
                    .findFirstVisibleItemPosition();
        }
        if (loading) {
            if (totalItemCount > previousTotal) {
                loading = false;
                previousTotal = totalItemCount;
            }
        }
        if (!loading
                && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) {
            // End has been reached do something
            currentPage++;
            onLoadMore(currentPage);
            loading = true;
        }
    }

    // Defines the process for actually loading more data based on page
    public abstract void onLoadMore(int page);

}

1

আমি আবদুলাজিজ নূর উত্তর ব্যবহার করে লোডমোররেসাইকেলার ভিউ তৈরি করেছি

LoadMoreRecyclerView

public class LoadMoreRecyclerView extends RecyclerView  {

    private boolean loading = true;
    int pastVisiblesItems, visibleItemCount, totalItemCount;
    //WrapperLinearLayout is for handling crash in RecyclerView
    private WrapperLinearLayout mLayoutManager;
    private Context mContext;
    private OnLoadMoreListener onLoadMoreListener;

    public LoadMoreRecyclerView(Context context) {
        super(context);
        mContext = context;
        init();
    }

    public LoadMoreRecyclerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        init();
    }

    public LoadMoreRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mContext = context;
        init();
    }

    private void init(){
        mLayoutManager = new WrapperLinearLayout(mContext,LinearLayoutManager.VERTICAL,false);
        this.setLayoutManager(mLayoutManager);
        this.setItemAnimator(new DefaultItemAnimator());
        this.setHasFixedSize(true);
    }

    @Override
    public void onScrolled(int dx, int dy) {
        super.onScrolled(dx, dy);

        if(dy > 0) //check for scroll down
        {
            visibleItemCount = mLayoutManager.getChildCount();
            totalItemCount = mLayoutManager.getItemCount();
            pastVisiblesItems = mLayoutManager.findFirstVisibleItemPosition();

            if (loading)
            {
                if ( (visibleItemCount + pastVisiblesItems) >= totalItemCount)
                {
                    loading = false;
                    Log.v("...", "Call Load More !");
                    if(onLoadMoreListener != null){
                        onLoadMoreListener.onLoadMore();
                    }
                    //Do pagination.. i.e. fetch new data
                }
            }
        }
    }

    @Override
    public void onScrollStateChanged(int state) {
        super.onScrollStateChanged(state);
    }

    public void onLoadMoreCompleted(){
        loading = true;
    }

    public void setMoreLoading(boolean moreLoading){
        loading = moreLoading;
    }

    public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) {
        this.onLoadMoreListener = onLoadMoreListener;
    }
}

WrapperLinearLayout

public class WrapperLinearLayout extends LinearLayoutManager
{
    public WrapperLinearLayout(Context context, int orientation, boolean reverseLayout) {
        super(context, orientation, reverseLayout);
    }

    @Override
    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
        try {
            super.onLayoutChildren(recycler, state);
        } catch (IndexOutOfBoundsException e) {
            Log.e("probe", "meet a IOOBE in RecyclerView");
        }
    }
}

// এটি এক্সএমএল লাইক যুক্ত করুন

<your.package.LoadMoreRecyclerView
    android:id="@+id/recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</your.package.LoadMoreRecyclerView>

অনক্রিয়েট বা অনভিউ তৈরি করা

mLoadMoreRecyclerView = (LoadMoreRecyclerView) view.findViewById(R.id.recycler_view);
mLoadMoreRecyclerView.setOnLoadMoreListener(new OnLoadMoreListener() {
            @Override
            public void onLoadMore() {
                callYourService(StartIndex);
            }
        });

callYourService

private void callYourService(){
    //callyour Service and get response in any List

    List<AnyModelClass> newDataFromServer = getDataFromServerService();
    //Enable Load More
    mLoadMoreRecyclerView.onLoadMoreCompleted();

    if(newDataFromServer != null && newDataFromServer.size() > 0){
            StartIndex += newDataFromServer.size();

            if (newDataFromServer.size() < Integer.valueOf(MAX_ROWS)) {
                    //StopLoading..
                   mLoadMoreRecyclerView.setMoreLoading(false);
            }
    }
    else{
            mLoadMoreRecyclerView.setMoreLoading(false);
            mAdapter.notifyDataSetChanged();
    }
}

1

একা ডেটা মডেলের খাঁটি যুক্তি ব্যবহার করে স্ক্রোল শ্রোতা ছাড়া এটি প্রয়োগ করাও সম্ভব। স্ক্রোল ভিউটির অবস্থান অনুসারে আইটেমের পাশাপাশি সর্বোচ্চ আইটেমের গণনা প্রয়োজন count একের পর এক না হয়ে প্রয়োজনীয় আইটেমগুলি খণ্ডগুলিতে আনার জন্য মডেলটির পটভূমি যুক্তি থাকতে পারে এবং ডেটা প্রস্তুত হওয়ার সময় ভিউটি অবহিত করে background

এই পদ্ধতির মাধ্যমে আনার সারিটি পাওয়া যায় যা অতি অনুরোধিত (তাই বর্তমানে দৃশ্যমান) আইটেমগুলি পুরানো (সম্ভবত ইতিমধ্যে স্ক্রোলড দূরে) সাবমিশনের চেয়ে বেশি পছন্দ করে, ব্যবহার করতে সমান্তরাল থ্রেডের সংখ্যা এবং এই জাতীয় জিনিসগুলি নিয়ন্ত্রণ করে। এই পদ্ধতির (ডেমো অ্যাপ্লিকেশান এবং পুনর্ব্যবহারযোগ্য গ্রন্থাগার) জন্য সম্পূর্ণ সোর্স কোড পাওয়া যায় এখানে


0

Https://developer.android.com/references/android/support/v7/widget/RecyclerView.html#setOnScrolListener%28android.support.v7.widget.RecyclerView.OnScrolListener%29 এ একটি পদ্ধতি public void setOnScrollListener (RecyclerView.OnScrollListener listener)রয়েছে । যে ব্যবহার

সম্পাদনা করুন:

এর onScrollStateChangedভিতরে ওভাররাইড পদ্ধতিটি করুন onScrollListenerএবং এটি করুন

            boolean loadMore = firstVisibleItem + visibleItemCount >= totalItemCount;

            //loading is used to see if its already loading, you have to manually manipulate this boolean variable
            if (loadMore && !loading) {
                 //end of list reached
            }

1
আরও নির্দিষ্ট হতে দয়া করে! ব্যবহারকারীর তালিকার শেষের দিকে স্ক্রোল করা হয়েছে তা নির্ধারণ করতে আমি কীভাবে পুনর্ব্যবহারযোগ্য ভিউ.অনস্ক্রোললিস্টার ব্যবহার করব ?
এরদনা

রিসাইক্লারভিউতে কোনও স্ক্রোল নেই nঅনস্ক্রোললিস্টনার ! আপনি আব্সলিস্টভিউ.অনস্ক্রোললিস্টনারকে রিসাইক্লারভিউ.অনস্ক্রোললিস্টনারের সাথে মিশ্রিত করুন।
এরদনা

হ্যাঁ এটি হওয়ার কথাonScrollStateChanged
প্যান্থার

onScrollStateChangedকাজ করবে না যেহেতু কেবল তখনই বলা হবে যখন আপনি স্ক্রোলের অবস্থা পরিবর্তন করবেন এবং আপনি যখন স্ক্রল করছেন তখন না।
পেড্রো অলিভিরা

@ পেড্রোলিভিরা onScrollStateChangedব্যবহারকারী এটি শেষ আইটেমটিতে স্ক্রোল করে তা নির্ধারণ করা কি সম্ভব ?
এরদনা

0

এটিকে প্রতিটি বিষয় বিশদে ব্যাখ্যা করা আছে তা পরীক্ষা করে দেখুন: রিসাইক্লারভিউ থেকে এ থেকে জেড ব্যবহার করে পৃষ্ঠাগুলি

    mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
    @Override
    public void onScrollStateChanged(RecyclerView recyclerView,
                                     int newState) {
        super.onScrollStateChanged(recyclerView, newState);
    }

    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
        int visibleItemCount = mLayoutManager.getChildCount();
        int totalItemCount = mLayoutManager.getItemCount();
        int firstVisibleItemPosition = mLayoutManager.findFirstVisibleItemPosition();

        if (!mIsLoading && !mIsLastPage) {
            if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount
                    && firstVisibleItemPosition >= 0) {
                loadMoreItems();
            }
        }
    }
})

loadMoreItems ():

private void loadMoreItems() {
    mAdapter.removeLoading();
    //load data here from the server

    // in case of success
    mAdapter.addData(data);
    // if there might be more data
    mAdapter.addLoading();
}

মাইএডাপ্টারে:

private boolean mIsLoadingFooterAdded = false;

public void addLoading() {
    if (!mIsLoadingFooterAdded) {
        mIsLoadingFooterAdded = true;
        mLineItemList.add(new LineItem());
        notifyItemInserted(mLineItemList.size() - 1);
    }
}

public void removeLoading() {
    if (mIsLoadingFooterAdded) {
        mIsLoadingFooterAdded = false;
        int position = mLineItemList.size() - 1;
        LineItem item = mLineItemList.get(position);

        if (item != null) {
            mLineItemList.remove(position);
            notifyItemRemoved(position);
        }
    }
}

public void addData(List<YourDataClass> data) {

    for (int i = 0; i < data.size(); i++) {
        YourDataClass yourDataObject = data.get(i);
        mLineItemList.add(new LineItem(yourDataObject));
        notifyItemInserted(mLineItemList.size() - 1);
    }
}

লিঙ্কটিতে একটি উত্তর থাকতে পারে, তবে আপনার পোস্টের লিঙ্কটিতে ব্যাখ্যার কয়েকটি উল্লেখযোগ্য অংশ ব্যাখ্যা করার চেষ্টা করুন।
ইয়ান

0

তালিকাটি খুব ছোট বা না থাকলে এই উত্তরগুলির কোনওটিই আমলে নেয় না।

এখানে কোডের একটি অংশটি আমি ব্যবহার করছি যা উভয় দিক থেকে রিসাইক্ল ভিউগুলিতে কাজ করে।

@Override
    public boolean onTouchEvent(MotionEvent motionEvent) {

        if (recyclerViewListener == null) {
            return super.onTouchEvent(motionEvent);
        }

        /**
         * If the list is too small to scroll.
         */
        if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
            if (!canScrollVertically(1)) {
                recyclerViewListener.reachedBottom();
            } else if (!canScrollVertically(-1)) {
                recyclerViewListener.reachedTop();
            }
        }

        return super.onTouchEvent(motionEvent);
    }

    public void setListener(RecyclerViewListener recycleViewListener) {
        this.recyclerViewListener = recycleViewListener;
        addOnScrollListener(new OnScrollListener() {

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

                if (recyclerViewListener == null) {
                    return;
                }

                recyclerViewListener.scrolling(dy);

                if (!canScrollVertically(1)) {
                    recyclerViewListener.reachedBottom();
                } else if (!canScrollVertically(-1)) {
                    recyclerViewListener.reachedTop();
                }
            }

        });
    }

0

আমি আপনাকে আমার aproximation যাক। আমার জন্য ভাল কাজ করে।

আমি এটি আপনাকে সাহায্য করে আশা করি।

/**
 * Created by Daniel Pardo Ligorred on 03/03/2016.
 */
public abstract class BaseScrollListener extends RecyclerView.OnScrollListener {

    protected RecyclerView.LayoutManager layoutManager;

    public BaseScrollListener(RecyclerView.LayoutManager layoutManager) {

        this.layoutManager = layoutManager;

        this.init();
    }

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

        super.onScrolled(recyclerView, dx, dy);

        this.onScroll(recyclerView, this.getFirstVisibleItem(), this.layoutManager.getChildCount(), this.layoutManager.getItemCount(), dx, dy);
    }

    private int getFirstVisibleItem(){

        if(this.layoutManager instanceof LinearLayoutManager){

            return ((LinearLayoutManager) this.layoutManager).findFirstVisibleItemPosition();
        } else if (this.layoutManager instanceof StaggeredGridLayoutManager){

            int[] spanPositions = null; //Should be null -> StaggeredGridLayoutManager.findFirstVisibleItemPositions makes the work.

            try{

                return ((StaggeredGridLayoutManager) this.layoutManager).findFirstVisibleItemPositions(spanPositions)[0];
            }catch (Exception ex){

                // Do stuff...
            }
        }

        return 0;
    }

    public abstract void init();

    protected abstract void onScroll(RecyclerView recyclerView, int firstVisibleItem, int visibleItemCount, int totalItemCount, int dx, int dy);

}

0

এই সমাধানটি আমার পক্ষে নিখুঁতভাবে কাজ করে।

//Listener    

public abstract class InfiniteScrollListener     extendsRecyclerView.OnScrollListener {

public static String TAG = InfiniteScrollListener.class.getSimpleName();
int firstVisibleItem, visibleItemCount, totalItemCount;
private int previousTotal = 0;
private boolean loading = true;
private int visibleThreshold = 1;
private int current_page = 1;

private LinearLayoutManager mLinearLayoutManager;

public InfiniteScrollListener(LinearLayoutManager linearLayoutManager) {
    this.mLinearLayoutManager = linearLayoutManager;
}

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

    visibleItemCount = recyclerView.getChildCount();
    totalItemCount = mLinearLayoutManager.getItemCount();
    firstVisibleItem = mLinearLayoutManager.findFirstVisibleItemPosition();

    if (loading) {
        if (totalItemCount > previousTotal) {
            loading = false;
            previousTotal = totalItemCount;
        }
    }
    if (!loading && (totalItemCount - visibleItemCount - firstVisibleItem <= visibleThreshold)) {

        current_page++;

        onLoadMore(current_page);

        loading = true;
    }
}

public void resetState() {
    loading = true;
    previousTotal = 0;
    current_page = 1;
}

public abstract void onLoadMore(int current_page);
}

//Implementation into fragment 
 private InfiniteScrollListener scrollListener;

scrollListener = new InfiniteScrollListener(manager) {
        @Override
        public void onLoadMore(int current_page) {
            //Load data
        }
    };
    rv.setLayoutManager(manager);
    rv.addOnScrollListener(scrollListener);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.