android - Weird behavior when scrolling StaggeredGridLayout -


i have recyclerview show images loaded picasso. have different aspect ratios, i'm using staggeredgridlayoutmanager. looks good, when scrolling , new image shows up, images move or down little, getting been relocated. dont stay in same place.

the thing is, if use gridlayout, works perfectly, looks having different item's sizes messes up.

this activitymain class:

protected void oncreate(bundle savedinstancestate)     {         super.oncreate(savedinstancestate);          // especificamos el layout 'products_grid.xml'         setcontentview(r.layout.products_grid);          _initdata();         _initauxviews();         _inittoolbar();         _initnavigationdrawers();         _initanimations();          new connecttoserver().execute();     }    protected void _initrecyclerview() {        mproductsrecyclerview = (recyclerview)findviewbyid(r.id.grid_recycler);     mstaggeredgridlayoutmanager = new staggeredgridlayoutmanager(2, staggeredgridlayoutmanager.vertical);     mproductadapter = new productsgridadapter(this, mproductsdisplayedlist);      mproductsrecyclerview.setlayoutmanager(mstaggeredgridlayoutmanager);     mproductsrecyclerview.setadapter(mproductadapter);     mproductsrecyclerview.setonscrolllistener(new recyclerview.onscrolllistener()             {                ...             } } 

main.xml, have custom recyclerview, not affect, checked it.

<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.coordinatorlayout     xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:app="http://schemas.android.com/apk/res-auto"     android:id="@+id/coordinator_layout"     android:layout_width="match_parent"     android:layout_height="match_parent">      <android.support.v4.widget.drawerlayout         android:id="@+id/drawer_layout"         android:layout_width="match_parent"         android:layout_height="match_parent"         android:background="@drawable/shop_background_bw">          <!-- contenido principal -->         <framelayout             android:layout_width="match_parent"             android:layout_height="wrap_content">              <!-- recylcer grid -->             <com.wallakoala.wallakoala.views.gridrecyclerview                 android:id="@+id/grid_recycler"                 android:layout_width="match_parent"                 android:layout_height="match_parent"                 android:scrollbars="none"                 android:cliptopadding="false"                 android:paddingtop="?attr/actionbarsize"                 android:layoutanimation="@anim/grid_layout_animation"/>              <!-- toolbar -->             <include android:id="@+id/appbar"                 layout="@layout/toolbar">              </include>              <!-- loading view -->             <com.wang.avi.avloadingindicatorview                 android:id="@+id/avloadingindicatorview"                 android:layout_width="125dp"                 android:layout_height="125dp"                 android:layout_gravity="center"                 android:visibility="gone"                 app:indicator="ballcliprotate"                 app:indicator_color="@color/coloraccent"/>              <!-- texto de no prductos -->             <textview                 android:id="@+id/nodata_textview"                 android:layout_width="wrap_content"                 android:layout_height="wrap_content"                 android:layout_margintop="@dimen/action_bar_height"                 android:layout_gravity="center_horizontal"                 android:visibility="gone"                 android:paddingtop="@dimen/action_bar_height"                 android:textappearance="?android:attr/textappearancemedium"                 android:text="@string/nodata_message"                 android:textsize="20sp"                 android:textcolor="@color/colortext"/>          </framelayout>          <include layout="@layout/left_navigation_drawer"/>      </android.support.v4.widget.drawerlayout>  </android.support.design.widget.coordinatorlayout> 

item_grid.xml

<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.cardview     xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:app="http://schemas.android.com/apk/res-auto"     android:id="@+id/card_item"     android:layout_width="match_parent"     android:layout_height="match_parent"     app:cardpreventcorneroverlap="false"     app:cardelevation="4dp"     app:cardcornerradius="4dp"     app:cardusecompatpadding="true">      <framelayout         android:layout_width="match_parent"         android:layout_height="match_parent">          <!-- loading view -->         <com.wang.avi.avloadingindicatorview             android:id="@+id/avloadingitem"             android:layout_width="50dp"             android:layout_height="50dp"             android:layout_gravity="center"             android:visibility="gone"             app:indicator="ballcliprotate"             app:indicator_color="@color/coloraccent"/>          <!-- background-->         <com.makeramen.roundedimageview.roundedimageview             android:id="@+id/grid_background"             android:layout_width="match_parent"             android:layout_height="200dp"             android:background="@color/colortext"             android:alpha="0.2"             android:visibility="gone"             app:riv_corner_radius_bottom_left="4dp"             app:riv_corner_radius_bottom_right="4dp"             app:riv_corner_radius_top_left="4dp"             app:riv_corner_radius_top_right="4dp"/>          <!-- main image-->         <com.makeramen.roundedimageview.roundedimageview             android:id="@+id/grid_image"             android:layout_width="match_parent"             android:layout_height="match_parent"             android:adjustviewbounds="true"             app:riv_corner_radius_bottom_left="4dp"             app:riv_corner_radius_bottom_right="4dp"             app:riv_corner_radius_top_left="4dp"             app:riv_corner_radius_top_right="4dp"/>          <!-- footer -->         <relativelayout             android:id="@+id/footer"             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:layout_gravity="bottom"             android:alpha="0.75">              <!-- info -->             <include android:id="@+id/extrainfo"                 layout="@layout/product_footer_extra"                 android:layout_width="match_parent"                 android:layout_height="wrap_content"                 android:visibility="visible"/>              <!-- info principal -->             <include android:id="@+id/mainfooter"                 layout="@layout/product_footer"                 android:layout_height="@dimen/footer_height"                 android:layout_width="match_parent"                 android:layout_below="@id/extrainfo"/>          </relativelayout>      </framelayout>  </android.support.v7.widget.cardview> 

edit: adapter code:

public class productsgridadapter extends recyclerview.adapter<productsgridadapter.productholder> {     /* constants */     private static final string tag = "cuoka";     private static final string package = "com.wallakoala.wallakoala";      /* context */     private static context mcontext;      /* data */     private static list<product> mproductlist;      public static class productholder extends recyclerview.viewholder implements view.onclicklistener     {         private product mproduct;          private imagebutton mfavimagebutton;         private imageview mproductimageview;         private imageview merrorimageview;         private view mloadingview;         private view mbackgroundview;         private view mproductfooterview, mproductfooterextraview, mproductfootermainview;         private textview mtitletextview, msubtitletextview, mnametextview, mpricetextview;          private animation scaleupfooterextra, scaledownfooterextra;          public productholder(view itemview)         {             super(itemview);              merrorimageview   = (imageview)itemview.findviewbyid(r.id.broken_image);             mtitletextview    = (textview)itemview.findviewbyid(r.id.footer_title);             msubtitletextview = (textview)itemview.findviewbyid(r.id.footer_subtitle);             mproductimageview = (imageview)itemview.findviewbyid(r.id.grid_image);             mfavimagebutton   = (imagebutton)itemview.findviewbyid(r.id.footer_fav_button);             mnametextview     = (textview)itemview.findviewbyid(r.id.name);             mpricetextview    = (textview)itemview.findviewbyid(r.id.price);              mbackgroundview         = itemview.findviewbyid(r.id.grid_background);             mloadingview            = itemview.findviewbyid(r.id.avloadingitem);             mproductfooterview      = itemview.findviewbyid(r.id.footer);             mproductfooterextraview = itemview.findviewbyid(r.id.extrainfo);             mproductfootermainview  = itemview.findviewbyid(r.id.mainfooter);              mproductfooterview.setonclicklistener(this);             //mproductimageview.setonclicklistener(this);              scaleupfooterextra = animationutils.loadanimation(mcontext, r.anim.scale_up);             scaledownfooterextra = animationutils.loadanimation(mcontext, r.anim.scale_down);         }          public void bindproduct(product product)         {             /* inicializamos los textviews */             mtitletextview.settext(product.getshop());             msubtitletextview.settext(product.getcolors().get(0).getreference());             mnametextview.settext(product.getname());             mpricetextview.settext(string.format("%.2f", product.getprice()) + "€");              /* ocultamos la info, importante. cosas malas pasan si no se pone. tambien la imagen de error. */             mproductfooterextraview.setvisibility(view.gone);             mproductfootermainview.setvisibility(view.gone);             merrorimageview.setvisibility(view.gone);              /* mostramos la view de carga y el background */             mloadingview.setvisibility(view.visible);              mbackgroundview.setvisibility(view.visible);              /* ponemos el icono del corazon. */             mfavimagebutton.setbackgroundresource(r.drawable.ic_favorite_border_white);              /* cargamos la imagen usando picasso */             string url = product.getcolors().get(0).getimages().get(0).getpath().replaceall(".jpg", "_small.jpg");             picasso.with(mcontext)                    .load(url)                    .into(mproductimageview, new callback() {                        @override                        public void onsuccess() {                            mbackgroundview.setvisibility(view.gone);                            mloadingview.setvisibility(view.gone);                            mproductfootermainview.setvisibility(view.visible);                        }                         @override                        public void onerror() {                            mloadingview.setvisibility(view.gone);                            merrorimageview.setvisibility(view.visible);                        }                    });              mproduct = product;         }      public productsgridadapter(context context, list<product> productlist)     {         mcontext = context;         mproductlist = productlist;     }      public void updateproductlist(list<product> productlist)     {         mproductlist = productlist;     }      @override     public productholder oncreateviewholder(viewgroup viewgroup, int viewtype)     {         view itemview = layoutinflater.from(viewgroup.getcontext())                                       .inflate(r.layout.product_item_grid                                                     , viewgroup                                                     , false );          return new productholder(itemview);     }      @override     public void onbindviewholder(final productholder productholder, int pos)     {         productholder.bindproduct(mproductlist.get(pos));     }      @override     public int getitemcount()     {         return mproductlist.size();     } } 

edit 2: i've found out what's going on. cardview firstly created without image, when it's loaded, layout redrawn, therefore weird movement produced. tried this:

when image first loaded, save height of it, , when recyclerview scrolled up, set background image of cardview height saved has same dimensions image, , should trick. doesnt. tried, code belongs holder constructor in adapter.

        final viewtreeobserver mproductimageviewtreeobserver = mproductimageview.getviewtreeobserver();         final viewtreeobserver mbackgroundtreeobserver = mbackgroundview.getviewtreeobserver();         mproductimageviewtreeobserver.addongloballayoutlistener(new viewtreeobserver.ongloballayoutlistener()         {             @override             public void ongloballayout()             {                 if (mproductheight != mproductimageview.getheight())                 {                     mproductheight = mproductimageview.getheight();                 }             }         });          mbackgroundtreeobserver.addonpredrawlistener(new viewtreeobserver.onpredrawlistener()         {             @override             public boolean onpredraw()             {                 if((mproductheight > 0) && (mproductheight != mbackgroundview.getheight()))                 {                     mbackgroundview.getlayoutparams().height = mproductheight;                 }                  return true;             }         }); 

does have clue of what's wrong?

thanks in advance,

i found solution myself. trick save aspect ratio when loading image first time target object.

then, in onprepareload, check if image has been loaded previously. if so, use aspect ratio stored set final height, way, there's no readjustment , scroll works smoothly.

mtarget = new target()         {             @override             public void onbitmaploaded(bitmap bitmap, picasso.loadedfrom from)             {                 mloadingview.setvisibility(view.gone);                 mproductfootermainview.setvisibility(view.visible);                  mproductimageview.getlayoutparams().height = viewgroup.layoutparams.wrap_content;                 mproductimageview.setbackgroundcolor(-1);                 mproductimageview.setalpha(1.0f);                   if (mproductbitmaparray[position] == 0.0f)                     mproductbitmaparray[position] = (double)bitmap.getheight() / (double)bitmap.getwidth();                  mproductimageview.setimagebitmap(bitmap);             }              @override             public void onbitmapfailed(drawable errordrawable)             {                 ... stuff             }              @override             public void onprepareload(drawable placeholderdrawable)             {                 mproductimageview.setimagebitmap(null);                  if (mproductbitmaparray[position] != 0)                     mproductimageview.getlayoutparams().height = (int)(mproductimageview.getwidth()                                                                             * mproductbitmaparray[position]);                 else                     mproductimageview.getlayoutparams().height = 600;                  mproductimageview.setbackgroundcolor(mcontext.getresources().getcolor(r.color.colortext));                 mproductimageview.setalpha(0.1f);             }         }; 

Comments

Popular posts from this blog

authentication - Mongodb revoke acccess to connect test database -

r - Update two sets of radiobuttons reactively - shiny -

ios - Realm over CoreData should I use NSFetchedResultController or a Dictionary? -