-
概述:
常用的布局类型并不能满足所有需求,这时就会用到ViewGroup。
ViewGroup作为一个放置View的容器,并且我们在写布局xml的时候,会告诉容器(凡是以layout为开头的属性,都是为用于告诉容器的),我们的宽度(layout_width)、高度(layout_height)、对齐方式(layout_gravity)等;当然还有margin等;于是乎,ViewGroup需要做的事情是:给childView计算出建议的宽和高和测量模式 ;决定childView的位置;为什么只是建议的宽和高,而不是直接确定呢,别忘了childView宽和高可以设置为wrap_content,这样只有childView才能计算出自己的宽和高。
博客名已经说明了这篇博客要将给出的内容,不用赘述。
先看效果图:
代码注释很详细,直接看代码即可,没贴源码,因为这是从一个项目里面抠出来的。
Demo
先写一个自定义LinearLayout,它的功能是自适应子控件:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556<code
class
=
"language-java"
hljs=
""
>
public
class
ItemContainer
extends
LinearLayout {
private
int
width;
//组件宽
private
int
height;
//组件高
private
int
childCount;
private
int
childMarginLeft = SizeConvert.dip2px(getContext(),
8
);
//子控件相对左边控件的距离
private
int
childMarginHorizonTal = SizeConvert.dip2px(getContext(),
10
);
//子控件相对最左、最右的距离
private
int
childMarginTop = SizeConvert.dip2px(getContext(),
8
);
//子控件相对顶部控件的距离
private
int
childWidth;
//子控件宽
private
int
childHeight;
//子控件高
public
ItemContainer(Context context) {
super
(context);
}
public
ItemContainer(Context context, AttributeSet attrs) {
super
(context, attrs);
}
@Override
protected
void
onMeasure(
int
widthMeasureSpec,
int
heightMeasureSpec) {
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);
}
@Override
protected
void
onLayout(
boolean
changed,
int
l,
int
t,
int
r,
int
b) {
/**
* 遍历所有子控件,并设置它们的位置和大小
* 每行只能有三个子控件,且高度固定,宽度相同,且每行正好布满
*/
for
(
int
i =
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<code
class
=
"language-java"
hljs=
""
>
public
class
ItemOperateActivity
extends
BaseActivity {
private
LinearLayout mContentNoItem;
private
LinearLayout mContentItemRemove;
private
ItemContainer mItemContainerAdd;
private
ItemContainer mItemContainerRemove;
@Override
protected
void
onCreate(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(
new
String[]{随时定位, 客户拜访},
new
String[]{新增客户, 客户总量});
}
/**
* 添加条目时需要调用的方法
* @param name
*/
private
void
addItem(String name) {
mContentNoItem.setVisibility(View.GONE);
Button button =
new
Button(getApplicationContext());
ViewGroup.LayoutParams params =
new
ViewGroup.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(
new
View.OnClickListener() {
@Override
public
void
onClick(View v) {
mItemContainerAdd.removeView(v);
removeItem(((Button) v).getText().toString());
if
(mItemContainerAdd.getChildCount()==
0
) {
mContentNoItem.setVisibility(View.VISIBLE);
}
}
});
mItemContainerAdd.addView(button);
}
/**
* 删除条目时需要调用的方法
* @param name
*/
private
void
removeItem(String name) {
mContentItemRemove.setVisibility(View.VISIBLE);
Button button =
new
Button(getApplicationContext());
ViewGroup.LayoutParams params =
new
ViewGroup.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(
new
View.OnClickListener() {
@Override
public
void
onClick(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 可添加的子控件名数组
*/
private
void
initItems(String[] itemsAdd, String[] itemsRemove) {
for
(String itemAdd : itemsAdd) {
addItem(itemAdd);
}
for
(String itemRemove : itemsRemove) {
removeItem(itemRemove);
}
}
}</code>
布局:
123456789101112131415161718192021222324252627282930313233343536373839404142434445<code
class
=
"language-xml"
hljs=
""
><!--?xml version=
1.0
encoding=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<code
class
=
"language-xml"
hljs=
""
><!--?xml version=
1.0
encoding=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<code
class
=
"language-xml"
hljs=
""
><!--?xml version=
1.0
encoding=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.0
encoding=utf-
8
?--></code>
item_select_bg_below:
123456<code
class
=
"language-xml"
hljs=
""
><!--?xml version=
1.0
encoding=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-10 16:20:28 发布