自定义开发android布局文件

本文介绍了一种自定义的Android布局控件FixedGridLayout,通过继承ViewGroup实现子控件的自动换行布局,并提供了详细的实现代码及使用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       在Android中除了控件之外还有布局控件或者容器控件,比如LinearLayout、FrameLayout等,它们通常不会实现具体的功能,主要负责布局和管理所包含的子控件。Android系统提供的布局控件都有各自的使用规则,需要根据实际的需要选择合适的布局控件。
        如果系统提供的布局控件无法满足实际的布局要求,可以通过扩展ViewGroup类来实现自己的布局控件。在扩展ViewGroup类时一般需要覆盖并实现如下三个重要的方法:
        onMeasure():计算控件所需要的区域空间。
        onLayout():布局子控件。

        dispatchDraw():绘制布局控件,需要特别注意:对于自定义控件需要覆盖onDraw方法,而自定义布局控件需要覆盖dispatchDraw方法。

我的需求

      开发过程中需要往布局文件中动态添加TextView,LinearLayout默认的布局方式不存在自动换行,所以导致布局效果非常差,为了实现动态添加的TextView能够自动换行显示,这里继承ViewGroup类,重新定义开发了一个布局文件。

直接上代码:

package com.west.aipuli.wheretobuy.unit;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

public class FixedGridLayout extends ViewGroup {
	private int mCellWidth;
	private int mCellHeight;
	public FixedGridLayout(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
	}
	public FixedGridLayout(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
		// 初始化单元格宽和高
		mCellWidth = 60;
		mCellHeight = 60;
	}
	// 设置单元格宽度
	public void setCellWidth(int w) {
		mCellWidth = w;
		requestLayout();

	}
	// 设置单元格高度
	public void setCellHeight(int h) {
		mCellHeight = h;
		requestLayout();
	}
	//为布局控件添加边框
	@Override
	protected void dispatchDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		// 获取布局控件宽高
		int width = getWidth();
		int height = getHeight();
		// 创建画笔
		Paint mPaint = new Paint();
		// 设置画笔的各个属性
		mPaint.setColor(Color.WHITE);
		mPaint.setStyle(Paint.Style.STROKE);
		mPaint.setStrokeWidth(1);
		mPaint.setAntiAlias(true);
		// 创建矩形框
		Rect mRect = new Rect(0, 0, width, height);
		// 绘制边框
		canvas.drawRect(mRect, mPaint);
		// 最后必须调用父类的方法
		super.dispatchDraw(canvas);
	}
    //计算控件所需要的区域空间
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		// TODO Auto-generated method stub
		// 创建测量参数
		int cellWidthSpec = MeasureSpec.makeMeasureSpec(mCellWidth,
				MeasureSpec.AT_MOST);
		int cellHeightSpec = MeasureSpec.makeMeasureSpec(mCellHeight,
				MeasureSpec.AT_MOST);
		// 记录ViewGroup中Child的总个数
		int count = getChildCount();
		// 设置子空间Child的宽高
		for (int i = 0; i < count; i++) {
			View childView = getChildAt(i);
			childView.measure(cellWidthSpec, cellHeightSpec);
		}
		// 设置容器控件所占区域大小
		// 注意setMeasuredDimension和resolveSize的用法
		setMeasuredDimension(resolveSize(mCellWidth * count, widthMeasureSpec),
				resolveSize(mCellHeight * count, heightMeasureSpec));
	}
    //控制子控件换行
	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		// TODO Auto-generated method stub
		int cellWidth = mCellWidth;
		int cellHeight = mCellHeight;
		int columns = (r - l) / cellWidth;
		if (columns < 0) {
			columns = 1;
		}
		int x = 0;
		int y = 0;
		int i = 0;
		int count = getChildCount();
		for (int j = 0; j < count; j++) {
			final View childView = getChildAt(j);
			//获取子控件Child的宽高
			int w = childView.getMeasuredWidth();
			int h = childView.getMeasuredHeight();
			// 计算子控件的顶点坐标
			int left = x + ((cellWidth - w) / 2);
			int top = y + ((cellHeight - h) / 2);
			// 布局子控件
			childView.layout(left, top, left + w, top + h);
			if (i >= (columns - 1)) {
				i = 0;
				x = 0;
				y += cellHeight;
			} else {
				i++;
				x += cellWidth;
			}

		}

	}

}
在Xml文件中直接使用该控件即可。

        <com.west.aipuli.wheretobuy.unit.FixedGridLayout
            android:id="@+id/isbuy_list_itemsImage_layout02_layout01"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="5dip"
            android:layout_alignLeft="@+id/isbuy_list_itemsImage_itemsTitle"
            android:layout_below="@+id/isbuy_list_itemsImage_itemsTitle" >
        </com.west.aipuli.wheretobuy.unit.FixedGridLayout>




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值