Android waterfall Streaming Effect (mogujie.com)

Source: Internet
Author: User

Let's take a look at an example: (mogujie.com)

It looks like our gridview, but it doesn't look like it, because the item size is not fixed, it looks like it has a different flavor, indeed. just like our square corner image, the corner appears after the stone corner. below I will briefly introduce the implementation method.

First:

We define the number of columns in the configuration file, for example, 3 columns. We need to define three linearlayout columns, and then add the obtained image to it.

Main. xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:background="@android:color/background_light"    android:orientation="vertical" >    <include        android:id="@+id/progressbar"        layout="@layout/loading" />    <com.jj.waterfall.LazyScrollView        android:id="@+id/lazyscrollview"        android:layout_width="fill_parent"        android:layout_height="fill_parent"        android:layout_weight="1"        android:scrollbars="@null" >        <LinearLayout            android:layout_width="fill_parent"            android:layout_height="fill_parent"            android:background="@android:color/background_light"            android:orientation="horizontal"            android:padding="2dp" >            <LinearLayout                android:id="@+id/layout01"                android:layout_width="fill_parent"                android:layout_height="fill_parent"                android:layout_weight="1"                android:orientation="vertical" >            </LinearLayout>            <LinearLayout                android:id="@+id/layout02"                android:layout_width="fill_parent"                android:layout_height="fill_parent"                android:layout_weight="1"                android:orientation="vertical" >            </LinearLayout>            <LinearLayout                android:id="@+id/layout03"                android:layout_width="fill_parent"                android:layout_height="fill_parent"                android:layout_weight="1"                android:orientation="vertical" >            </LinearLayout>        </LinearLayout>    </com.jj.waterfall.LazyScrollView>    <TextView        android:id="@+id/loadtext"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:background="@drawable/loading_bg"        android:gravity="center"        android:padding="10dp"        android:text="Loading..."        android:textColor="@android:color/background_dark" /></LinearLayout>

Here, because there are a lot of images, we put the images in the assets file. If you want to pull data from the Internet, write additional parts by yourself.

@ Overridepublic void oncreate (bundle savedinstancestate) {super. oncreate (savedinstancestate); initview (); assetmanager = This. getassets (); // get the display image width image_width = (getwindowmanager (). getdefadisplay display (). getwidth ()-4)/3; try {image_filenames = arrays. aslist (assetmanager. list ("Images"); // get image name} catch (ioexception e) {e. printstacktrace ();} addimage (current_page, count );}

/***** Load more ** @ Param current_page * Current page number * @ Param count * displayed per page */private void addimage (INT current_page, int count) {for (INT x = current_page * count; x <(current_page + 1) * count & x <image_filenames.size (); X ++) {addbitmaptoimage (image_filenames.get (x ), y, x); y ++; If (Y> = 3) y = 0 ;}}

/***** Add imageview to layout ** @ Param ImagePath image name * @ Param J column * @ Param I line */Public void addbitmaptoimage (string ImagePath, Int J, int I) {imageview = getimageview (); asynctask = new imagedownloadasynctask (this, ImagePath, effeccute (); imageview. settag (I); If (j = 0) {layout01.addview (imageview);} else if (j = 1) {layout02.addview (imageview );} else if (j = 2) {layout03.addview (imageview);} imageview. setonclicklistener (New onclicklistener () {@ overridepublic void onclick (view v) {toast. maketext (mainactivity. this, "you clicked" + v. gettag () + "item", toast. length_short ). show ();}});}

The comments are quite clear. I believe everyone can understand them, so I will not explain them much.

Because waterfall stream is not a rule attempt, we cannot use listview to "add a button at the bottom to try and click to load more, which looks ugly ". Therefore, we 'd better slide to the low end for automatic loading.

The custom scrollview we use here, because we want to implement a sliding page, here we need to determine whether to perform paging and other operations.

Lazyscrollview. Java (this method is very practical .)

/***** Custom scrollview ** @ author Zhangjia **/public class lazyscrollview extends scrollview {Private Static final string tag = "lazyscrollview"; private handler; private view; public lazyscrollview (context) {super (context);} public lazyscrollview (context, attributeset attrs) {super (context, attrs);} public lazyscrollview (context, attributeset attrs, int defstyle) {s Uper (context, attrs, defstyle);} // obtain the total height public int computeverticalscrollrange () {return Super. computehorizontalscrollrange ();} public int computeverticalscroloffset () {return Super. computeverticalscroloffset ();}/***** initialize */private void Init () {This. setontouchlistener (ontouchlistener); handler = new handler () {@ overridepublic void handlemessage (Message MSG) {// process incoming messages heresup Er. handlemessage (MSG); Switch (msg. What) {Case 1: If (view. getmeasuredheight () <= getscrolly () + getheight () {If (onscrolllistener! = NULL) {onscrolllistener. onbottom () ;}} else if (getscrolly () = 0) {If (onscrolllistener! = NULL) {onscrolllistener. ontop () ;}} else {If (onscrolllistener! = NULL) {onscrolllistener. onscroll () ;}} break; default: Break ;}};} ontouchlistener = new ontouchlistener () {@ overridepublic Boolean ontouch (view V, motionevent event) {// todo auto-generated method stubswitch (event. getaction () {Case motionevent. action_down: break; Case motionevent. action_up: If (view! = NULL & onscrolllistener! = NULL) {handler. sendmessagedelayed (handler. obtainmessage (1), 200);} break; default: break;} return false ;};/*** get the reference view, mainly to get its measuredheight, then compare it with scrolly + getheight of the scroll bar. */Public void getview () {This. view = getchildat (0); If (view! = NULL) {Init () ;}/ *** define interface ** @ author admin **/public interface onscrolllistener {void onbottom (); void ontop (); void onscroll ();} private onscrolllistener; Public void setonscrolllistener (onscrolllistener) {This. onscrolllistener = onscrolllistener ;}

We also need a class that is asynchronously loaded for implementation. Some of my friends who have development experience must have used it many times. Here I will not show the code, you can click to download it (if you think it is good, please make sure to express it .)

By the way, we need to implement the onscrolllistener interface for lazyscrollview in mainactivity to listen on sliding to the bottom.

:


/*************************************** ***********************************/

Next I will introduce another method: (more flexible than above)

We dynamically add columns.

The configuration file will not be pasted. It is the same as the above example, but the nominal value contains a linearlayout layout.

Here we dynamically add column la S.

/***** Init view */Public void initview () {setcontentview (R. layout. main); lazyscrollview = (lazyscrollview) findviewbyid (R. id. waterfall_scroll); lazyscrollview. getview (); lazyscrollview. setonscrolllistener (this); waterfall_container = (linearlayout) findviewbyid (R. id. waterfall_container); progressbar = (linearlayout) findviewbyid (R. id. progressbar); loadtext = (textview) findviewbyid (R. id. loadtext); item_width = getwindowmanager (). getdefadisplay display (). getwidth ()/column; linearlayouts = new arraylist <linearlayout> (); // Add a column to waterfall_containerfor (INT I = 0; I <column; I ++) {linearlayout layout = new linearlayout (this); linearlayout. layoutparams itemparam = new linearlayout. layoutparams (item_width, layoutparams. wrap_content); layout. setorientation (linearlayout. vertical); layout. setlayoutparams (itemparam); linearlayouts. add (layout); waterfall_container.addview (layout );}}
/***** Get imageview ** @ Param imagename * @ return */Public imageview getimageview (string imagename) {bitmapfactory. options = getbitmapbounds (imagename); // create an image display object imageview = new imageview (this); layoutparams = new layoutparams (layoutparams. wrap_content, layoutparams. fill_parent); imageview. setlayoutparams (layoutparams); // imageview. setminimumheight (options. outheight); Im Ageview. setminimumwidth (options. outwidth); imageview. setpadding (2, 0, 2, 2); imageview. setbackgroundresource (R. drawable. image_border); If (options! = NULL) Options = NULL; return imageview;}/***** obtain the bitmapfactory of the corresponding image. options */Public bitmapfactory. options getbitmapbounds (string imagename) {int H, W; bitmapfactory. options = new bitmapfactory. options (); options. injustdecodebounds = true; // only the bitmap size is returned, which can reduce memory usage and prevent oom. inputstream is = NULL; try {is = assetmanager. open (File + "/" + imagename);} catch (ioexception e) {e. printstacktrace ();} bitmapfactory. decodestream (is, null, options); return options ;}

Here I modified it a little and added a border for the iamgeview to be displayed. This looks good. While we slide dynamically, the images gradually fill the border. this is the effect of mogujie.com.

:

The image is displayed in four columns, so the image is a little small. If you look at it carefully, you should see a lot of borders, and then the images are filled with borders one after another. this effect is more friendly to the above user experience.

Finally, a brief summary: The second method is recommended for waterfall streams, which is highly scalable. When the boss said four columns were too ugly and changed to three columns, so we only need to change column to 3. That's OK, simple.

Note: because the image volume is too large and it takes up too much space, I uploaded the image to the Internet and downloaded the file from the source code to the assets folder of the project. Then I ran the file and it was OK.

If there are any deficiencies, please leave a message to point out,

If you want source code, please leave your email. Thanks for you.

Due to the busy schedule, I uploaded the source code to the Internet. If necessary, download it by myself. If you have any questions, please leave a message. (remember to download the image and import it to the project)

Image download


Example 2 source code (method 1)


Example 1 source code (method 2)

Haha. If it helps you again, remember to give it a thumbs up.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.