I'm trying to do this animation:
to insert a new item others move down as it does by default. but the first item and the second change. the first is inserted with ViewType 1 then the second switches the ViewType to 2. I currently manage 3 view types(adaptadorNotificaciones.java).
1 full size. notificacion_item1.xml
2 padding. notificacion_item2.xml
3 separator. section.xml
I extend from DefaultItemAnimator as follows (animadroNotificaciones):
public class animadroNotificaciones extends DefaultItemAnimator {
#Override
public boolean animateAdd(RecyclerView.ViewHolder holder){
return true;
}
public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, int fromX, int fromY, int toX, int toY){
return super.animateChange(oldHolder,newHolder,fromX,fromY,toX,toY);
}
#Override
public void onAnimationFinished(RecyclerView.ViewHolder holder){
super.onAnimationFinished(holder);
}
#Override
public boolean animateMove(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY){
return super.animateMove(holder,fromX,fromY,toX,toY);
}}
I'm also picturing it like a stack:
LinearLayoutManager llm = new LinearLayoutManager(this);
llm.setOrientation(LinearLayoutManager.VERTICAL);
llm.setReverseLayout(true);
llm.setStackFromEnd(true);
recyclerView.setLayoutManager(llm);
so when I add an item the scroll has to move up:
recyclerView.scrollToPosition(arreglo.size()-1);
The whole code to insert an item (adaptadorNotificaciones.java):
public void addNotificacion(ItemLista notificacion,RecyclerView recyclerView){
String mesAnterior = "";
String mesInsertado = "";
if(arreglo.size()!=0)
mesAnterior = ManejadorFechas.getFecha(arreglo.get(arreglo.size()-1).getTiempo(),false);
mesInsertado = ManejadorFechas.getFecha(notificacion.getTiempo(),false);
if(!mesInsertado.equals(mesAnterior) && arreglo.size()!=0){
arreglo.get(arreglo.size()-1).setTipo(2);
arreglo.add(new ItemLista(3,mesAnterior));
arreglo.add(notificacion);
notifyItemRangeChanged(arreglo.size()-3,arreglo.size()-1);
recyclerView.scrollToPosition(arreglo.size()-1);
}else if(arreglo.size()!=0){
arreglo.get(arreglo.size()-1).setTipo(2);
arreglo.add(notificacion);
notifyItemRangeChanged(arreglo.size()-2,arreglo.size()-1);
recyclerView.scrollToPosition(arreglo.size()-1);
}else{
arreglo.add(notificacion);
notifyItemInserted(arreglo.size()-1);
recyclerView.scrollToPosition(arreglo.size()-1);
}
}
but the above code gives me the next result:
I think It is caused by the following line:
notifyItemRangeChanged(arreglo.size()-3,arreglo.size()-1);
anyone has an idea how to fix this? Thanks in advance.
I solved it, this way:
rv.setItemAnimator(new animadroNotificaciones(){
#Override
public void onAnimationFinished(RecyclerView.ViewHolder viewHolder) {
adaptador.notifyDataSetChanged();
}
});
Related
I have been going at this problem for many days now with no end in sight, so any help would definetely be appreciated! This is the problem:
I have a room database and a recycler view where I display part of that database. And generally everything works fine. However, if I try to drag (thus switching the order) of two items with different viewtypes, the adapter drops the item back at his original place.
This previous stack overflow question displays the problem beautifully:Android RecyclerView: drag and drop over multiple ViewType
The code: (In the fragment java)
// Configuring RecycleView
RecyclerView recyclerView = root.findViewById(R.id.recyclerview_viewpager_schedule);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setHasFixedSize(true);
// configuring Adapter
daysAdapter = new DaysAdapter();
prevfrom = -1;
flagish = -1;
//daysAdapter.setHasStableIds(true);
recyclerView.setAdapter(daysAdapter);
daysViewModel.getNotesInDay(args.getInt(ARG_OBJECT)).observe(getViewLifecycleOwner(), new Observer<List<DayActivity>>() {
#Override
public void onChanged(List<DayActivity> dayActivities) {
//I use a flag in order for the list not to update onMove because that makes a weird looking effect. It updates later on and it works just fine!
if (flagish != 5) daysAdapter.submitList(dayActivities);
flagish = 1;
}
});
ItemTouchHelper mIth = new ItemTouchHelper(
new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN, 0) {
#RequiresApi(api = Build.VERSION_CODES.N)
#Override
public boolean onMove(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder, #NonNull RecyclerView.ViewHolder target) {
final int fromPos = viewHolder.getAdapterPosition();
final int toPos = target.getAdapterPosition();
Log.d("onMove", "From:" + fromPos);
Log.d("onMove", "to:" + toPos);
Log.d("STOP_HERE_please_1", fromPos + " " + toPos);
Bundle arguments = getArguments();
Log.d("STOP_HERE_3", String.valueOf(arguments.getInt(ARG_OBJECT)));
if (fromPos==toPos) return false;
//prevFrom is the previous fromPos in case the item hansn't been dropped yet
if (prevfrom == -1) prevfrom = fromPos;
if (prevfrom == toPos) return false;
getView().clearFocus();
// Change position
DayActivity lItem;
newList = new ArrayList<>();
int lIncrement = (fromPos<toPos) ? -1 : +1; // true if scroll down
int lMax = Integer.max(prevfrom, toPos);
int lMin = Integer.min(prevfrom, toPos);
List<DayActivity>oldList =daysAdapter.getOrdersBetween(lMin, lMax);
//This function (getOrdersBetween) gets the DayActivities whose positions are between those two values
for (int i=lMin; i<= lMax; i++) {
lItem = oldList.get(i);
if (i == fromPos) {
lItem.setOrder_Day(toPos);
} else
lItem.setOrder_Day(lItem.getOrder_Day() + lIncrement);
//The program uses the order to order the items in the recycler view
newList.add(lItem);
}
daysAdapter.notifyItemMoved(fromPos, toPos);
return true;
}
#Override
public boolean isLongPressDragEnabled() {
return true;
}
#Override
public boolean isItemViewSwipeEnabled() {
return false;
}
#Override
public void onSwiped(#NonNull RecyclerView.ViewHolder viewHolder, int direction) {
}
#Override
public void onSelectedChanged(#Nullable RecyclerView.ViewHolder viewHolder, int actionState) {
super.onSelectedChanged(viewHolder, actionState);
if (actionState == ACTION_STATE_DRAG)
viewHolder.itemView.setAlpha(0.5f);
}
#Override
public void clearView(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
viewHolder.itemView.setAlpha(1.0f);
flagish = 5;
if(newList != null) daysViewModel.updateList(newList);
prevfrom = -1;
}
I believe the problem is routed in the adapter.notifyitemmoved, but I haven't been able to solve it! Some people reccommended in other posts for me to make sethasStableIds(), but this function only lead notifyItemMoved to have a similar effect even if the two items have simiar viewtypes.
I don't think there is any need to overload this post with code from the adapter, but if anyone needs it, just let me know. Thanks!!!
NotifyItemMoved should work with different ViewTypes.
I assume you are using AsyncDiffer? Check if you override adapters getItemViewType(position) function correctly, maybe you are fetching position from AsyncDiffers current list which is not yet synced?
I have a ViewPager2 contains ScrollView.
What the problem is, when I try to get ScrollView of current page in onPageSelected(), it doesn't work.
Here I'd like to set previous scrollY to the ScrollView when user back to see selected page. (because scrollY is reset for some reason before that)
My code is below.
ViewPagerAdapter.java (edited)
public class ViewPagerAdapter extends RecyclerView.Adapter<ViewPagerAdapter.ViewHolder> {
private LayoutInflater mInflater;
private List<String> mText;
private ViewPager2 pager2;
MainActivity main;
public ViewPagerAdapter(Context context, List<String> data, ViewPager2 pager2, MainActivity main){
this.mInflater = LayoutInflater.from(context);
this.mText = data;
this.pager2 = pager2;
this.main = main;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType){
View view = mInflater.inflate(R.layout.tab_scroll_item, parent, false);
return new ViewPagerAdapter.ViewHolder(view);
}
#Override
public void onBindViewHolder(final ViewPagerAdapter.ViewHolder holder, int position){
holder.scrollView.setTag("scv_tab" + position);
holder.scrollView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
#Override
public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
if(scrollY != 0) {
main.setScrollY(scrollY, getPosition());
}
System.out.println("onScrollChanged : " + scrollY);
}
});
holder.textView.setEnabled(false);
holder.textView.setEnabled(true);
holder.textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, applyTextSize());
holder.textView.setText(mText.get(position));
holder.textView.setTag("tv_tab" + position);
}
#Override
public int getItemCount(){
return mText.size();
}
protected int getPosition(){
return pager2.getCurrentItem();
}
public class ViewHolder extends RecyclerView.ViewHolder{
ScrollView scrollView;
TextView textView;
public ViewHolder(View itemView){
super(itemView);
scrollView = itemView.findViewById(R.id.tab_scroll);
textView = itemView.findViewById(R.id.tab_textview);
}
}
[REVICED]onBindViewHolder
#Override
public void onBindViewHolder(final ViewPagerAdapter.ViewHolder holder, final int position){
holder.scrollView.setTag("scv_tab" + position);
holder.scrollView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
#Override
public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
if(scrollY != 0) {
main.storeScrollY(scrollY, position);
}
System.out.println("onScrollChanged : " + scrollY);
}
});
int y = main.retrieveScrollY(position);
holder.scrollView.setScrollY(y);
holder.textView.setEnabled(false);
holder.textView.setEnabled(true);
holder.textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, applyTextSize());
holder.textView.setText(mText.get(position));
holder.textView.setTag("tv_tab" + position);
}
MainActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(R.style.AppTheme);
super.onCreate(savedInstanceState);
...
mPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
#Override
public void onPageSelected(int position) {
super.onPageSelected(position);
if(!searchView.isIconified()){
searchView.setIconified(true);
}
if(highlightModel.getHighlitedOrNot(position)){
searchText.deleteTextHighlight(position);
highlightModel.setHighlitedOrNot(position, false);
}
int positionY[] = getScrollFromViewModel();
ScrollView sv = findScrollView(); // HERE IS THE PROBLEM
if(sv != null) {
sv.setScrollY(positionY[position]);
}else{
System.out.println("sv is null"); // ALWAYS SHOWS NULL
}
}
});
...
searchView = (SearchView) findViewById(R.id.searchview);
searchView.setOnSearchClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
fab.setVisibility(View.VISIBLE);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int actualResult = searchText.scrollToHighlightedWord(findTextView()
, findScrollView() // here findScrollView() works perfectly.
, searchResultIndex);
if(actualResult == (searchResultIndex + 1)) {
++searchResultIndex;
}else if(actualResult == searchResultIndex){
showToastAtMain("last word");
}else{
forOnClose();
}
}
});
}
});
private ScrollView findScrollView(){
ScrollView sv = mPager2.findViewWithTag("scv_tab" + mPager2.getCurrentItem());
return sv;
}
tab_scroll_item.xml (edited)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="#+id/tab1_layout">
<ScrollView
android:id="#+id/tab_scroll"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/tab_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:lineSpacingExtra="7dp"
android:textIsSelectable="true"
android:paddingStart="9dp"
android:paddingTop="9dp"
android:paddingEnd="9dp"/>
</ScrollView>
</LinearLayout>
Any advice is truly appreciated. Thank you for reading this long question.
onPageSelected will be called way earlier than selected page drawing mechanism, before any onCreateViewHolder and onBindViewHolder. I would advise you to "incject" somehow your data into your "page" (is it View or whole Fragment? that makes big difference) and in your case set this scroll position inside onBindViewHolder. This will make rendering of RecyclerView draw even first frame in correct scrolled position. Your way, even when you will wait some time for RecyclerView drawing, will make that onBindViewHolder will draw first frame on 0 scroll and your method will scroll a bit in next frames - this will be visible like some blink or fast-autoscroll (I think this behavior isn't intended)
edit - add proper method for setting scroll for your Adapter even before super call
#Override
public void onPageSelected(int position) {
int positionY[] = getScrollFromViewModel();
adapter.setScrollForPosition(positionY[position]);
super.onPageSelected(position);
...
for adapter
private final HashMap<Integer, Integer> scrollYHistory = new HashMap<>();
public void setScrollForPosition(int position, int scrollY){
scrollYHistory.put(position, scrollY);
}
use stored scrollY value in onBindViewHolder and clean entry in your HashMap
#Override
public void onBindViewHolder(final ViewPagerAdapter.ViewHolder holder, final int position){
Integer scrollY = scrollYHistory.remove(position);
if (scrollY == null) scrollYa = 0; // may be null if not stored yet!
holder.scrollView.setScrollY(scrollY);
...
also remove unnecessary reference to MainActivity main in adapter's constructor and variable inside, it already gets Context reference and doesn't (shouldn't) need to know which Activity is creating it
edit - expanding comment:
instead of calling scrollView.setScrollY straight inside onBindViewHolder you should set up your TextView at first, then wait for rendering it and then scrolling to proper position
#Override
public void onBindViewHolder(final ViewPagerAdapter.ViewHolder holder, final int position){
...
holder.textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, applyTextSize());
holder.textView.setText(mText.get(position));
...
holder.textView.post(new Runnable(){
// this will be called after nearest drawing
#Override
public void run() {
Integer scrollY = scrollYHistory.remove(position);
if (scrollY == null) scrollYa = 0; // may be null if not stored yet!
holder.scrollView.setScrollY(scrollY);
}
});
}
Thanks to snachmsm, I got to know that onPageSelected will be called way earlier than ViewPager2 drawing. And for some reason I found my solution using mPager2.postDelayed().
After adding these, I got NO null ScrollView here.
mPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
...
//Here I added onPageScrollStateChanged() and postDelayed() in it.
#Override
public void onPageScrollStateChanged(int state){
if(state == ViewPager2.SCROLL_STATE_SETTLING){
mPager2.postDelayed(new Runnable() {
#Override
public void run() {
int position = mPager2.getCurrentItem();
int y = scrollModel.getPreviousScrollY(position);
ScrollView sv = findScrollView();
sv.scrollTo(0, y);
}
}, 50);
}
}
});
}
I created custom LinearLayoutManager class.My goal is to smoothScrollToPosition with animation.Here is a my code:
public class LinearLayoutManagerWithSmoothScroller extends LinearLayoutManager {
private static final float MILLISECONDS_PER_INCH = 100f;
public LinearLayoutManagerWithSmoothScroller(Context context) {
super(context, VERTICAL, false);
}
#Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state,
int position) {
RecyclerView.SmoothScroller smoothScroller = new TopSnappedSmoothScroller(recyclerView.getContext());
smoothScroller.setTargetPosition(position);
startSmoothScroll(smoothScroller);
}
private class TopSnappedSmoothScroller extends LinearSmoothScroller {
public TopSnappedSmoothScroller(Context context) {
super(context);
}
#Override
public PointF computeScrollVectorForPosition(int targetPosition) {
return LinearLayoutManagerWithSmoothScroller.this
.computeScrollVectorForPosition(targetPosition);
}
#Override
protected float calculateSpeedPerPixel
(DisplayMetrics displayMetrics) {
return MILLISECONDS_PER_INCH/displayMetrics.densityDpi;
}
#Override
protected int getVerticalSnapPreference() {
return SNAP_TO_START;
}
}
}
Also,I created custom LayoutAnimation in RecyclerView.Here is a xml code
<layoutAnimation
xmlns:android="http://schemas.android.com/apk/res/android"
android:animation="#anim/item_animation_from_bottom"
android:delay="15%"
android:animationOrder="normal"
/>
And here is my java code.
leaderBoardAdapter = new SPGamificationLeaderBoardAdapter(response.list, getContext());
leaderBoardRecyclerView.setAdapter(leaderBoardAdapter);
leaderBoardRecyclerView.setHasFixedSize(true);
leaderBoardRecyclerView.setNestedScrollingEnabled(false);
LayoutAnimationController controller =
AnimationUtils.loadLayoutAnimation(getContext(), R.anim.layout_animation_from_bottom);
leaderBoardRecyclerView.setLayoutManager(smoothScroller);
leaderBoardRecyclerView.setLayoutAnimation(controller);
leaderBoardRecyclerView.scheduleLayoutAnimation();
leaderBoardRecyclerView.post(() -> leaderBoardRecyclerView.smoothScrollToPosition(getPosition(response)));
My problem is that, both options(smoothScrollToPosition and LayoutAnimation) does not working same time.I removed smoothScrollToPosition and layout animation worked ,and removed smoothScrollToPosition - layout animation has worked.
Is any way to use both functions same time? what's wrong in my code?
You can use the scrollToPosition(itemNo) for achieving your goal.
Like below:
recyclerview.scrollToPosition(20);
Using smoothScrollToPosition , items are scroll very fast thats why animation is not worked.
i use GridLayoutManager to RecyclerView but i require every four row this (provide image) ViewType
give me solution
This type view
Assumning all items have similar views Try This:
GridLayoutManager layoutManager = new GridLayoutManager(DashboardActivity.this, 2);
layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
#Override
public int getSpanSize(int position) {
if (positions you wish to have a different view) {
return 2;
}
return 1;
}
});
RecyclerView supports multiple viewtypes.
Take a look into this:
How to create RecyclerView with multiple view type?
#Override
public int getItemViewType(int position) {
//Every 5th view should be different
return position % 5;
}
#Override
public int getItemCount() {
return 2;
}
I have created a very simple project, displaying 28 images with StaggeredGridLayoutManager by recyclerview. but as I scroll the recyclerview it moves items for example from left to right or swap the column of left and right.
codes:
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
public class MainActivity extends Activity {
String mImageDir;
private RecyclerView mRecyclerView;
private StaggeredGridLayoutManager mLayoutManager;
MyRecyclerAdapter myRecyclerAdapter;
List<ImageModel> mImageList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = (RecyclerView)findViewById(R.id.recyclerview_rootview);
mLayoutManager = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);
mLayoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setHasFixedSize(false);
mImageList = new ArrayList<ImageModel>();
for (int i = 1; i < 29 ; i++) {
ImageModel img = new ImageModel();
img.setTitle("Image No " + i);
int drawableResourceId = this.getResources().getIdentifier("image"+String.valueOf(i), "drawable", this.getPackageName());
img.setResId(drawableResourceId);
mImageList.add(img);
}
myRecyclerAdapter = new MyRecyclerAdapter(MainActivity.this,mImageList);
mRecyclerView.setAdapter(myRecyclerAdapter);
}
}
And the adapter:
public class MyRecyclerAdapter extends RecyclerView.Adapter<MyRecyclerAdapter.ViewHolder> {
private List<ImageModel> mItems;
Context mContext;
public MyRecyclerAdapter(Context context,List<ImageModel> objects) {
mContext = context;
mItems = objects;
}
static class ViewHolder extends RecyclerView.ViewHolder{
public ImageView mImageView;
public TextView mTextView;
public View rootView;
public ViewHolder(View itemView) {
super(itemView);
rootView = itemView;
mImageView =(ImageView)itemView.findViewById(R.id.image);
mTextView =(TextView)itemView.findViewById(R.id.title);
}
}
#Override
public int getItemCount() {
return mItems.size();
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
ImageModel item = mItems.get(position);
Picasso.with(mContext).load(item.getResId()).into(holder.mImageView);
holder.mTextView.setText(item.getTitle());
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int arg1) {
LayoutInflater inflater =
(LayoutInflater) mContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
View convertView = inflater.inflate(R.layout.item, parent, false);
return new ViewHolder(convertView);
}
}
and a sample moving item:
http://i.imgur.com/FUapm2K.gif?1
if you play (scroll up and down) you can discover more interesting animation :-)
How to prevent that and having stable layout like an ordinary listview?
Edit
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
ImageModel item = mItems.get(position);
RelativeLayout.LayoutParams rlp = (RelativeLayout.LayoutParams)holder.mImageView.getLayoutParams();
float ratio = item.getHeight()/item.getWidth();
rlp.height = (int)(rlp.width * ratio);
holder.mImageView.setLayoutParams(rlp);
Picasso.with(mContext).load(item.getResId()).into(holder.mImageView);
holder.mTextView.setText(item.getTitle());
}
This is happening because SGLM does not keep any w/h information about the views. So each time a View is rebound, it gets the place holder size first and then the final size when the image is loaded.
Loading the actual image w/ different size (than place holder) triggers a new layout request, and during that layout request, SGLM detects that there will be gaps in the UI (or some item w/ higher position appears below an item w/ lower position) thus re-orders items w/ an animation.
You can avoid it by setting your place holder image to the dimensions of the actual image. If you don't have it ahead of time, you can save them after the image is loaded for the first-time and use it in the next onBind call.
What worked for me was to disable all animation on the recycle view when using StaggeredGridLayoutManager.
mRecyclerView.setItemAnimator(null);
You can create your own animator if you only want to restrict moving animations and keep the add and remove item animations.
You can try this
StaggeredGridLayoutManager manager = new StaggeredGridLayoutManager(2, OrientationHelper.VERTICAL);
manager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);
mRecyclerView.setLayoutManager(manager);
after you set this, you'll find there is a blank at the top when you scroll to the top. continue to set this
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
((StaggeredGridLayoutManager)recyclerView.getLayoutManager()).invalidateSpanAssignments();
}
});
It's work for me, I get this way somewhere. I hope it can help you!
Change this line
mLayoutManager.setGapStrategy(
StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS);
to this line
mLayoutManager.setGapStrategy(
StaggeredGridLayoutManager.GAP_HANDLING_NONE);
Add the following line at the end of the method:
holder.mImageView.requestLayout();
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
...
holder.mImageView.requestLayout();
}
This fixed the issue for me.
Maybe this is a more efficient way:
mBrandRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
if(newState == RecyclerView.SCROLL_STATE_IDLE){
mBrandRecyclerView.invalidateItemDecorations();
}
}
});
For more information:
https://github.com/ibosong/CommonItemDecoration
Set your recyclerview's height fixed and item height and width wrap-content for staggered-layout-manager
First set gap strategy like following code :
mLayoutManager = new StaggeredGridLayoutManager(SPAN_COUNT, StaggeredGridLayoutManager.VERTICAL);
mLayoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);
and then add your item to mItems and then use:
mAdapter.notifyItemInserted(mItems.size() - 1);
this method is better than using:
mAdapter.notifyDataSetChanged();