熱門標簽推薦的流式佈局

来源: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
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...