How to horizontally center the last item of a recyclerview - android

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!

Related

How to get data of RecyclerView items that is not shown on Screen?

I have a recyclerView that each item of it contain a question title and also a recyclerView inside it. I want to change the color of items inside the second recyclerView when clicking on a send button. I do this with these lines of code:
(questionListView is the RecyclerView and ansRecycle is second RecyclerView)
for (int i=0;i<adapter.getItemCount();i++){
questionListView.scrollToPosition(i);
questionListView.
adapter.notifyItemChanged(i);
View view=questionListView.findViewHolderForAdapterPosition(i).itemView;
RecyclerView ansRecycle=view.findViewById(R.id.checkedAnswerLayout);
for(int j=0;j<ansRecycle.getAdapter().getItemCount();j++) {
View temp=ansRecycle.getChildAt(j);
CheckBox ch=temp.findViewById(R.id.checkedChoice);
if(ch.getText().toString().equals(questions.get(i).getCorrectAnswers())){
ch.setTextColor(Color.RED);
}
}
}
For items that are shown on screen all things are fine but for others, there is no existence ViewHolder and I can not change the color of them.
How can I do this?
The problem is that items that are not on screen doesn't exist. The whole point of recyclerview is that it uses small amount of views, and recycle them when they leave the screen.
What you should do is do the same "if" when you bind the data.:
#Override
public void onBindViewHolder(MyDataViewHolder holder, int position) {
if(ch.getText().toString().equals(questions.get(i).getCorrectAnswers())){
ch.setTextColor(Color.RED);
}
}
Work around solution would be:
add a field to the Question - like int color = your color with setters/getters
on click get the questionItem and set the color of it to a new color
onBind of the recyclerView's find the textView and set the color based on your queston
same with answers.
for example
holder.textView.setColor(question.getColor());

How to change an another item's state in a RecyclerView in android

I have a RecyclerView. Every layout contains expandle view within itself.
With item click expandle view of clicked item is expands. And if I'll click on two items there is will be two items with expanded view in my RecyclerView. I need to close others item's expandles view with item click. Only one item with expanded expandle view must be in recycler.
How do I can make this?
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
holder.exp.collapse();
holder.itemView.setOnClickListener(v -> {
holder.exp.expand();
});
Save the Position of previously expanded position make a property in lists object like some boolean isOpen or something set it to false or true as required now on Click of a new row
list.get(prevPosition).setIsOpen(false);
then
notifyItemChanged(prevPosition);
make sure you have handled in your bindViewHolder something like this
if(list.get(postition).getIsOpen()==false){
//hide your expanded list
}

Snap center onItemClick in cyclic Recyclerview android

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

Show selected item on RecyclerView in Sync with ViewPager

I am trying to get a ViewPager and a RecyclerView to work in sync in displaying an image. The ViewPager contains an ImageView which shows a full sized image and the recycler view shows thumbnails of previous and upcoming images.
If the user swipes on the ViewPager then the RecyclerView moves left/right in sync. If the user scrolls and then clicks a photo, the ViewPager sets that position.
This all works, just giving background to my app.
The part I am stuck on is showing a border around the thumbnail that is currently selected in the RecyclerView from onPageSelected. The element which is considered selected is the one that is currently show on the ViewPager
A lot of the other questions deal with this problem using the onClickListener. My onClickListener just calls
viewPager.setCurrentItem(index)
So any time an item is selected, onPageSelected is called, either naturally from the ViewPager or from the click event. So this is where I feel I need to set the border.
So far I'm using a bit of a hack since the number of images is only 20.
for (int i = 0, ii = recyclerViewAdapter.getItemCount(); i < ii; i++) {
//RecyclerView.ViewHolder holder = recyclerView.findViewHolderForItemId(recyclerViewAdapter.getItemId(i));
RecyclerView.ViewHolder holder = recyclerView.findViewHolderForAdapterPosition(position);
if (holder instanceof RecyclerViewAdapter.RecyclerViewHolder) {
if (i == position) {
...
((RecyclerViewAdapter.RecyclerViewHolder) holder).getViewHolderContainer().setBackground(border);
} else {
((RecyclerViewAdapter.RecyclerViewHolder) holder).getViewHolderContainer().setBackground(null);
}
}
}
This doesn't work. If get's the right position since I'm provided that by the ViewPager but neither method for retrieving the ViewHolder at 'position' seems to work.
So, after all that, my question is if anyone can recommend me a clean way (or really even a hack at this point) that will let me update the current position of an element based on the position from onPageSelected of the ViewPager.
Thank you kindly.
So I ended up getting this working using two interfaces. No ugly looping hacks required.
ViewPager.OnPageChangeListener and OnChildAttachStateListener.
Basically my issue was that if I scrolled away from the currently selected item in the RecyclerView then I couldn't unselect that item later because the ViewHolder was recycled or null. Basically I couldn't access the previous view to unselect it so multiple items would end up selected when you scroll through it.
So with the ViewPager it was easy.
#Override
public void onPageSelected(int position)
int previousItemPos = currentItemPos; //currentItemPos is a class attr
currentItemPos = position;
int rotation = getActivity().getWindowManager().getDefaultDisplay().getRotation()
if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_270) { //portrait
portraitScroll(position) //scrolls the recyclerView to currently selected item based on viewWidth
} else if .. landscape do the same
changeItem(position, previousItemPos);
}
#Override
public void onChildViewAttachedToWindow(View view) {
int childPosition = recyclerView.getChildAdapterPosition(view);
if (childPosition == currentItemPos) {
highlightItem(view); //applies an effect
}
}
#Override
public void onChildViewDetachedToWindow(View view) {
unHighlightItem(view);
}
private void changeItem(int newItem, int oldItem) {
ViewHolder holder = recyclerView.findViewHolderForItemId(recyclerView.getItemId(newItem));
if (holder instance of RecyclerViewHolder) {
highlightItem((RecyclerViewHolder) holder).getViewHolderContainer());
}
ViewHolder oldHolder = recyclerView.findViewHolderForItemId(recyclerView.getItemId(oldItem));
if (oldHolder instance of RecyclerViewHolder) {
unHighlightItem((RecyclerViewHolder) holder).getViewHolderContainer());
}
So basically each time we scroll so that the currently selected item in the ViewPager goes out of sight, we unselect it when it is detached. If we scroll back to it and the position hasn't changed, we reselect it.
If the ViewPager changes item, first we scroll to that item based on the width of the each RecyclerViews view, then we select it in onPageSelected.

Recyclerview make the last added item be the selected item?

I have a horizontal Recyclerview which displays bitmaps.
The Way it is implemented is I have a Imageview and a recyclerview underneath it. The currently selected item is displayed on the image view. The selected image view is given a blue background to indicate it is selected. I can choose images from the gallery and each time a new image is selected, I want to scroll to the last position and make the item selected.
The list of images is maintained in a array list and each time a new image is added, I add the image to the list and notifyDataChanged().
Currently when I am binding a view, I toggle the visibility of the blue background in
public void onBindViewHolder(final MyRecyclerViewHolder holder, int position) {
}
But the problem is, if the child is off screen, the bind view is not called and I dont scroll to the new position.
I read through the documentation of recycler view and could not figure out how to scroll to that particular child view. I do not there is a SmoothScrollTo method but my question is where do I trigger this ?
There is one solution:
In your RecyclerView adapter, add a variable selectedItem and a methods setSelectedItem():
private static int selectedItem = -1;
... ...
public void setSelectedItem(int position)
{
selectedItem = position;
}
In your onBindViewHolder(...), add:
#Override
public void onBindViewHolder(ViewHolder holder, final int position)
{
... ...
if(selectedItem == position)
holder.itemView.setSelected(true);
}
Now you can scroll to specific item and set it selected programmatically by:
myRecyclerViewAdapter.setSelectedItem(position_scrollTo);
myRecyclerView.scrollToPosition(position_scrollTo);
For example, you want to scroll to last position and make it selected, just:
int last_pos = myRecyclerViewAdapter.getItemCount() - 1;
myRecyclerViewAdapter.setSelectedItem(last_pos);
myRecyclerView.scrollToPosition(last_pos);
[UPDATE]
To add item and make it selected, you should have a addItem(...) method in adapter, which will add item to item list. After adding item, refresh list and scroll to new added/latest item:
myRecyclerViewAdapter.addItem(...);
myRecyclerViewAdapter.notifyDataSetChanged();
myRecyclerViewAdapter.setSelectedItem(myRecyclerViewAdapter.getItemCount() - 1);
myRecyclerView.scrollToPosition(myRecyclerViewAdapter.getItemCount() - 1);
Hope this help!
Your view will not be created until you scroll to the item.
You must call
recyclerView.scrollToPosition(position)
Where position is
recyclerView.getAdapter().size()
So the item became visible.
Use RecyclerView LayoutManager to scroll item at position
recyclerView.getLayoutManager().scrollToPosition(position)
I forgot to address the timing part ideally this should be called when the adapter has been identified of the dataset change.
You could use
recyclerView.smoothScrollToPosition(View.FOCUS_DOWN);

Categories

Resources