In my application, I have a list of elements implemented using RecyclerView. Under certain conditions, items can be moved to the very end of the list, and I need them to be animated. Therefore, at first I transfer the elements to the end to the data source (ArrayList in my case) and the call method notifyItemMoved(oldPosition, dataSet.size() - 1). Everything works fine, except when the item I'm moving to the end (it doesn't really matter if it is at the very end of the list or just below the bottom position) is either the topmost in the list or the very first partially visible . In such cases, not only the moved item is animated, but the entire list scrolls with it.
I thought it might be some kind of mess in my code, so I created a clean test program with the RecyclerView component, and the result was the same.
I think this is a mistake RecyclerViewbecause it is still a very green component, and Goggle continues to develop it, although I am sure that I am not the only one who has encountered such a problem, so I hope someone has a workaround for of this.
Here my code snippets Activity, RecyclerView.Adapterand layout.
activity
public class RecyclerViewActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycler_view);
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
RecyclerView.Adapter adapter = new RecyclerViewAdapter(recyclerView);
recyclerView.setAdapter(adapter);
recyclerView.addItemDecoration(new SimpleDividerItemDecoration(RecyclerViewActivity.this));
}
}
Adapter
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
private ArrayList<String> mDataSet;
private RecyclerView mRecyclerView;
public RecyclerViewAdapter(RecyclerView recyclerView) {
mRecyclerView = recyclerView;
mDataSet = new ArrayList<String>();
mDataSet.add("San Francisco");
mDataSet.add("Los Angeles");
mDataSet.add("Seattle");
mDataSet.add("Portland");
mDataSet.add("Sacramento");
mDataSet.add("San Diego");
mDataSet.add("Chicago");
mDataSet.add("Boston");
mDataSet.add("New York");
mDataSet.add("New Jersey");
mDataSet.add("Washington");
mDataSet.add("Miami");
mDataSet.add("New Orlean");
}
public RecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_recycler_view_item, parent, false);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int itemPosition = mRecyclerView.getChildAdapterPosition(v);
String item = mDataSet.get(itemPosition);
mDataSet.remove(itemPosition);
mDataSet.add(item);
notifyItemMoved(itemPosition, mDataSet.size() - 1);
}
});
return new ViewHolder(view);
}
public void onBindViewHolder(ViewHolder holder, int position) {
holder.itemName.setText(mDataSet.get(position));
}
@Override
public int getItemCount() {
return mDataSet.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
protected TextView itemName;
public ViewHolder(View v) {
super(v);
itemName = (TextView) v.findViewById(R.id.recycler_view_item_text);
}
}
}
Markup
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"/>
</LinearLayout>
And here is a video about how it looks:
https://youtu.be/kjG4oFE7o0w
1) Portland - approx.
2) Seattle - approx.
3) Los Angleles - ok.
4) San Francisco - NOT OK - the entire list is scrolled using the item.
, , .