Android自定义控件之自定义ViewGroup实现标签云
来源:互联网 发布:李善姬在韩国地位知乎 编辑:程序博客网 时间:2024/04/27 10:25
实现的功能:
基本绘制流程:
构造函数获取自定义属性
onMeasure()方法,测量子控件的大小
onLayout()方法,对子控件进行布局
1、自定义属性
<resources> <declare-styleable name="TabsViewGroup"> <attr name="tabVerticalSpace" format="dimension" /> <attr name="tabHorizontalSpace" format="dimension" /> </declare-styleable></resources>
2、构造函数中获取自定义属性值
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函数测量子控件大小,然后设置当前控件大小
@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函数对所有子控件重新布局
@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[]{"世预赛欧洲区", "世预赛南美区", "五人世界杯", "意甲", "美国大联盟", "乌超", "英冠", "国际冠军杯", "巴西圣保罗州杯", "巴西杯"}; 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地址
0 0
- Android自定义控件之自定义ViewGroup实现标签云
- Android自定义控件之自定义ViewGroup实现标签云
- 4.3 自定义控件 之 继承ViewGroup实现标签云
- 自定义VIewGroup 实现云标签
- Android 自定义ViewGroup之实现FlowLayout-标签流容器
- Android 自定义ViewGroup之实现FlowLayout-标签流容器
- Android 自定义ViewGroup控件
- Android自定义控件 -- 自定义ViewGroup
- 自定义ViewGroup实现标签云效果。
- 简单-自定义ViewGroup实现标签云
- Kotlin 第一弹:自定义 ViewGroup 实现流式标签控件
- Android进阶——自定义View之重写ViewGroup组合系统控件实现自定义ToolBar模板
- Android小白进阶(二)--自定义控件之自定义ViewGroup
- android之自定义ViewGroup
- Android之自定义ViewGroup
- Android之自定义ViewGroup
- Android之自定义ViewGroup
- Android 自定义控件之ViewGroup实例(实现一个简易的Viewpager)
- 8.python数据结构-列表-基本操作
- Makefile中的wildcard,notdir,patsubst用法
- MyStrlen, MyStrcmp, MyReverse,MyStrcpy,MyStrncpy,Merge,Change
- CentOS设置程序开机启动
- 配置Hibernate遇到的问题
- Android自定义控件之自定义ViewGroup实现标签云
- 仿饿了么加入购物车旋转控件
- a+b 高精度
- 使用版本控制工具SVN的项目中各种小图标所代表的具体含义
- APACHE内外网链接
- Java枚举类型详解(原理+用法)
- 9.python数据结构-列表-建立/索引/反转
- Qt语言如何读取CSV文件
- struts2 国际化 I18N