熱門標簽推薦的流式佈局

来源:http://www.cnblogs.com/libuyi/archive/2016/09/25/5906430.html
-Advertisement-
Play Games

【應用場景】:熱門標簽、推薦 【特點】: 在佈局內,隨意擺放任意個view,每行所擺放的view個數,根據實施計算出來的寬度,一旦當前要擺放的view寬度和之前擺放的所有view寬度加在一起,超過了佈局的寬度,那麼就把該view換行擺放。 【佈局】: <LinearLayout xmlns:andr ...


【應用場景】:熱門標簽、推薦

【特點】:

在佈局內,隨意擺放任意個view,每行所擺放的view個數,根據實施計算出來的寬度,一旦當前要擺放的view寬度和之前擺放的所有view寬度加在一起,超過了佈局的寬度,那麼就把該view換行擺放。

 

【佈局】:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<com.atguigu.p2pinvest0520.ui.FlowLayout
android:id="@+id/flow_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/holo_purple">

</com.atguigu.p2pinvest0520.ui.FlowLayout>

</LinearLayout>

 

【自定義FlowLayout】:

public class FlowLayout extends ViewGroup {
public FlowLayout(Context context) {
this(context, null);
}

public FlowLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);


}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);

//獲取寬度和高度的模式和數值
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);

//如果是至多模式,需要我們自己去測量佈局的寬度和高度
int width = 0;
int height = 0;

//聲明一行的寬度和高度
int lineWidth = 0;
int lineHeight = 0;

//獲取子視圖的個數
int childCount = getChildCount();
for(int i = 0;i < childCount;i++){
//獲取每一個子視圖的寬度和高度,邊距值
View childView = getChildAt(i);
//需要調用如下的方法之後,才可以獲取子視圖的寬高
measureChild(childView,widthMeasureSpec,heightMeasureSpec);
//獲取測量的寬高
int childWidth = childView.getMeasuredWidth();
int childHeight = childView.getMeasuredHeight();
//獲取邊距(要想獲取邊距,必須重寫當前類的方法generateLayoutParams())
MarginLayoutParams mp = (MarginLayoutParams) childView.getLayoutParams();

if(lineWidth + childWidth + mp.leftMargin + mp.rightMargin <= widthSize){//不換行
lineWidth += childWidth + mp.leftMargin + mp.rightMargin;
lineHeight = Math.max(lineHeight,childHeight + mp.topMargin + mp.bottomMargin);

}else{//換行
width = Math.max(width,lineWidth);
height += lineHeight;

//重置
lineWidth = childWidth + mp.leftMargin + mp.rightMargin;
lineHeight = childHeight + mp.topMargin + mp.bottomMargin;
}

//單獨的考慮一下最後一個!
if(i == childCount - 1){
width = Math.max(width,lineWidth);
height += lineHeight;
}


}

Log.e("TAG", "widthSize = " + widthSize + ",heightSize = " + heightSize);
Log.e("TAG", "width = " + width + ",height = " +height);
//設置當前佈局的寬高
setMeasuredDimension(widthMode == MeasureSpec.EXACTLY? widthSize : width,
heightMode == MeasureSpec.EXACTLY ? heightSize : height);
}

private List<Integer> allHeights = new ArrayList<>();//每一行的高度構成的集合
private List<List<View>> allViews = new ArrayList<>();//每一行view集合構成的集合

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {

int width = getWidth();//獲取佈局的寬度

//每一行的寬度和高度
int lineWidth = 0;
int lineHeight = 0;

 

int childCount = getChildCount();
List<View> lineViews = new ArrayList<>();//用於保存一行的所有的View
//目的:給allHeights 和 allViews 賦值
for(int i = 0; i < childCount; i++) {
View childView = getChildAt(i);
int childWidth = childView.getMeasuredWidth();
int childHeight = childView.getMeasuredHeight();

MarginLayoutParams mp = (MarginLayoutParams) childView.getLayoutParams();

if(lineWidth + childWidth + mp.leftMargin + mp.rightMargin <= width){//不換行
lineWidth += childWidth + mp.leftMargin + mp.rightMargin;
lineHeight = Math.max(lineHeight,childHeight + mp.topMargin + mp.bottomMargin);

lineViews.add(childView);
}else{//換行
allHeights.add(lineHeight);
allViews.add(lineViews);

lineViews = new ArrayList<>();
lineViews.add(childView);

lineWidth = childWidth + mp.leftMargin + mp.rightMargin;
lineHeight = childHeight + mp.topMargin + mp.bottomMargin;

}

//單獨考慮最後一個元素
if(i == childCount - 1){
allViews.add(lineViews);
allHeights.add(lineHeight);

}
}

Log.e("TAG", "allViews.size = " + allViews.size() + "allHeight.size = " + allHeights.size());

int lineNumber = allViews.size();

int x = 0;
int y = 0;

for(int i = 0; i < lineNumber; i++) {
List<View> singleLineViews = allViews.get(i);//獲取一行中元素構成的集合
int singleLineHeight = allHeights.get(i);//獲取一行的高度
for(View view : singleLineViews){//遍歷一行元素
MarginLayoutParams mp = (MarginLayoutParams) view.getLayoutParams();
int left = x + mp.leftMargin;
int top = y + mp.topMargin;
int right = left + view.getMeasuredWidth();
int bottom = top + view.getMeasuredHeight();


view.layout(left,top,right,bottom);

x += view.getMeasuredWidth() + mp.leftMargin + mp.rightMargin;


}
//換行
x = 0;
y += singleLineHeight;


}
}

@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
MarginLayoutParams mp = new MarginLayoutParams(getContext(), attrs);
return mp;

}
}

【動態添加TextView】

public class ProductHotFragment extends BaseFragment {


@Bind(R.id.flow_layout)
FlowLayout flowLayout;

//提供頁面要顯示的數據
private String[] datas = new String[]{"新手計劃", "樂享活系列90天計劃", "錢包", "30天理財計劃(加息2%)",
"林業局投資商業經營與大撈一筆", "中學老師購買車輛", "屌絲下海經商計劃", "新西游影視拍",
"Java培訓老師自己周轉", "HelloWorld", "C++-C-ObjectC-java", "Android vs ios", "演算法與數據結構", "JNI與NDK", "team working"};
private Random random;

@Override
protected RequestParams getParams() {
return null;
}

@Override
protected String getUrl() {
return null;
}

@Override
protected void initData(String content) {
random = new Random();
//1.動態的創建TextView
for(int i = 0; i < datas.length; i++) {

final TextView tv = new TextView(getActivity());

//設置TextView的屬性
tv.setText(datas[i]);
tv.setTextSize(UIUtils.dp2Px(10));

ViewGroup.MarginLayoutParams mp = new ViewGroup.MarginLayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
mp.leftMargin = UIUtils.dp2Px(8);
mp.rightMargin = UIUtils.dp2Px(8);
mp.topMargin = UIUtils.dp2Px(8);
mp.bottomMargin = UIUtils.dp2Px(8);
tv.setLayoutParams(mp);

//設置textView的背景
int red = random.nextInt(211);
int green = random.nextInt(211);
int blue = random.nextInt(211);
//測試一:
// tv.setBackground(DrawUtils.getDrawable(Color.rgb(red,green,blue),UIUtils.dp2Px(5)));

//測試二:
tv.setBackground(DrawUtils.getSelector(DrawUtils.getDrawable(Color.rgb(red, green, blue),UIUtils.dp2Px(5)),DrawUtils.getDrawable(Color.WHITE,UIUtils.dp2Px(5))));
//保存按下能顯示selector的效果,需要設置一個如下的屬性
// tv.setClickable(true);

//添加點擊事件,也是實現顯示selector的效果的一種方式
tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(ProductHotFragment.this.getActivity(), tv.getText(), Toast.LENGTH_SHORT).show();
}
});

//設置內邊距
int padding = UIUtils.dp2Px(5);
tv.setPadding(padding,padding,padding,padding);

// 2.添加到FlowLayout佈局中
flowLayout.addView(tv);
}

}

@Override
protected void initTitle() {

}

@Override
public int getLayoutId() {
return R.layout.fragment_product_hot;
}


}

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • hibernate入門 1、orm hibernate是一個經典的開源的orm[數據訪問中間件]框架 ORM( Object Relation Mapping)對象關係映射 通過 對象模型 操作 資料庫關係模型 hibernate處於項目的持久層位置,因此又稱為持久層框架 2、hibernate核心 ...
  • DOM基於樹形,SAX基於事件,DOM4J和JDOM基於底層API ...
  • 在剛學習SpringMVC框架整合時,你也許會產生疑問為什麼Spring.xml和SpringMVC.xml中都有註解過濾。 <context:component-scan base-package="myproject"> 和<context:component-scan base-package ...
  • 前言 最近要找工作,免不得要有一番筆試,今年好像突然就都流行線上筆試了,真是搞的我一塌糊塗。有的公司呢,不支持Python,Java我也不會,C有些數據結構又有些複雜,所以是時候把STL再看一遍了…不會告訴你距離上次使用可能已經有半年以上了。 STL是什麼 STL為C++的標準模版庫,又稱為C++泛 ...
  • 20160923 定義:將一個類的定義放在另一個類的內部; 從外部類的非靜態方法之外,創建某個內部類的對象:OutClassName.InnerClassName; 內部類擁有所有其外部類的成員的訪問權; 成員內部類不能含有static修飾的變數和方法,因為成員內部類需要先創建了外部類,才能創建它自 ...
  • SpringMVC又一個漂亮的web框架,他與Struts2並駕齊驅,Struts出世早而占據了一定優勢,下麵同樣做一個簡單的應用實例,介紹SpringMVC的基本用法,接下來的博客也將梳理一下Struts2和SpringMVC的一些異同,通過梳理和舊知識的聯繫,讓學習的成本變低,花很短的時間就可以 ...
  • 分別使用序數和enummap的結果: 序數: test1() 使用enummap,tes1t ...
  • 1. Python 文件I/O 本章只講述所有基本的的I/O函數,更多函數請參考Python標準文檔。 2.列印到屏幕 最簡單的輸出方法是用print語句,你可以給它傳遞零個或多個用逗號隔開的表達式。此函數把你傳遞的表達式轉換成一個字元串表達式,並將結果寫到標準輸出如下: 示例1: 運行示例1結果如 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...