How to get the data when scrolling RecyclerView for the particular position? I have a list of items which will show the user about the upcoming events(dynamically). I need to fetch the event details when it is positioned at center, to change the position of marker. Sorry, I can't show the code. If you need more details please comment here.
You must fetch the location data inside your reyclerview adapter's onBindViewHolder.
public class Adapter extends RecyclerView.Adapter<Adapter.MyViewHolder> {
private List<Wrapper> dashboardList; //
public Adapter(List<Wrapper> dashboardList) {
this.dashboardList = dashboardList;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
Wrapper data = dashboardList.get(position);
holder.tv_price.setText(data.getPrice());
holder.tv_address.setText(data.getAddress());
fetchLocation(data.getLocation());
}
public void fetchLocation(String location)
{
//Code for location search
}
Related
I am actually making some visibility changes to items that are clicked of the recycler view. But when the user clicks on one object and then clicks on the other object then the previous object should come to its initial state.
The manager.findViewByPosition(position) is working fine if the view is in focus of the screen but I am not able to get the view if the element is not in current focus.
For example:- the user clicks on 1st(position) item then clicks on the last position then the findViewByPosition returns a null.
Please help and let me know if there is some other way of doing it.
The expected result should be the view of the last item to be refreshed but it's not happening for the views that are not in the current focus of the screen.
Below is my code snippet. Updated with what you suggested.
public class BodyPartWithMmtRecyclerView extends
RecyclerView.Adapter<BodyPartWithMmtRecyclerView.ViewHolder>
{
//variables defined.
int selectedPosition = -1;
static class ViewHolder extends RecyclerView.ViewHolder {
//All the view items declared here.
ViewHolder(View view) {
super(view);
//All the views are defined here.
}
}
public BodyPartWithMmtRecyclerView(List<BodyPartWithMmtSelectionModel> bodyPartsList, Context context){
//array list initialization and shared preference variables initialization
}
public BodyPartWithMmtRecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
//Creating a new view.
}
public void onBindViewHolder(#NonNull final BodyPartWithMmtRecyclerView.ViewHolder holder, #SuppressLint("RecyclerView") final int position) {
BodyPartWithMmtSelectionModel bodyPartWithMmtSelectionModel = bodyPartsList.get(position);
holder.iv_bodypart.setImageResource(bodyPartWithMmtSelectionModel.getIv_body_part());
holder.tv_body_part_name.setText(bodyPartWithMmtSelectionModel.getExercise_name());
if(selectedPosition!=position && selectedPosition!=-1){
//updated the elements view to default view. Like made the visibility and other changes here.
}
//some click listeners on the sub-elements of the items. Like textviews, spinner, etc
holder.iv_bodypart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
((BodyPartSelection)context).setFabVisible();
if(selectedPosition!=-1){
((BodyPartSelection)context).visibilityChanged(selectedPosition,position);
/*here what I was doing is whenever the user clicks on an item I check weather a previous item is clicked or not then if yes then I send the position to a function that makes it to default but the issue was that if the item is not in the focus of the screen the findViewByPosition returns null.*/
}
selectedPosition = position;
bodypartSelected = holder.tv_body_part_name.getText().toString();
holder.iv_bodypart.setVisibility(View.INVISIBLE);
holder.rl_left_right.setVisibility(View.VISIBLE);
}
});
//and other listeners below
}
#Override
public int getItemCount() {
return bodyPartsList==null?0:bodyPartsList.size();
}
#Override
public int getItemViewType(int position) {
return position;
}
}
VisibilityChanged function
public void visibilityChanged(int position, int clicked){
View view = manager.findViewByPosition(position);
if(view!=null) {
Log.i("inside","visibility change");
ImageView imageView = view.findViewById(R.id.bodypartImage);
//other elements and changing the visibility of elemets to default.
}
}
I have updated my code based on the snippet you updated. Please don't change the visibility condition if-else I have added with any different logic which I saw in your code snippet. As you did, it will not update both selected and default view as RecyclerView reuse the view layout. So if the condition is not proper, you may see multiple items as selected or some other types of unwated behaviour.
public void onBindViewHolder(#NonNull final BodyPartWithMmtRecyclerView.ViewHolder holder, #SuppressLint("RecyclerView") final int position) {
BodyPartWithMmtSelectionModel bodyPartWithMmtSelectionModel = bodyPartsList.get(position);
holder.iv_bodypart.setImageResource(bodyPartWithMmtSelectionModel.getIv_body_part());
holder.tv_body_part_name.setText(bodyPartWithMmtSelectionModel.getExercise_name());
if(selectedPosition == position){
//updated the elements view to SELECTED VIEW. Like made the visibility and other changes here.
} else {
//updated the elements view to default view. Like made the visibility and other changes here.
}
//some click listeners on the sub-elements of the items. Like textviews, spinner, etc
holder.iv_bodypart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
((BodyPartSelection)context).setFabVisible();
/Comment by Hari: Don't try to change the visibility of default as it will be done automatically after calling notifyDataSetChanged(). */
if(selectedPosition!=-1){
((BodyPartSelection)context).visibilityChanged(selectedPosition,position);
/*here what I was doing is whenever the user clicks on an item I check weather a previous item is clicked or not then if yes then I send the position to a function that makes it to default but the issue was that if the item is not in the focus of the screen the findViewByPosition returns null.*/
/*Comment by Hari: This snippet is valuable which is missing as you are getting null issue here.
However Don't try to change the visibility of default as it will be done automatically after calling notifyDataSetChanged(). */
}
selectedPosition = position;
bodypartSelected = holder.tv_body_part_name.getText().toString();
holder.iv_bodypart.setVisibility(View.INVISIBLE);
holder.rl_left_right.setVisibility(View.VISIBLE);
//Keep this as last statement in onClick
notifyDataSetChanged();
}
});
//and other listeners below
}
Let me know your further response.
Based on #Hari N Jha's Answer.
Call notifyDataSetChanged() when you update anything. E.g
int selectedPosition = -1;
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
//....
if(position == selectedPosition) {
//Add background color change of your layout or as you want for selected item.
} else {
//Add background color change of your layout or as you want for default item.
}
notifyDataSetChanged(); //Call notifyDataSetChanged() here after done all the stufs
//...
}
I am having a RecyclerView which is populating list of objects.Each object has one image and a comment. I want to update the comment on a specific row. I dont want to refresh the whole RecyclerView's Adapter. I just want to update or refresh that specific row. How can I achieve it? Below is my implementation. Am I doing it write ?
This method is in my Adapter: UPDATED
public void updateComment(String comment,int position){
this.mList.get(position).setCommentText(comment);
notifyItemChanged(position,this.mList);
}
From my Activity I am calling the above method like this:
adapter.updateComment("Great",1);
UPDATE:
As per the suggestion by pskink. I implemented this:
#Override
public void onBindViewHolder(CellViewHolder holder, int position, List<Object> payloads) {
if(payloads.isEmpty()){
super.onBindViewHolder(holder,position,payloads);
}else{
for (Object payload : payloads) {
if (payload instanceof MyMemo) {
holder.bindComment((MyMemo) payload);
}
}
}
}
The bindComment() method in my ViewHolder:
private void bindComment(MyMemo payload) {
comment.setText(payload.getCommentText());
}
I want know that how to highlight recyclerView item.when the user close the app and open app in next time then change the color recyclerView item whos read the uesr.how it is possible?
Store the Item positions that the user reads and then in the onBindViewHolder method of the RecylerViewAdapter try this following code
#Override
public void onBindViewHolder(RecylerViewAdapter.ViewHolder holder, final int position) {
//some code....
if(isRead(position)){
holder.mView.setBackgroundColor(Color.RED);
}else
holder.mView.setBackgroundColor(Color.TRANSPARENT);
}
// readList is the positions that you stored in some array
// you can use the sqlite database or other logic whatever you prefer to store the positions
private void isRead(int position){
for(int i = 0;i<readList.length;i++){
if(readList[i]==position)
return true;
}
return false;
}
Edit: if anyone is having the same problem in the future it was a pretty easy fix. I used clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) to handle when the entire drag was finished and had forgotten to call it's super-method. That's why it didn't update properly.
Original question:
Here's the entire code: https://github.com/vustav/Ppaaiinntt/tree/master/app/src/main/java/com/decent/rvtest
Everything works fine except when I add an element right after deleting another. It does exist though. If I add another there's a properly sized space between the old list and the new element. I use a string where they add their names before a print and it shows there, and if I drag to change positions of the elements it shows up properly.
My reputation doesn't allow me to post images so an imgur-album will have to do:
http://imgur.com/a/bmb17
On the first image there's three elements and the string is printed at the bottom.
The second image is after the swipe. Notice the string is updated.
The third is after adding another "111". The string is correct but it doesn't show up in the view.
The fourth is after adding another. The string is still correct and the new element shows up in the view.
The last image is after dragging to change the position of the last two elements. Now everything is fine again.
These are the relevant methods (I think):
protected void add(PictureElement pe){
chain.add(pe);
notifyItemInserted(chain.size()-1);
}
public void remove(int position) {
chain.remove(position);
notifyItemRemoved(position);
}
protected void swap(int from, int to){
chain.swap(from, to);
notifyItemMoved(from, to);
}
Edit: onBindViewHolder, getItemCount and the ViewHolder:
#Override
public int getItemCount() {
return chain.size();
}
#Override
public void onBindViewHolder(PEViewHolder PEViewHolder, int i) {
PictureElement pe = chain.get(i);
PEViewHolder.name.setText(pe.getName());
}
protected static class PEViewHolder extends RecyclerView.ViewHolder {
protected TextView name;
public PEViewHolder(View v) {
super(v);
name = (TextView) v.findViewById(R.id.txtName);
}
}
Interesting quote on the different notify methods you are using
public final void notifyItemRemoved (int position) Notify any registered observers that the item previously located at position has
been removed from the data set. The items previously located at and
after position may now be found at oldPosition - 1. This is a
structural change event. Representations of other existing items in
the data set are still considered up to date and will not be rebound,
though their positions may be altered. Parameters position : Position
of the item that has now been removed.
public final void notifyItemRangeChanged (int positionStart, int itemCount) Notify any registered observers that the itemCount items
starting at position positionStart have changed. Equivalent to calling
notifyItemRangeChanged(position, itemCount, null);. This is an item
change event, not a structural change event. It indicates that any
reflection of the data in the given position range is out of date and
should be updated. The items in the given range retain the same
identity.
Could you try and comment this block of code and check if it works
//Called by the ItemTouchHelper when the user interaction with an element is over and it also
// completed its animation
/*
#Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
//update from where the action took place
mPEAdapter.updateChain(viewHolder.getLayoutPosition());
//clearView is called after onMove so any drags or swipes are complete
dragging = false;
mPEAdapter.setSwipe(false);
}
*/
I have a fragment that contains a Recyclerview (along with ViewHolder and Adapter). The onClick handler is defined inside ViewHolder, but I would like to query the position of item selected in the fragment level.
I can save the item position to fragment's member variable using getAdapterPosition() from within the ViewHolder's onClick but is there a direct way to get the ViewHolder or position clicked from the fragment level? Ideally I would rather the ViewHolder not know anything about the fragment.
You could use multiple listeners (interfaces) to transport the clicked position back from your ViewHolders to your Fragment via your RecyclerView. Following is a minimalized example of what I mean: basically you let your Fragment listen to your RecyclerView, which in turn listens to your ViewHolders beeing clicked.
Hope this helps you find a way to solve your problem. Don't know if it is the best way, but it worked for me and I like this communication.
YourViewHolder.java
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick() {
for (ViewHolderListener l : listeners) {
l.onViewHolderClicked(getLayoutPosition())
...
public interface ViewHolderListener() {
void onViewHolderClicked(int position);
}
YourRecyclerView.java
public class YourRecyclerView ... implements YourViewHolder.ViewHolderListener {
...
#Override
public void onViewHolderClicked(int position) {
for (RecyclerViewListener l : listeners) {
l.onViewClicked(position);
...
public interface RecyclerViewListener {
void onViewClicked(int position);
}
YourFragment.java
public class YourFragment ... implements YourRecyclerView.RecyclerViewListener {
...
#Override
public void onViewClicked(int position) {
// Here you do whatever you want with the clicked view's position
}