Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

notifyItemChanged() make the RecyclerView scroll and jump to UP

Tags:

i have a RecycleView with an adapter that show a list of servers and the user must select one server.

when i call notifyItemChanged(previousPosition) inside the onClick() method to make the old server unselected and the new server selected, that's make the RecycleView list jump to up exactly in the middle of list.

and this problem happen just when i click on one of the last 2 or 3 servers inside the RecycleView list

here is the code of my RecyclerView.Adapter :

public class ServerAdapter extends RecyclerView.Adapter<ServerAdapter.ServerViewHolder> {      private List<Server> listServers = new ArrayList<>();     private int[] icons = new int[]{R.drawable.server1,R.drawable.server2,R.drawable.server3,R.drawable.server4,R.drawable.server5,R.drawable.server6,R.drawable.offline};     private int selected = 0;     private int previousSelected = 0;      public ServerAdapter(List<Server> listServers){         this.listServers = listServers;     }      @Override     public ServerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {         View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.server_relative_layout,parent,false);         return new ServerViewHolder(view);     }      @Override     public void onBindViewHolder(final ServerViewHolder holder, final int position) {         if(position == selected){             holder.getBackground().setSelected(true);         }else{             holder.getBackground().setSelected(false);         }         holder.getBackground().setOnClickListener(new View.OnClickListener() {             @Override             public void onClick(View v) {                 if(position != selected){                     previousSelected = selected;                     selected = position;                     holder.getBackground().setSelected(true);                     notifyItemChanged(previousSelected);                 }             }         });         holder.getImageServer().setImageResource(icons[position%6]);         holder.getTextNameServer().setText(listServers.get(position).getName());         holder.getTextConnected().setText(listServers.get(position).getUrl());     }      @Override     public int getItemCount() {         return listServers.size();     }      public class ServerViewHolder extends RecyclerView.ViewHolder{         private ImageView imageServer;         private TextView textNameServer;         private TextView textConnected;         private View background;         public ServerViewHolder(View itemView) {             super(itemView);             imageServer = (ImageView)itemView.findViewById(R.id.imageServer);             textNameServer = (TextView)itemView.findViewById(R.id.textNameServer);             textConnected = (TextView)itemView.findViewById(R.id.textConnected);             background = itemView;         }          public ImageView getImageServer() {             return imageServer;         }          public TextView getTextConnected() {             return textConnected;         }          public TextView getTextNameServer() {             return textNameServer;         }          public View getBackground() {             return background;         }     } } 

any solutions to solve this problem ? thanks.

The problem happened exactly when i specify the layout height and do not let it to wrap_content

<android.support.v7.widget.RecyclerView     android:layout_width="wrap_content"     android:layout_height="400dp"     android:id="@+id/serverRecyclerView"     android:layout_margin="10dp" /> 

or when i put it below something for expample like that :

<android.support.v7.widget.RecyclerView     android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:id="@+id/serverRecyclerView"     android:layout_margin="10dp"     android:layout_below="@+id/image"/> 

my code exactly is :

<android.support.v7.widget.RecyclerView     android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:id="@+id/serverRecyclerView"     android:layout_margin="10dp"     android:layout_alignTop="@+id/imageBall"     android:layout_alignParentRight="true"     android:layout_alignParentEnd="true"     android:layout_toRightOf="@+id/camera"     android:layout_toEndOf="@+id/camera"/> 
like image 993
Zakariaa Oulhafiane Avatar asked Apr 19 '16 17:04

Zakariaa Oulhafiane


People also ask

Does RecyclerView have scroll?

To be able to scroll through a vertical list of items that is longer than the screen, you need to add a vertical scrollbar. Inside RecyclerView , add an android:scrollbars attribute set to vertical .

How do I make my RecyclerView scroll smooth?

Use the setHasFixedsize method If the height of our RecyclerView items is fixed then we should use the setHasFixedsize method in our XML of our card item. This will fix the height of our RecyclerView item and prevent it from increasing or decreasing the size of our Card Layout.

How do I stop refreshing RecyclerView data scroll to top position android?

Make a setDataList method in your adapter class. And set your updated list to adapter list. And then every time of calling API set that list to setDataList and call adapter. notifyDataSetChanged() method of your adapter class.

What is viewType in onCreateViewHolder?

This viewType variable is internal to the Adapter class. It's used in the onCreateViewHolder() and onBindViewHolder to inflate and populate the mapped layouts. Before we jump into the implementation of the Adapter class, let's look at the types of layouts that are defined for each view type.


2 Answers

Looks like this is a bug: https://code.google.com/p/android/issues/detail?id=203574

The best workaround seems to be Bart's answer to set the RecyclerView's LinearLayoutManager's AutoMeasure property to false.

  LinearLayoutManager llm = new LinearLayoutManager(context);   llm.setAutoMeasureEnabled(false);          recyclerView.setLayoutManager(llm); 

The set FixedSize to true solution had way too many side-effects...

RecyclerView.setHasFixedSize(true)

like image 64
Aace Avatar answered Oct 13 '22 21:10

Aace


I don't know why, but I used:

RecyclerView.setHasFixedSize(true) 

This worked for me. I hope it can help.

like image 30
zzq Avatar answered Oct 13 '22 21:10

zzq