天天看點

android 瀑布流效果(仿蘑菇街) .

我們還是來看一款示例:(蘑菇街)  

android 瀑布流效果(仿蘑菇街) .
android 瀑布流效果(仿蘑菇街) .

 看起來很像我們的gridview吧,不過又不像,因為item大小不固定的,看起來是不是别有一番風味,确實如此.就如我們的方角圖形,斯通見慣後也就出現了圓角.下面我簡單介紹下實作方法.

第一種:

我們在配置檔案中定義好列數.如上圖也就是3列.我們需要定義三個LinearLayout,然後把擷取到的圖檔add裡面就ok了.

main.xml

[java]  view plain copy

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:background="@android:color/background_light"  
  6.     android:orientation="vertical" >  
  7.     <include  
  8.         android:id="@+id/progressbar"  
  9.         layout="@layout/loading" />  
  10.     <com.jj.waterfall.LazyScrollView  
  11.         android:id="@+id/lazyscrollview"  
  12.         android:layout_width="fill_parent"  
  13.         android:layout_height="fill_parent"  
  14.         android:layout_weight="1"  
  15.         android:scrollbars="@null" >  
  16.         <LinearLayout  
  17.             android:layout_width="fill_parent"  
  18.             android:layout_height="fill_parent"  
  19.             android:background="@android:color/background_light"  
  20.             android:orientation="horizontal"  
  21.             android:padding="2dp" >  
  22.             <LinearLayout  
  23.                 android:id="@+id/layout01"  
  24.                 android:layout_width="fill_parent"  
  25.                 android:layout_height="fill_parent"  
  26.                 android:layout_weight="1"  
  27.                 android:orientation="vertical" >  
  28.             </LinearLayout>  
  29.             <LinearLayout  
  30.                 android:id="@+id/layout02"  
  31.                 android:layout_width="fill_parent"  
  32.                 android:layout_height="fill_parent"  
  33.                 android:layout_weight="1"  
  34.                 android:orientation="vertical" >  
  35.             </LinearLayout>  
  36.             <LinearLayout  
  37.                 android:id="@+id/layout03"  
  38.                 android:layout_width="fill_parent"  
  39.                 android:layout_height="fill_parent"  
  40.                 android:layout_weight="1"  
  41.                 android:orientation="vertical" >  
  42.             </LinearLayout>  
  43.         </LinearLayout>  
  44.     </com.jj.waterfall.LazyScrollView>  
  45.     <TextView  
  46.         android:id="@+id/loadtext"  
  47.         android:layout_width="fill_parent"  
  48.         android:layout_height="wrap_content"  
  49.         android:background="@drawable/loading_bg"  
  50.         android:gravity="center"  
  51.         android:padding="10dp"  
  52.         android:text="Loading..."  
  53.         android:textColor="@android:color/background_dark" />  
  54. </LinearLayout>  

在這裡因為圖檔很多就把圖檔放在assets檔案中,如果想從網上拉取資料,自己寫額外部分.

[java]  view plain copy

  1. @Override  
  2.     public void onCreate(Bundle savedInstanceState) {  
  3.         super.onCreate(savedInstanceState);  
  4.         InitView();  
  5.         assetManager = this.getAssets();  
  6.         // 擷取顯示圖檔寬度  
  7.         Image_width = (getWindowManager().getDefaultDisplay().getWidth() - 4) / 3;  
  8.         try {  
  9.             image_filenames = Arrays.asList(assetManager.list("images"));// 擷取圖檔名稱  
  10.         } catch (IOException e) {  
  11.             e.printStackTrace();  
  12.         }  
  13.         addImage(current_page, count);  
  14.     }  

[java]  view plain copy

  1.     private void addImage(int current_page, int count) {  
  2.         for (int x = current_page * count; x < (current_page + 1) * count  
  3.                 && x < image_filenames.size(); x++) {  
  4.             addBitMapToImage(image_filenames.get(x), y, x);  
  5.             y++;  
  6.             if (y >= 3)  
  7.                 y = 0;  
  8.         }  
  9.     }  

[java]  view plain copy

  1.     public void addBitMapToImage(String imagePath, int j, int i) {  
  2.         ImageView imageView = getImageview();  
  3.         asyncTask = new ImageDownLoadAsyncTask(this, imagePath, imageView,  
  4.                 Image_width);  
  5.         asyncTask.setProgressbar(progressbar);  
  6.         asyncTask.setLoadtext(loadtext);  
  7.         asyncTask.execute();  
  8.         imageView.setTag(i);  
  9.         if (j == 0) {  
  10.             layout01.addView(imageView);  
  11.         } else if (j == 1) {  
  12.             layout02.addView(imageView);  
  13.         } else if (j == 2) {  
  14.             layout03.addView(imageView);  
  15.         }  
  16.         imageView.setOnClickListener(new OnClickListener() {  
  17.             @Override  
  18.             public void onClick(View v) {  
  19.                 Toast.makeText(MainActivity.this,  
  20.                         "您點選了" + v.getTag() + "個Item", Toast.LENGTH_SHORT)  
  21.                         .show();  
  22.             }  
  23.         });  
  24.     }  

注釋已經很明确,相信大家都看的明白,我就不過多解釋了.

因為瀑布流不是一個規則的試圖,是以我們不可能用listview那種“底部加一個按鈕試圖,點選加載更多,這樣看起來很難看”。是以我們最好滑動到低端自動加載.

我們這裡用到的自定義ScrollView,因為我們要實作下滑分頁,這裡要判斷是否要進行分頁等操作.

LazyScrollView.java (這個法很實用哦.)

[java]  view plain copy

  1. public class LazyScrollView extends ScrollView {  
  2.     private static final String tag = "LazyScrollView";  
  3.     private Handler handler;  
  4.     private View view;  
  5.     public LazyScrollView(Context context) {  
  6.         super(context);  
  7.     }  
  8.     public LazyScrollView(Context context, AttributeSet attrs) {  
  9.         super(context, attrs);  
  10.     }  
  11.     public LazyScrollView(Context context, AttributeSet attrs, int defStyle) {  
  12.         super(context, attrs, defStyle);  
  13.     }  
  14.     // 這個獲得總的高度  
  15.     public int computeVerticalScrollRange() {  
  16.         return super.computeHorizontalScrollRange();  
  17.     }  
  18.     public int computeVerticalScrollOffset() {  
  19.         return super.computeVerticalScrollOffset();  
  20.     }  
  21.     private void init() {  
  22.         this.setOnTouchListener(onTouchListener);  
  23.         handler = new Handler() {  
  24.             @Override  
  25.             public void handleMessage(Message msg) {  
  26.                 // process incoming messages here  
  27.                 super.handleMessage(msg);  
  28.                 switch (msg.what) {  
  29.                 case 1:  
  30.                     if (view.getMeasuredHeight() <= getScrollY() + getHeight()) {  
  31.                         if (onScrollListener != null) {  
  32.                             onScrollListener.onBottom();  
  33.                         }  
  34.                     } else if (getScrollY() == 0) {  
  35.                         if (onScrollListener != null) {  
  36.                             onScrollListener.onTop();  
  37.                         }  
  38.                     } else {  
  39.                         if (onScrollListener != null) {  
  40.                             onScrollListener.onScroll();  
  41.                         }  
  42.                     }  
  43.                     break;  
  44.                 default:  
  45.                     break;  
  46.                 }  
  47.             }  
  48.         };  
  49.     }  
  50.     OnTouchListener onTouchListener = new OnTouchListener() {  
  51.         @Override  
  52.         public boolean onTouch(View v, MotionEvent event) {  
  53.             // TODO Auto-generated method stub  
  54.             switch (event.getAction()) {  
  55.             case MotionEvent.ACTION_DOWN:  
  56.                 break;  
  57.             case MotionEvent.ACTION_UP:  
  58.                 if (view != null && onScrollListener != null) {  
  59.                     handler.sendMessageDelayed(handler.obtainMessage(1), 200);  
  60.                 }  
  61.                 break;  
  62.             default:  
  63.                 break;  
  64.             }  
  65.             return false;  
  66.         }  
  67.     };  
  68.     public void getView() {  
  69.         this.view = getChildAt(0);  
  70.         if (view != null) {  
  71.             init();  
  72.         }  
  73.     }  
  74.     public interface OnScrollListener {  
  75.         void onBottom();  
  76.         void onTop();  
  77.         void onScroll();  
  78.     }  
  79.     private OnScrollListener onScrollListener;  
  80.     public void setOnScrollListener(OnScrollListener onScrollListener) {  
  81.         this.onScrollListener = onScrollListener;  
  82.     }  

我們還需要一個類, 異步加載實作 ,我想有開發經驗的朋友一定用過好多次了,這裡就不展示代碼了,想看的朋友,可以點選下載下傳( 如果認為還不錯的話,請您一定要表示一下哦. )

對了,忘記一點,我們還需要對MainActivity 中的lazyScrollView實作OnScrollListener接口,對滑動到底部進行監聽.

效果圖:

android 瀑布流效果(仿蘑菇街) .

下面我介紹另外一種做法:(相對上面更靈活)

我們動态添加列.

配置檔案就不貼了,和上面那例子一樣,隻不過裡面值包含一個LinearLayout布局.

在這裡我們動态添加列布局.

[java]  view plain copy

  1.     public void initView() {  
  2.         setContentView(R.layout.main);  
  3.         lazyScrollView = (LazyScrollView) findViewById(R.id.waterfall_scroll);  
  4.         lazyScrollView.getView();  
  5.         lazyScrollView.setOnScrollListener(this);  
  6.         waterfall_container = (LinearLayout) findViewById(R.id.waterfall_container);  
  7.         progressbar = (LinearLayout) findViewById(R.id.progressbar);  
  8.         loadtext = (TextView) findViewById(R.id.loadtext);  
  9.         item_width = getWindowManager().getDefaultDisplay().getWidth() / column;  
  10.         linearLayouts = new ArrayList<LinearLayout>();  
  11.         // 添加列到waterfall_container  
  12.         for (int i = 0; i < column; i++) {  
  13.             LinearLayout layout = new LinearLayout(this);  
  14.             LinearLayout.LayoutParams itemParam = new LinearLayout.LayoutParams(  
  15.                     item_width, LayoutParams.WRAP_CONTENT);  
  16.             layout.setOrientation(LinearLayout.VERTICAL);  
  17.             layout.setLayoutParams(itemParam);  
  18.             linearLayouts.add(layout);  
  19.             waterfall_container.addView(layout);  
  20.         }  
  21.     }  

[java]  view plain copy

  1.     public ImageView getImageview(String imageName) {  
  2.         BitmapFactory.Options options = getBitmapBounds(imageName);  
  3.         // 建立顯示圖檔的對象  
  4.         ImageView imageView = new ImageView(this);  
  5.         LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT,  
  6.                 LayoutParams.FILL_PARENT);  
  7.         imageView.setLayoutParams(layoutParams);  
  8.         //  
  9.         imageView.setMinimumHeight(options.outHeight);  
  10.         imageView.setMinimumWidth(options.outWidth);  
  11.         imageView.setPadding(2, 0, 2, 2);  
  12.         imageView.setBackgroundResource(R.drawable.image_border);  
  13.         if (options != null)  
  14.             options = null;  
  15.         return imageView;  
  16.     }  
  17.     public BitmapFactory.Options getBitmapBounds(String imageName) {  
  18.         int h, w;  
  19.         BitmapFactory.Options options = new BitmapFactory.Options();  
  20.         options.inJustDecodeBounds = true;// 隻傳回bitmap的大小,可以減少記憶體使用,防止OOM.  
  21.         InputStream is = null;  
  22.         try {  
  23.             is = assetManager.open(file + "/" + imageName);  
  24.         } catch (IOException e) {  
  25.             e.printStackTrace();  
  26.         }  
  27.         BitmapFactory.decodeStream(is, null, options);  
  28.         return options;  
  29.     }  

在這裡我稍微修改了下,為要顯示的iamgeview添加一個邊框,這樣看起來效果不錯,我們動态滑動的同時, 然後圖檔陸續的填充邊框.蘑菇街就是這種效果哦.

 效果圖:

android 瀑布流效果(仿蘑菇街) .
android 瀑布流效果(仿蘑菇街) .
android 瀑布流效果(仿蘑菇街) .

顯示成4列,是以圖檔有點小,仔細看的話,你應該可以看到有好多邊框,然後圖檔陸續的填充邊框.這種效果感覺對上面那個使用者體驗更友好些.

最後簡單總結下:針對瀑布流最好使用第二種方法,這種可擴充性比較大,哪天老大說四列太醜了,改成三列,那麼我們隻需要把column改成3就ok了,簡單吧。

注意:由于圖檔量太多,占用空間太大,是以我将圖檔上傳到網上,擷取源碼的同學下載下傳該檔案放到項目的assets檔案夾下,然後運作就ok了.

如果有不足之處,請留言指出,  

想要源碼請留郵箱.Thanks for you 。

由于比較繁忙,我将源碼上傳網上,如有需要,自行下載下傳,如有問題,請留言.(記得下載下傳圖檔導入項目裡面)

圖檔下載下傳

示例二源碼(第一種方式)

示例一源碼(第二種方式)

哈哈,如果對您又幫助的話,記得贊一個哦