編輯:關於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程序設計有所幫助。
View的Draw時序圖前面幾篇通過對View樹的measure和layout過程分析事,接下來將結合前兩步得到的測量值及在視圖中的位位置,開始進行繪制操作,一步比一步復
Android應用框架鼓勵開發者在開發應用時重用組件,本文將闡述如何用組件構建應用程序以及如何用intent將組件聯系起來。如需閱讀官方原文,請您點擊這個鏈接:《App
現在app中,圖片預覽功能肯定是少不了的,用戶基本已經形成條件反射,看到小圖,點擊看大圖,看到大圖兩個手指開始進行放大,放大後,開始移動到指定部位。一、概述想要做到圖片支
本文實例講述了android開發socket編程之udp發送實現方法。分享給大家供大家參考。具體分析如下:需要實現的功能:采用udp下的socket編程,當按下確認鍵,模