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
Post a Comment