Android自定义ViewGroup控件
程序员文章站
2022-06-08 17:01:55
...
一、简单实现自定义ViewGroup四个顶点放置View
重写generateLayoutParams方法指定ViewGroup的LayoutParams为MarginLayoutParams。重写onMeasure方法,计算childView的测量模式及值,设置ViewGroup的宽和高。重写onLayout方法,设置所有childView的位置。
public class NewlineViewGroup extends ViewGroup {
private MarginLayoutParams params = null;
private int count;
private int cWidth = 0;
private int cHeight = 0;
public NewlineViewGroup(Context context) {
super(context);
}
public NewlineViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
}
public NewlineViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
/**
* 重写父类的该方法,返回MarginLayoutParams的实例
*
* @param attrs
* @return
*/
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new MarginLayoutParams(getContext(), attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//计算出所有的childView的宽高
measureChildren(widthMeasureSpec, heightMeasureSpec);
//获取childView数量
count = getChildCount();
setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
}
/**
* 测量宽度
*
* @param measureSpec
* @return
*/
private int measureWidth(int measureSpec) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.AT_MOST) {//设置为wrap_content
int t = 0, b = 0;
for (int i = 0; i < count; i++) {
View childView = getChildAt(i);
//获取子view的宽
cWidth = childView.getMeasuredWidth();
params = (MarginLayoutParams) childView.getLayoutParams();
if (i == 0 || i == 1) {
t += cWidth + params.leftMargin + params.rightMargin;
}
if (i == 2 || i == 3) {
b += cWidth + params.leftMargin + params.rightMargin;
}
}
specSize = Math.max(t, b);
return specSize;
}
return specSize;
}
/**
* 测量高度
*
* @param measureSpec
* @return
*/
private int measureHeight(int measureSpec) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.AT_MOST) {//设置为wrap_content
int l = 0, r = 0;
for (int i = 0; i < count; i++) {
View childView = getChildAt(i);
//获取子view的高
cHeight = childView.getMeasuredHeight();
params = (MarginLayoutParams) childView.getLayoutParams();
if (i == 0 || i == 2) {
l += cHeight + params.topMargin + params.bottomMargin;
}
if (i == 1 || i == 3) {
r += cHeight + params.topMargin + params.bottomMargin;
}
}
specSize = Math.max(l, r);
return specSize;
}
return specSize;
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
for (int i = 0; i < count; i++) {
View childView = getChildAt(i);
cWidth = childView.getMeasuredWidth();
cHeight = childView.getMeasuredHeight();
params = (MarginLayoutParams) childView.getLayoutParams();
int cl = 0, cr = 0, ct = 0, cb = 0;
switch (i) {
case 0:
cl = params.leftMargin;
ct = params.topMargin;
break;
case 1:
cl = getWidth() - cWidth - params.leftMargin;
ct = params.topMargin;
break;
case 2:
cl = params.leftMargin;
ct = getHeight() - cHeight - params.bottomMargin;
break;
case 3:
cl = getWidth() - cWidth - params.leftMargin - params.rightMargin;
ct = getHeight() - cHeight - params.bottomMargin;
break;
}
cr = cl + cWidth;
cb = cHeight + ct;
childView.layout(cl, ct, cr, cb);
}
}
}
xml文件中的实现
<com.example.yinyuetai.myapplication.newline.NewlineViewGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="100dp">
<TextView
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#FF4444"
android:gravity="center"
android:text="0"
android:textColor="#FFFFFF"
android:textSize="22sp"
android:textStyle="bold" />
<TextView
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#00ff00"
android:gravity="center"
android:text="1"
android:textColor="#FFFFFF"
android:textSize="22sp"
android:textStyle="bold" />
<TextView
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#ff0000"
android:gravity="center"
android:text="2"
android:textColor="#FFFFFF"
android:textSize="22sp"
android:textStyle="bold" />
<TextView
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#0000ff"
android:gravity="center"
android:text="3"
android:textColor="#FFFFFF"
android:textSize="22sp"
android:textStyle="bold" />
</com.example.yinyuetai.myapplication.newline.NewlineViewGroup>
二、实现ViewGroup自动换行
代码中邮详细注解不在赘述
private int childCount;
private static final int PADDING_HOR = 20;
private static final int PADDING_VER = 20;
private static final int SIDE_MARGIN = 40;
private static final int TEXT_MARGIN = 40;
public WordWrapViewGroup(Context context) {
super(context);
}
public WordWrapViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
}
public WordWrapViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new MarginLayoutParams(getContext(), attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//横纵坐标
int x = 0;
int y = 0;
//行数
int rows = 1;
//获取view的数量
childCount = getChildCount();
//获取父控件宽度
int specWidth = MeasureSpec.getSize(widthMeasureSpec);
//实际宽度
int actualWidth = specWidth - SIDE_MARGIN * 2;
for (int i = 0; i < childCount; i++) {
View view = getChildAt(i);
//设置边框距离
view.setPadding(PADDING_HOR, PADDING_VER, PADDING_HOR, PADDING_VER);
//设置父控件ViewGroup大小
view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
//获得当前控件的宽高
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
//计算总宽度
x += width + TEXT_MARGIN;
//判断是否超出实际宽度
if (x > actualWidth) {
x = width;
rows++;
}
y = rows * (height + TEXT_MARGIN);
}
setMeasuredDimension(actualWidth, y);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int actualWidth = r - l;
//横纵坐标开始
int x = 0;
int y = 0;
//行数
int rows = 1;
for (int i = 0; i < childCount; i++) {
View view = getChildAt(i);
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
x += width + TEXT_MARGIN;
if (x > actualWidth) {
x = width + TEXT_MARGIN;
rows++;
}
y = rows * (height + TEXT_MARGIN);
view.layout(x - width, y - height, x, y);
}
}
}
上一篇: 如何有效的做好网站软文推广?
下一篇: Winform透明窗体