Android自定義控件ViewGroup實現(xiàn)標簽云
本文實例為大家分享了Android自定義控件ViewGroup實現(xiàn)標簽云的具體代碼,供大家參考,具體內(nèi)容如下
實現(xiàn)的功能:

基本繪制流程:
構造函數(shù)獲取自定義屬性
onMeasure()方法,測量子控件的大小
onLayout()方法,對子控件進行布局
1、自定義屬性
<resources>
<declare-styleable name="TabsViewGroup">
<attr name="tabVerticalSpace" format="dimension" />
<attr name="tabHorizontalSpace" format="dimension" />
</declare-styleable>
</resources>
2、構造函數(shù)中獲取自定義屬性值
public TabsViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray attrArray = context.obtainStyledAttributes(attrs, R.styleable.TabsViewGroup);
if (attrArray != null) {
childHorizontalSpace = attrArray.getDimensionPixelSize(R.styleable.TabsViewGroup_tabHorizontalSpace, 0);
childVerticalSpace = attrArray.getDimensionPixelSize(R.styleable.TabsViewGroup_tabHorizontalSpace, 0);
attrArray.recycle();
}
}
3、onMeasure函數(shù)測量子控件大小,然后設置當前控件大小
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int widthModel = MeasureSpec.getMode(widthMeasureSpec);
int heightModel = MeasureSpec.getMode(heightMeasureSpec);
//輸出寬度高度以及測量模式
Log.i(TAG, "sizeWidth :" + widthSize);
switch (widthModel) {
case MeasureSpec.AT_MOST:
Log.i(TAG, "Width model AT_MOST");
break;
case MeasureSpec.EXACTLY:
Log.i(TAG, "Width model EXACTLY");
break;
case MeasureSpec.UNSPECIFIED:
Log.i(TAG, "Width model UNSPECIFIED");
break;
}
Log.i(TAG, "sizeHeight :" + heightSize);
switch (heightModel) {
case MeasureSpec.AT_MOST:
Log.i(TAG, "Height model AT_MOST");
break;
case MeasureSpec.EXACTLY:
Log.i(TAG, "Height model EXACTLY");
break;
case MeasureSpec.UNSPECIFIED:
Log.i(TAG, "Height model UNSPECIFIED");
break;
}
//左右邊距
int left = getPaddingLeft();
int top = getPaddingTop();
//記錄每一行的寬度和高度
int lineWidth = 0;
int lineHeight = 0;
// 如果是warp_content情況下,記錄寬和高
int containerWidth = 0;
int containerHeight = 0;
// 遍歷每個子元素
for (int index = 0; index < getChildCount(); index++) {
View child = getChildAt(index);
if (child.getVisibility() == GONE) {
continue;
}
measureChild(child, widthMeasureSpec, heightMeasureSpec);
MarginLayoutParams params = (MarginLayoutParams) child.getLayoutParams();
int childWidth = child.getMeasuredWidth() + params.leftMargin + params.rightMargin + childHorizontalSpace;
int childHeight = child.getMeasuredHeight() + params.topMargin + params.bottomMargin + childVerticalSpace;
if (lineWidth + childWidth > widthSize - getPaddingRight() - getPaddingLeft()) {
containerWidth = Math.max(lineWidth, childWidth);
lineWidth = childWidth;
containerHeight += lineHeight;
lineHeight = childHeight;
Rect rect = new Rect(left,
containerHeight + top,
left + childWidth - childHorizontalSpace,
containerHeight + top + child.getMeasuredHeight());
child.setTag(rect);
} else {
Rect rect = new Rect(lineWidth + left,
containerHeight + top,
lineWidth + left + childWidth - childHorizontalSpace,
containerHeight + top + child.getMeasuredHeight());
child.setTag(rect);
lineWidth += childWidth;
lineHeight = Math.max(lineHeight, childHeight);
}
}
containerWidth = Math.max(containerWidth, lineWidth) + getPaddingLeft() + getPaddingRight();
containerHeight += lineHeight + getPaddingTop() + getPaddingBottom();
containerHeight -= childVerticalSpace;
setMeasuredDimension(widthModel == MeasureSpec.EXACTLY ? widthSize : containerWidth,
heightModel == MeasureSpec.EXACTLY ? heightSize : containerHeight);
}
4、onLayout函數(shù)對所有子控件重新布局
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (child.getVisibility() == GONE) {
continue;
}
Rect location = (Rect) child.getTag();
child.layout(location.left, location.top, location.right, location.bottom);
}
}
使用方法
1、布局問自己中直接引用
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:owen="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:textSize="16sp"
android:text="國際足球"/>
<View
android:layout_width="wrap_content"
android:layout_height="0.1dp"
android:background="#e0e0e0"/>
<com.ownchan.tabviewgroup.view.TabsViewGroup
android:id="@+id/tabs_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dip"
owen:tabHorizontalSpace="10dp"
owen:tabVerticalSpace="10dp" />
</LinearLayout>
2、代碼添加標簽
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
TabsViewGroup tabsViewGroup = (TabsViewGroup) findViewById(R.id.tabs_view);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
String[] tabs = new String[]{"世預賽歐洲區(qū)",
"世預賽南美區(qū)", "五人世界杯", "意甲", "美國大聯(lián)盟", "烏超", "英冠", "國際冠軍杯", "巴西圣保羅州杯", "巴西杯"};
for (int i = 0; i < tabs.length; i++) {
TextView textView = new TextView(this);
textView.setText(tabs[i]);
textView.setTextColor(Color.WHITE);
textView.setBackgroundDrawable(getResources().getDrawable(R.drawable.tabs_bg));
textView.setGravity(Gravity.CENTER);
textView.setPadding(10, 0, 10, 0);
textView.setTextSize(16);
tabsViewGroup.addView(textView, params);
}
}
效果圖:

項目Github地址
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
Android進階KOOM線上APM監(jiān)控全面剖析
這篇文章主要為大家介紹了Android進階KOOM線上APM監(jiān)控全面剖析詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-01-01
Android開發(fā)技巧之永不關閉的Toast信息框(長時間顯示而非系統(tǒng)關閉)
Toast信息提示框之所以在顯示一定時間后會自動關閉,是因為在系統(tǒng)中有一個Toast隊列;那么有些時候需要這個Toast信息提示框長時間顯示,直到需要關閉它時通過代碼來控制,而不是讓系統(tǒng)自動來關閉Toast信息提示框2013-01-01
Android調(diào)用google地圖生成路線圖實現(xiàn)代碼
Android程序調(diào)用本機google地圖并且傳遞起始和終點位置生成路線圖,有需要的朋有可以參考下,或許本文對你有所幫助,好了話不多說,看代碼2013-02-02
Android在Sqlite3中的應用及多線程使用數(shù)據(jù)庫的建議(實例代碼)
這篇文章主要介紹了Android在Sqlite3中的應用及多線程使用數(shù)據(jù)庫的建議,包括編寫數(shù)據(jù)庫具體操作類、增刪改查,通過實例代碼介紹了在實際中的應用,需要的朋友可以參考下2022-04-04
Android Studio中統(tǒng)一管理版本號引用配置問題
這篇文章主要介紹了Android Studio中統(tǒng)一管理版本號引用配置問題,需要的朋友可以參考下2018-01-01
Android開發(fā)實現(xiàn)應用層面屏蔽狀態(tài)欄的方法小結(jié)
這篇文章主要介紹了Android開發(fā)實現(xiàn)應用層面屏蔽狀態(tài)欄的方法,結(jié)合實例形式分析了Android屏蔽狀態(tài)欄的相關函數(shù)調(diào)用、權限控制及函數(shù)重寫等相關操作技巧,需要的朋友可以參考下2017-08-08

