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

基本繪制流程:
構(gòu)造函數(shù)獲取自定義屬性
onMeasure()方法,測量子控件的大小
onLayout()方法,對子控件進(jìn)行布局
1、自定義屬性
<resources>
<declare-styleable name="TabsViewGroup">
<attr name="tabVerticalSpace" format="dimension" />
<attr name="tabHorizontalSpace" format="dimension" />
</declare-styleable>
</resources>
2、構(gòu)造函數(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ù)測量子控件大小,然后設(shè)置當(dāng)前控件大小
@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、代碼添加標(biāo)簽
@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[]{"世預(yù)賽歐洲區(qū)",
"世預(yù)賽南美區(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);
}
}
效果圖:

項(xiàng)目Github地址
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android自定義ViewGroup實(shí)現(xiàn)標(biāo)簽流效果
- Android自定義ViewGroup多行多列效果
- Android自定義ViewGroup實(shí)現(xiàn)朋友圈九宮格控件
- Android自定義ViewGroup實(shí)現(xiàn)流式布局
- Android進(jìn)階教程之ViewGroup自定義布局
- Android自定義ViewGroup實(shí)現(xiàn)豎向引導(dǎo)界面
- Android自定義ViewGroup實(shí)現(xiàn)淘寶商品詳情頁
- 一篇文章弄懂Android自定義viewgroup的相關(guān)難點(diǎn)
- Android自定義ViewGroup實(shí)現(xiàn)選擇面板
相關(guān)文章
Android中使用Matrix控制圖形變換和制作倒影效果的方法
這篇文章主要介紹了Android中使用Matrix控制圖形變換和制作倒影效果的方法,用Matrix來作矩陣變化十分強(qiáng)大,文中的制作倒影的例子便是一個十分巧妙的運(yùn)用,需要的朋友可以參考下2016-04-04
Android App界面的ListView布局實(shí)戰(zhàn)演練
這篇文章主要介紹了Android App界面的ListView布局方法,文中分了三種情況通過實(shí)例來講解,ListView適用于功能最簡單的應(yīng)用程序UI布局,需要的朋友可以參考下2016-04-04
Android UI手機(jī)信息頁面設(shè)計(jì)
這篇文章主要為大家詳細(xì)介紹了Android UI手機(jī)信息頁面的設(shè)計(jì)代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-03-03
Android中Serializable和Parcelable序列化對象詳解
這篇文章主要介紹了Android中Serializable和Parcelable序列化對象的相關(guān)資料,感興趣的小伙伴們可以參考一下2016-02-02
Android利用OpenGLES繪制天空盒實(shí)例教程
這篇文章主要給大家介紹了關(guān)于Android利用OpenGLES繪制天空盒的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-08-08
react native android6+拍照閃退或重啟的解決方案
android 6+權(quán)限使用的時候需要動態(tài)申請,那么在使用rn的時候要怎么處理拍照權(quán)限問題呢?本文提供的是一攬子rn操作相冊、拍照的解決方案,需要的朋友可以參考下2017-11-11
Android編程仿Iphone拖動相片特效Gallery的簡單應(yīng)用示例
這篇文章主要介紹了Android編程仿Iphone拖動相片特效Gallery的簡單應(yīng)用,結(jié)合實(shí)例形式分析了Android圖形拖動特效的實(shí)現(xiàn)步驟與相關(guān)操作技巧,需要的朋友可以參考下2016-10-10

