-
概述:
常用的布局类型并不能满足所有需求,这时就会用到ViewGroup。
ViewGroup作为一个放置View的容器,并且我们在写布局xml的时候,会告诉容器(凡是以layout为开头的属性,都是为用于告诉容器的),我们的宽度(layout_width)、高度(layout_height)、对齐方式(layout_gravity)等;当然还有margin等;于是乎,ViewGroup需要做的事情是:给childView计算出建议的宽和高和测量模式 ;决定childView的位置;为什么只是建议的宽和高,而不是直接确定呢,别忘了childView宽和高可以设置为wrap_content,这样只有childView才能计算出自己的宽和高。
博客名已经说明了这篇博客要将给出的内容,不用赘述。
先看效果图:

代码注释很详细,直接看代码即可,没贴源码,因为这是从一个项目里面抠出来的。
Demo
先写一个自定义LinearLayout,它的功能是自适应子控件:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556<codeclass="language-java"hljs="">publicclassItemContainerextendsLinearLayout {privateintwidth;//组件宽privateintheight;//组件高privateintchildCount;privateintchildMarginLeft = SizeConvert.dip2px(getContext(),8);//子控件相对左边控件的距离privateintchildMarginHorizonTal = SizeConvert.dip2px(getContext(),10);//子控件相对最左、最右的距离privateintchildMarginTop = SizeConvert.dip2px(getContext(),8);//子控件相对顶部控件的距离privateintchildWidth;//子控件宽privateintchildHeight;//子控件高publicItemContainer(Context context) {super(context);}publicItemContainer(Context context, AttributeSet attrs) {super(context, attrs);}@OverrideprotectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);childCount = getChildCount();//得到子控件数量if(childCount>0) {childWidth = (width - childMarginLeft *4) /3;childHeight = SizeConvert.dip2px(getContext(),42);//给子控件的高度一个定值//根据子控件的高和子控件数目得到自身的高height = childHeight * ((childCount-1)/3+1) + childMarginHorizonTal *2+ childMarginTop*((childCount-1)/3);Log.d(childHeight,childHeight+);}else{//如果木有子控件,自身高度为0,即不显示height =0;}width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);Log.d(height,height+);//根据自身的宽度约束子控件宽度measureChildren(widthMeasureSpec, heightMeasureSpec);//设置自身宽度setMeasuredDimension(width, height);}@OverrideprotectedvoidonLayout(booleanchanged,intl,intt,intr,intb) {/*** 遍历所有子控件,并设置它们的位置和大小* 每行只能有三个子控件,且高度固定,宽度相同,且每行正好布满*/for(inti =0; i < childCount; i++) {View childView = getChildAt(i);//得到当前子控件childView.layout((i%3) * childWidth + (i%3+1)*childMarginLeft, (i /3)*childHeight + childMarginHorizonTal + (i /3)*childMarginTop, (i%3+1) * childWidth + (i%3+1)*childMarginLeft, (i /3+1)*childHeight + childMarginHorizonTal + (i /3)*childMarginTop);}}}</code>主活动完成的功能就是上面贴图演示的功能,让两个自定义ViewGroup能够添加删除子控件,子控件是在代码中动态搭建的,下面会给出方法:
活动:1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495<codeclass="language-java"hljs="">publicclassItemOperateActivityextendsBaseActivity {privateLinearLayout mContentNoItem;privateLinearLayout mContentItemRemove;privateItemContainer mItemContainerAdd;privateItemContainer mItemContainerRemove;@OverrideprotectedvoidonCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_item_operate);mContentNoItem = (LinearLayout) findViewById(R.id.linearlayout_attention_null);mContentItemRemove = (LinearLayout) findViewById(R.id.linearlayout_remove);mItemContainerAdd = (ItemContainer) findViewById(R.id.item_container_add);mItemContainerRemove = (ItemContainer) findViewById(R.id.item_container_remove);initItems(newString[]{随时定位, 客户拜访},newString[]{新增客户, 客户总量});}/*** 添加条目时需要调用的方法* @param name*/privatevoidaddItem(String name) {mContentNoItem.setVisibility(View.GONE);Button button =newButton(getApplicationContext());ViewGroup.LayoutParams params =newViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,0);button.setLayoutParams(params);button.setText(name);button.setGravity(Gravity.CENTER);button.setBackgroundResource(R.drawable.item_select_bg);button.setTextSize(13);button.setTextColor(Color.argb(255,47,79,79));//铅灰色button.setOnClickListener(newView.OnClickListener() {@OverridepublicvoidonClick(View v) {mItemContainerAdd.removeView(v);removeItem(((Button) v).getText().toString());if(mItemContainerAdd.getChildCount()==0) {mContentNoItem.setVisibility(View.VISIBLE);}}});mItemContainerAdd.addView(button);}/*** 删除条目时需要调用的方法* @param name*/privatevoidremoveItem(String name) {mContentItemRemove.setVisibility(View.VISIBLE);Button button =newButton(getApplicationContext());ViewGroup.LayoutParams params =newViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,0);button.setLayoutParams(params);button.setText(name);button.setGravity(Gravity.CENTER);button.setBackgroundResource(R.drawable.item_select_bg_below);button.setTextSize(13);button.setTextColor(Color.argb(255,47,79,79));//铅灰色button.setOnClickListener(newView.OnClickListener() {@OverridepublicvoidonClick(View v) {/*** 点击按钮时,删除*/mItemContainerRemove.removeView(v);addItem(((Button) v).getText().toString());if(mItemContainerRemove.getChildCount() ==0) {mContentItemRemove.setVisibility(View.GONE);}}});mItemContainerRemove.addView(button);}/*** 初始化子控件* @param itemsAdd 已添加的子控件名数组* @param itemsRemove 可添加的子控件名数组*/privatevoidinitItems(String[] itemsAdd, String[] itemsRemove) {for(String itemAdd : itemsAdd) {addItem(itemAdd);}for(String itemRemove : itemsRemove) {removeItem(itemRemove);}}}</code>布局:
123456789101112131415161718192021222324252627282930313233343536373839404142434445<codeclass="language-xml"hljs=""><!--?xml version=1.0encoding=utf-8?--><linearlayout android:layout_height="match_parent"android:layout_width="match_parent"android:orientation="vertical"xmlns:android="http://schemas.android.com/apk/res/android"><relativelayout android:background="@drawable/item_bg"android:layout_height="60dp"android:layout_width="match_parent"><linearlayout android:gravity="center"android:id="@+id/linearlayout_back"android:layout_alignparentleft="true"android:layout_centervertical="true"android:layout_height="wrap_content"android:layout_marginleft="5dp"android:layout_width="wrap_content"android:orientation="horizontal"><imagebutton android:background="@drawable/btn_back/"android:layout_height="wrap_content"android:layout_width="wrap_content"><textview android:layout_height="wrap_content"android:layout_width="wrap_content"android:text="报表"android:textsize="@dimen/head_left_text_size/"></textview></imagebutton></linearlayout><textview android:layout_centerinparent="true"android:layout_height="wrap_content"android:layout_width="wrap_content"android:text="订阅"android:textsize="@dimen/head_center_text_size/"></textview></relativelayout><linearlayout android:background="@drawable/item_bg"android:layout_height="wrap_content"android:layout_width="match_parent"android:orientation="horizontal"android:paddingbottom="12dp"android:paddingleft="8dp"android:paddingtop="12dp"><textview android:layout_height="wrap_content"android:layout_width="wrap_content"android:text="已添加"android:textsize="16dp/"><textview android:layout_height="wrap_content"android:layout_width="wrap_content"android:text="(点击删除)"android:textsize="13dp/"></textview></textview></linearlayout><com.test.shiweiwei.myproject.selfish_view.self_defined_view_group.itemcontainer android:background="@drawable/item_bg"android:id="@+id/item_container_add"android:layout_height="wrap_content"android:layout_width="match_parent"></com.test.shiweiwei.myproject.selfish_view.self_defined_view_group.itemcontainer><linearlayout android:background="@drawable/item_bg"android:gravity="center"android:id="@+id/linearlayout_attention_null"android:layout_height="wrap_content"android:layout_width="match_parent"android:orientation="vertical"android:paddingbottom="35dp"android:paddingtop="35dp"android:visibility="gone"><imageview android:layout_height="wrap_content"android:layout_width="wrap_content"android:src="@mipmap/attendance_null/"><textview android:layout_height="wrap_content"android:layout_width="wrap_content"android:text="无报表信息/"android:textsize="13dp"></textview></imageview></linearlayout><imageview android:layout_height="wrap_content/"android:layout_width="match_parent"><linearlayout android:id="@+id/linearlayout_remove"android:layout_height="wrap_content"android:layout_width="match_parent"android:orientation="vertical"><linearlayout android:background="@drawable/item_bg"android:layout_height="wrap_content"android:layout_margintop="@dimen/first_page_item_margin_top"android:layout_width="match_parent"android:orientation="horizontal"android:paddingbottom="12dp"android:paddingleft="8dp"android:paddingtop="12dp"><textview android:layout_height="wrap_content"android:layout_width="wrap_content"android:text="可添加"android:textsize="16dp/"></textview></linearlayout><com.test.shiweiwei.myproject.selfish_view.self_defined_view_group.itemcontainer android:background="@drawable/item_bg"android:id="@+id/item_container_remove"android:layout_height="wrap_content"android:layout_width="match_parent"></com.test.shiweiwei.myproject.selfish_view.self_defined_view_group.itemcontainer></linearlayout></imageview></linearlayout></code>drawable下的文件:
item_bg:12345<codeclass="language-xml"hljs=""><!--?xml version=1.0encoding=utf-8?--><solid android:color="@color/white"></solid><stroke android:color="@color/stroke_vertical"android:width="0.3dp"></stroke></shape></code>item_select_bg:
1234567<codeclass="language-xml"hljs=""><!--?xml version=1.0encoding=utf-8?--><solid android:color="@color/white"></solid><stroke android:color="@color/dark_brow"android:width="0.3dp"></stroke><corners android:radius="4dp"></corners><padding android:bottom="12dp"android:top="12dp"></padding></shape><!--?xml version=1.0encoding=utf-8?--></code>item_select_bg_below:
123456<codeclass="language-xml"hljs=""><!--?xml version=1.0encoding=utf-8?--><solid android:color="@color/white"></solid><stroke android:color="@color/stroke_vertical"android:width="0.3dp"></stroke><corners android:radius="4dp"></corners></shape></code>
Android自定义ViewGroup之子控件的自动换行和添加删除
最新推荐文章于 2022-10-17 17:16:30 发布
本文介绍如何使用自定义LinearLayout实现动态添加和删除子控件的功能,包括初始化子控件、添加子控件、删除子控件等操作。通过设置组件的宽度、高度、对齐方式等属性,实现子控件的自适应布局。
3476

被折叠的 条评论
为什么被折叠?



