How do I create a circular (endless) RecyclerView?
There is no way of making it infinite, but there is a way to make it look like infinite.
in your adapter override
getCount()
to return something big likeInteger.MAX_VALUE
:@Override
public int getCount() {
return Integer.MAX_VALUE;
}in
getItem()
andgetView()
modulo divide (%) position by real item number:@Override
public Fragment getItem(int position) {
int positionInList = position % fragmentList.size();
return fragmentList.get(positionInList);
}at the end, set current item to something in the middle (or else, it would be endless only in downward direction).
// scroll to middle item
recyclerView.getLayoutManager().scrollToPosition(Integer.MAX_VALUE / 2);
how to create closed circular Recyclerview with custom Recycler adapter?
I looked in a little deep and found a working solution/hack here.I have tested it and it works well.I am closing this question. thanks!
How to implement endless list with RecyclerView?
Thanks to @Kushal and this is how I implemented it
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
loading = true;
}
}
}
}
});
Don't forget to add
LinearLayoutManager mLayoutManager;
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
RecyclerView how to make cyclic
Please refer to the following question which answers a similar problem: How do I create a circular (endless) RecyclerView?
Endless RecyclerView, that repeat data when goes to the end
You are lucky, I did it a couple of days ago.
The trick in my solution was to override the getItemCount()
of the adapter
so that it works with Integer.MAX_VALUE
value.
The getItemCount()
is used by the recyclerview
to determinate how many items there are in the list, and if it returns always MAX_VALUE
, the list is pretty much infinite.
This is my example:
Activity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mlayout);
RecyclerView myRv = findViewById(R.id.myRv);
ArrayList<MyObject> objectList = new ArrayList<>();
objectList = retrieveObjectList();
myRv.setLayoutManager(new SlowLayoutManager(myActivity.this));
MyAdapter myAdapter = new MyAdapter(objectList);
myRv.setAdapter(myAdapter);
}
Adapter
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private ArrayList<MyObject> myObjects;
public MyAdapter(ArrayList<MyObject> myObjects) {
this.myObjects = myObjects;
}
//used to retrieve the effective item position in list
public int getActualItemCount() {
if (myObjects == null) {
myObjects = new ArrayList<>();
}
return myObjects.size();
}
@Override
public int getItemCount() {
return Integer.MAX_VALUE;
}
@NonNull
@Override
public MyAdapter.MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new MyAdapter.MyViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_view, parent, false));
}
@Override
public void onBindViewHolder(@NonNull MessagesAdapter.MessagesViewHolder holder, int position) {
if (myObjects.size() == 0) {
holder.bind(null);
} else {
MyObject myObject = myObjects.get(position % myObjects.size());
holder.bind(SMSMessage);
}
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView myTv;
MessagesViewHolder(View itemView) {
super(itemView);
myTv = itemView.findViewById(R.id.myTv);
}
void bind(MyObject myObject) {
if (myObject != null) {
myTv.setText(myObject.getProperty());
} else {
myTv.setText("");
}
}
}
}
I use this way (obj I changed names so you can fill them with yours, since some of mine were similar to native ones).
If you have any question, ask freely
Implementing Endless RecyclerView
This could achieve your goal.
public abstract class EndlessRecyclerOnScrollListener extends RecyclerView.OnScrollListener {
public static String TAG = EndlessRecyclerOnScrollListener.class.getSimpleName();
private int previousTotal = 0; // The total number of items in the dataset after the last load
private boolean loading = true; // True if we are still waiting for the last set of data to load.
private int visibleThreshold = 5; // The minimum amount of items to have below your current scroll position before loading more.
int firstVisibleItem, visibleItemCount, totalItemCount;
private int current_page = 1;
private LinearLayoutManager mLinearLayoutManager;
public EndlessRecyclerOnScrollListener(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)) {
// End has been reached
// Do something
current_page++;
onLoadMore(current_page);
loading = true;
}
}
public abstract void onLoadMore(int current_page);
}
And sample activity
public class SampleActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sample);
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.list);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setOnScrollListener(new EndlessRecyclerOnScrollListener(linearLayoutManager) {
@Override
public void onLoadMore(int current_page) {
// do something...
}
});
}
}
Edit: See here: Endless Scrolling with AdapterViews
How to make different views RecyclerView as endless loop?
So after extensive searching, found this solution.
So this is what I did
RecyclerViewAdapterClass
fun initialize(scrollableData: ArrayList<ScrollableData>, activity: AppCompatActivity) {
this.scrollableData = scrollableData
this.activity = activity
list = /*listOf(scrollableData.last()) +*/ scrollableData + listOf(scrollableData.first()) //this is very important
}
...
override fun getItemViewType(position: Int): Int {
return list[position % list.size].index
}
HomeActivity#setupRecyclerView(...)
mainScreenAdapter.itemCount.takeIf { it > 1 }
?.apply {
onScrollListener = OnScrollListener(
mainScreenAdapter.itemCount,
linearLayoutManager
) {
//some code here
}
recycler_view.addOnScrollListener(onScrollListener)
recycler_view.scrollToPosition(0)
}
OnScrollListener
internal class OnScrollListener(val itemCount: Int, val layoutManager: LinearLayoutManager,
val stateChanged: (Int) -> Unit) : RecyclerView.OnScrollListener() {
var isLooping = false
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView!!, dx, dy)
val firstItemVisible = layoutManager.findFirstCompletelyVisibleItemPosition()
if (firstItemVisible > 0 && firstItemVisible % (itemCount - 1) == 0) {
// When position reaches end of the list, it sho uld go back to the beginning
isLooping = true
recyclerView?.scrollToPosition(0)
} /*else if (firstItemVisible == 0) {
// When position reaches beginning of the list, it should go back to the end
recyclerView?.scrollToPosition(itemCount-1)
}*/
}
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView!!, newState)
var loop = newState
if (isLooping) {
loop = 100
isLooping = false
}
stateChanged(loop)
}
}
Ref: https://github.com/tomoima525/CirculerAutoScrollingRecyclerView
Creating horizontal RecyclerView with circular scroll
In your getItemCount function in Adapter class use return Integer.MAX_VALUE;
Also use position as below in bindviewholder function.
int positionInList = position % yourList.size();
Related Topics
Android Emulator Error Message: "Panic: Missing Emulator Engine Program for 'X86' Cpus."
Android What Does the Cliptopadding Attribute Do
How to Get City Name from Latitude and Longitude Coordinates in Google Maps
Webview, Add Local .CSS File to an HTML Page
Android Webview with an Embedded Youtube Video, Full Screen Button Freezes Video
How to Change Status Bar Color to Match App in Lollipop? - Android
Error:'Keytool' Is Not Recognized as an Internal or External Command, Operable Program or Batch File
When Should I Use the Assets as Opposed to Raw Resources in Android
Android How to Use Environment.Getexternalstoragedirectory()
Update Ui from Thread in Android
Android Webview Rem Units Scale Way to Large for Boxes
Keyboard Showed Messed Up Elements' Position
Trusting All Certificates with Okhttp
How to Generate Class Diagram (Uml) on Android Studio (Intellij Idea)
Scale Factor for Xxhdpi Android
How to Download the Android Sdk Without Downloading Android Studio