BiliBili客戶端中瀑布流的圖片是怎麼做到寬度固定,根據圖片比例來設置長度呢?

-----------------[ 2016.3.8 update ]------------------------

為了方便後來者,還是把問題總結下吧。

結合各位所答,我的做法是給數據中增加了圖片的寬高比。

TuiJianViewHolder viewholder = (TuiJianViewHolder) holder;
//實現根據屏幕寬度計算高度
//獲取屏幕的寬度
int screenWidth = UIUtils.getScreenWidth();
//一列的寬度 = 屏幕寬度 - 圖片之間的間隙 / 2 (兩列)
int myWidth = (screenWidth - UIUtils.dip2px(16)) / 2;
//高度 = 一列的寬度 / 從數據中得到的寬高比
int height = (int) (myWidth / mDatas.get(position).ratio + 0.5f);
//最後給圖片重新布局即可
viewholder.mIcon.setLayoutParams(new RelativeLayout.LayoutParams(myWidth, height));

可以參考我的仿B站客戶端:

GitHub - liujia95/BiliPlayer

------------------------[ 原描述 ]------------------------


謝 @bbcallen 邀請, 我是B站客戶端程序猿

4.0版本之前的瀑布流布局使用一個開源的庫etsy/AndroidStaggeredGrid · GitHub並做了一些優化修改,見地址: https://github.com/ctiao/AndroidStaggeredGrid/commits/biliplayer-dev

4.0版本之後改用RecyclerView+StaggeredGridLayoutManager(http://developer.android.com/intl/zh-cn/reference/android/support/v7/widget/StaggeredGridLayoutManager.html)

推薦第二種(RecyclerView+ StaggeredGridLayoutManager)做法。

適應圖片高度寬度的方法,最好的辦法在服務端就有圖片尺寸的數據返回,根據圖片大小設置itemview的高寬(方法很多,可以動態修改layoutparams或者擴展view使用setMeasuredDimension) 如果因為條件限制服務端不能返回正確的圖片尺寸,可以自己預讀並緩存圖片頭部信息拿到圖片尺寸(使用http://developer.android.com/intl/zh-cn/reference/android/graphics/BitmapFactory.Options.html#inJustDecodeBounds),因為只是讀取頭部位元組所以效率並不會有太大影響.

回答完畢, 最後打個廣告,歡迎大家安裝並使用嗶哩嗶哩動畫客戶端嗶哩嗶哩手機客戶端 , 是傾注了我們大量心思與愛(?)研發的一款產品,感謝.

另外客戶端招聘開發攻城獅,歡迎對B站對移動端項目感興趣的同學投簡歷到wangyongrong#http://bilibili.com


我猜介面返回的數據肯定帶有圖片的長寬信息,所以可以得到圖片的比例。

可以根據此比例在綁定ItemView數據的時候先計算並動態的設置ItemView裡面的ImageView的高度。

這樣即使在圖片還沒有完成載入之前,佔位區域的寬高比例都和實際圖片一致。


  1. 伺服器保存圖片的寬高比 + 客戶端緩存圖片的寬高比;

  2. 寬度鋪滿,在通過寬度和寬高比計算當前圖片的高度,在布局渲染的時候預先設置高度;

  3. 優先使用本地的,如果計算出來的高度和圖片實際高度相差太遠的話會造成界面跳動;

  4. 推薦使用「交錯式GridLayout」來展示圖片,因為這種布局會使得界面上的圖片數量比較少,有利於優化流暢程度;

具體代碼請參考:kaedea/fresco-sample-usage · GitHub


看到有bilibili的官方開發回答了安卓端的方法,我這裡說一下iOS端的方法。

很簡單collectionview + 自定義layout.

原理是,每個cell寬度固定,屏幕的寬度-leftinset -rightinset-itemspace,然後除以2,高度需要根據寬度來進行等比例的縮放,有一個函數,AVMakeRectWithAspectRatioInsideRect可以幫助計算。然後layout通過代理獲知vc里數據源的圖片高度,在prepare方法里拿到之後。在layoutAttributesForElementsInRect賦值給attributes 就行了。

詳情請看我的這個博客,http://www.jianshu.com/p/427fef49af19


既然你知道是瀑布流,那麼問題就可以簡單地歸結為如何從網路獲取圖片並得到其寬高比例,根據寬高比去修改item的高度。

另外,在bilibili開源協議中提到,它是利用Facebook的fresco褲子來完成圖片載入的,有興趣你可以更具體化為,如何使用fresco獲得已載入的圖片的寬高。很多事,其實你只要多去搜搜


讓我來猜。。。

因為之前也做過類似的需求,所以也看過類似產品。

這種布局鼻祖是pinterest。pinterest的展示是先出來數據,然後載入圖片(還有不是這樣的?)。但是數據出來的時候,圖片的已經占坑了,寬高固定了,甚至做的更妙的是,占坑的placeholder圖片是根據最終圖片通過某種演算法得到的一個顏色值,例如,圖片主要是黃色,那麼placeholder也是黃色,可見,數據過來的時候,已經確定了圖片的樣式了,當然包括寬高。

當然是猜的,沒空抓包(:匿


1.請問你用的是什麼方式來做批量載入圖片的?如果用的是載入圖片的開源框架的話,有很多是在載入的時候就獲取到要載入的圖片的寬高,直接設定item中圖片的寬高就可以了,而且要設置好imageview的scaletype,這個在很多地方是要用到的;如果不是的話可以在後台獲取的數據中添加這些屬性返還給你,這樣你也可以做到動態設置。

2.我個人猜測是獲取屏幕寬度,減去左右的間隔,算出最終單個item的顯示寬度,然後同樣的如果載入用的是圖片載入的框架,直接可以獲取到寬高的直接設置imageview,不能獲取或者不使用圖片載入框架的讓後台給你寬高,算出寬度比例,進而算出長度比例,設置好scaletype就可以做到填充整個imageview。

個人淺見,android新手


數據介面返回尺寸,用recyclerview,我LOFTER就是這麼乾的!


伺服器返回圖片寬高,本地自己算。我們是這樣實現的


樓主問題解決了嗎?求指點求源碼,我也遇到這樣的問題


我感覺 應該是返回的圖片長寬 本地裁剪的。不然gd庫增加的伺服器負荷太重了


這個跟Ray家的一個collectionview教程一毛一樣


推薦閱讀:

Android應用開發大神用過這個網站嗎?該怎樣學習和使用?
Android 開發中有什麼經典的輪子值得自己去實現一遍?
做用戶界面設計,1920*1080 解析度智能電視的 SafeZone 應該是多大?
安卓手機上有哪些應用可以開發軟體?
如何在 Android 手機上實現抓包?

TAG:Android開發 | Android |