編輯:關於Android編程
本文實例講述了Android簡單實現自定義流式布局的方法。分享給大家供大家參考,具體如下:
首先來看一下 手淘HD - 商品詳情 - 選擇商品屬性 頁面的UI

商品有很多尺碼,而且展現每個尺碼所需要的View的大小也不同(主要是寬度),所以在從服務器端拉到數據之前,展現所有尺碼所需要的行數和每一行的個數都無法確定,因此不能直接使用GridView或ListView。
如果使用LinearLayout呢?
一個LinearLayout只能顯示一行,如果要展示多行,則每一行都要new一個LinearLayout出來,而且還必須要計算出每一個LinearLayout能容納多少個尺碼對應的View,實現起來也會比較復雜。
其實要實現這個功能,只需要借鑒一下CSS3的flex-box 就可以了。

要實現一個Android版本的flexbox,原理非常簡單,為了與Android的命名規范保持一致,我們稱之為FlowLayout。
1. 首先新建一個FlowLayout類,繼承自ViewGroup
2. 在onMeasure中根據 child views 計算出FlowLayout高度
3. 在onLayout中對child views 的進行布局(layout)
下面只列出了最核心的代碼片段,完整代碼已經放到Github上-AndroidFlowLayout,歡迎fork。
在onMeasure中計算FlowLayout的高度
// 遍歷所有的子View
for (int i = 0, childCount = getChildCount(); i < childCount; ++i) {
View childView = getChildAt(i);
// measure子View,並獲取它的寬度和高度
LayoutParams childLayoutParams = childView.getLayoutParams();
childView.measure(
getChildMeasureSpec(widthMeasureSpec, paddingLeft + paddingRight, childLayoutParams.width),
getChildMeasureSpec(heightMeasureSpec, paddingTop + paddingBottom, childLayoutParams.height));
int childWidth = childView.getMeasuredWidth();
int childHeight = childView.getMeasuredHeight();
// 計算當前行的高度(當前行所有子View中最高的那個)
lineHeight = Math.max(childHeight, lineHeight);
// 把當前child view放到上一個child view的右邊,如果放不下,則換行
if (childLeft + childWidth + paddingRight > myWidth) {
childLeft = paddingLeft;
childTop += mVerticalSpacing + lineHeight;
lineHeight = childHeight;
} else {
childLeft += childWidth + mHorizontalSpacing;
}
}
int wantedHeight = childTop + lineHeight + paddingBottom;
// 計算FlowLayout所需要高度
setMeasuredDimension(myWidth, resolveSize(wantedHeight, heightMeasureSpec));
在onLayout中對child views進行布局
代碼與onMeasure非常類似,只需要根據child view的寬度和高度放到指定位置即可。
for (int i = 0, childCount = getChildCount(); i < childCount; ++i) {
View childView = getChildAt(i);
if (childView.getVisibility() == View.GONE) {
continue;
}
int childWidth = childView.getMeasuredWidth();
int childHeight = childView.getMeasuredHeight();
lineHeight = Math.max(childHeight, lineHeight);
if (childLeft + childWidth + paddingRight > myWidth) {
childLeft = paddingLeft;
childTop += mVerticalSpacing + lineHeight;
lineHeight = childHeight;
}
// 關鍵代碼
childView.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
childLeft += childWidth + mHorizontalSpacing;
}
完整版代碼已經放到Github-FlowLayout,打出來的aar包已經上傳到了bintray,使用方式非常簡單,只需要在項目(project)對應的build.gradle中添加一條dependency即可。
compile 'com.liangfeizc:flowlayout:1.0.0@aar'
把aar包上傳到 jCenter
具體做法可參考 publishing gradle android library to jcenter
打包腳本可參考 flowlayout/build.gradle
更多關於Android相關內容感興趣的讀者可查看本站專題:《Android布局layout技巧總結》、《Android視圖View技巧總結》、《Android操作XML數據技巧總結》、《Android編程之activity操作技巧總結》、《Android資源操作技巧匯總》、《Android文件操作技巧匯總》、《Android操作SQLite數據庫技巧總結》、《Android操作json格式數據技巧總結》、《Android數據庫操作技巧總結》、《Android編程開發之SD卡操作方法匯總》、《Android開發入門與進階教程》及《Android控件用法總結》
希望本文所述對大家Android程序設計有所幫助。
Android View框架總結(六)View布局流程之Draw過程
View的Draw時序圖前面幾篇通過對View樹的measure和layout過程分析事,接下來將結合前兩步得到的測量值及在視圖中的位位置,開始進行繪制操作,一步比一步復
Android官方文檔之App Components(Intents and Intent Filters)
Android應用框架鼓勵開發者在開發應用時重用組件,本文將闡述如何用組件構建應用程序以及如何用intent將組件聯系起來。如需閱讀官方原文,請您點擊這個鏈接:《App
Android實現手勢滑動多點觸摸縮放平移圖片效果
現在app中,圖片預覽功能肯定是少不了的,用戶基本已經形成條件反射,看到小圖,點擊看大圖,看到大圖兩個手指開始進行放大,放大後,開始移動到指定部位。一、概述想要做到圖片支
android開發socket編程之udp發送實例分析
本文實例講述了android開發socket編程之udp發送實現方法。分享給大家供大家參考。具體分析如下:需要實現的功能:采用udp下的socket編程,當按下確認鍵,模