Description: I am working on one demo with the functionality that user can select an option from the item of horizontal Recyclerview. In this, I got stuck in below queries.
Queries:
1: How to make Recyclerview cyclic?
For example, I have 10 items named 1,2,3,4,5,6,7,8,9,10. Now if user scrolls the recyclerview then he/she will be able to scroll it endlessly. i.e 1,2,3,4,5...9,10,1,2...9,10,1,2,3..9,10 like this.
To achieve this I have used this answer. Somehow it worked but only in forward direction.
2: How to give Snap center to the particular item which is selected by the user?
For example: As shown in the image, if the user clicks on '15' then that item will come to the center. Same as if the user clicks on '07' then it should come to the center position.
I have implemented this demo. But it doesn't work on click on the item.
The code which I have done so far is as below:
Layout Manager:
final CenterZoomLayoutManager mLayoutManager = new CenterZoomLayoutManager(mContext,
CenterZoomLayoutManager.HORIZONTAL, false);// To get centered item zoom
recyclerview.setLayoutManager(mLayoutManager);
Adapter object:
mAdapter = new CustomAdapter(mContext, arrayList, new RecyclerViewClickListener() {
#Override
public void recyclerViewListClicked(View v, int position) {
}
});
recyclerview.setAdapter(mAdapter);
Any help is appreciated!
Thanks.
CarouselView may fulfill your requirements. Please check following GitHub links for the same.
https://android-arsenal.com/details/1/1481
https://github.com/nicklockwood/iCarousel
https://www.pocketmagic.net/a-3d-carousel-view-for-android/
https://github.com/clkasd/CarouselViewProject
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 like
Integer.MAX_VALUE:
#Override
public int getCount() {
return Integer.MAX_VALUE;
}
in getItem() and getView() 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);
For snapping
use SnapHelper or scrollToPositionWithOffset, where offset is (width/2 - itemWidth/2)
I can use this library
You can solve your problem by personalizing this library. By selecting each item, you can use the ScrollToX function to navigate to that item.
https://github.com/mahdimoaz/RecyclerViewHorizontalCenterSelected
Related
I want to add empty spaces between items of a RecyclerView with GridLayoutManager but I can't find anything which solves my problem.
I am creating a custom calendar and I have to make a custom grid from scratch. The first day of the month should be placed farther from the start when it is not the first day of the week.
I have achieved a similar result by passing a firstItemLocation to my RecyclerView adapter and overriding the onBindViewHolder method like this:
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
if (position < firstItemLocation) {
holder.itemView.setVisibility(View.GONE);
} else {
holder.tv.setText(String.format(Locale.US, "%d", list.get(position - firstItemLocation)));
}
}
It works fine but in a hypothetical situation when the user has to scroll it adds random empty spaces and glitches like this.
Any seggestions to make it better without that glitch?
read about "recycling pattern", how it works and why - RecyclerView got its name because of this, so its very important to understand how this works
but in short:
inside onBindViewHolder you have to call desired methods ALWAYS. you are calling setVisibility only inside if and not in else. try with bellow snippet
if (position < firstItemLocation) {
holder.itemView.setVisibility(View.GONE);
holder.tv.setText("")
} else {
holder.itemView.setVisibility(View.VISIBLE);
holder.tv.setText(String.format(Locale.US, "%d", list.get(position - firstItemLocation)));
}
thats because holder may be a "recycled" instance, used previously to draw another list item, and its set up is still applied to views
I am implementing a recycler view with two ViewHolder types. After creating the first item as first-type view holder, I have a list of items of the same, second type. Now, I would like to juxtapose the second type items in order to define a two-column recycler view list considering the second type. Is it possible to do that? I have no idea of what should be implemented in the adapter and honestly I have found no good suggestions here. I guess I might not post my adapter code, since I don't know whether it is possible to do what I aim, I hope a conceptual answer may be sufficient too. I have an image, made with a not good image editor of my smartphone, I hope it is clear:
I am late but I found out a solution.
I associate to the recyclerview a GridLayoutManager with span count = 2.
Since I have, at the top of the recyclerview, an EditText (I use it as a search bar), as you can see in the image, I have to set the lookup of the grid. This is done by setSpanSizeLookup(). So, in the onViewCreated() method of my fragment class that initializes the recyclerview (I have a Fragment hosting the recyclerview), I insert the following code:
GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), 2);
gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
#Override
public int getSpanSize(int position) {
int type = adapter.getItemViewType(position);
if (type == RecyclerAdapter.SEARCH)
return 2;
else
return 1;
}
});
recyclerView.setLayoutManager(gridLayoutManager);
where the part "if (type == RecyclerAdapter.SEARCH) return 2;" means that the view holder for the search bar is going to occupy one whole row, 2 grid cells (since the span = 2).
In my recyclerview adapter, the method getItemViewType is essential:
#Override
public int getItemViewType(int position) {
if (position == 0)
return SEARCH;
else
return DESCRIPTION;
}
where SEARCH and DESCRIPTION are two static final variables.
I am trying to make a application that displays data in list using RecyclerView, In LinearLayoutManager there is a option to set Stack from end and reverse layout that allows for me to show the newest data on top of list. Is there anyway I can show the newest data at position 0 (at top) in staggered grid layout?
StaggeredGridLayoutManager has the method setReverseLayout.
Use it like this:
mLayoutManager = new StaggeredGridLayoutManager(getActivity());
mLayoutManager.setReverseLayout(true);
You can use GridLayoutManagaer. In constructor you can pass true/false to reverse layout or can use setReverseLayout(boolean) method. check this
You can scroll to the end after updating(inserting) you data (when it's needed)
private void updateData(#NonNull List<Item> items, boolean moveToTheEnd) {
adapter.updateItems(items);
if(moveToTheEnd) {
recyclerView.scrollToPosition(adapter.getItemCount() - 1);
}
}
The solution that worked for me, without having those spaces at the beginning, is to add this line at the beginning of your onBindViewHolder method in your adapter:
position = getItemCount()-1-position;
So your code will be something like this:
#Override
public void onBindViewHolder(#NonNull MyAdapter.ViewHolder holder, int position) {
position = getItemCount()-1-position;
holder.textView.setText(mObjects.get(position).getText());
}
There is a way to horizontally center the last item in a recycler view.
So...if there is only one item this item will be centered and will not scroll, if there is two or more that can fill the width it will be possible to scroll, but the last item will appears first on center
For example. In the following images, every time a new search category (iPhone, Celulares e Smartphones) are added, the last item is centralized.
You will have to do it in your adapter. I have never did something like this, but my try would be something like this:
On the method onBindViewHolder:
#Override
public void onBindViewHolder(MyHolder holder, int position) {
OrderItem item = items.get(position);
//last item
if(position == item.size()-1){
holder.textview.setLayoutParams(Gravity.CENTER_VERTICAL);
}
}
Try adapt this idea in your project!
I'm working on a note taking app. I add a note, and it get's added to the bottom of the list. As the last assertion in the espresso test, I want to make sure that the ListView displays a listItem that has just been added. This would mean grabbing the last item in the listView. I guess you might be able to do it in other ways? (e.g. get the size of adapted data, and go to THAT position? maybe?), but the last position of the list seems easy, but I haven't been able to do it. Any ideas?
I've tried this solution, but Espresso seems to hang. http://www.gilvegliach.it/?id=1
1. Find the number of elements in listView's adapter and save it in some variable. We assume the adapter has been fully loaded till now.:
final int[] numberOfAdapterItems = new int[1];
onView(withId(R.id.some_list_view)).check(matches(new TypeSafeMatcher<View>() {
#Override
public boolean matchesSafely(View view) {
ListView listView = (ListView) view;
//here we assume the adapter has been fully loaded already
numberOfAdapterItems[0] = listView.getAdapter().getCount();
return true;
}
#Override
public void describeTo(Description description) {
}
}));
2. Then, knowing the total number of elements in listView's adapter you can scroll to the last element:
onData(anything()).inAdapterView(withId(R.id.some_list_view)).getPosition(numberOfAdapterItems[0] - 1).perform(scrollTo())