自定义view时使用xml传递参数-设定TextView中图片大小

当给的widget不能满足使用的时候就需要自定义。用xml配置view十分方便。如果我们希望通过xml向view中传递参数,就得多写点东西。下面写的例子是对TextView的一个扩展。TextView提供了设置四个方向图片的功能,但是无法设置图片的大小就不太好了。本文实现了一个新的类TextViewPlus,对TextView进行扩展,让其能够在xml中配置图片大小。

改变图片大小不能在xml中做,但是可以在java代码中做。先取得文本周围四个方向的图片Drawable[],然后分别调用drawable.setBounds()设置大小,最后再放回TextView中。然后问题就出在怎么让类读取xml中信息上了。

代码一共分为3部分:

1. main.xml布局文件; 2. TextViewPlus类; 3. attrs.xml文件,用于让系统识别自定义属性。构建顺序应该是attrs.xml -> TextViewPlus -> main.xml

配置文件attrs.xml

<?xml version="1.0" encoding="UTF-8"?>
<resources>

    <declare-styleable name="TextViewPlus">
        <attr name="left_height" format="dimension" />
        <attr name="left_width" format="dimension" />
        <attr name="right_height" format="dimension" />
        <attr name="right_width" format="dimension" />
        <attr name="top_height" format="dimension" />
        <attr name="top_width" format="dimension" />
        <attr name="bottom_height" format="dimension" />
        <attr name="bottom_width" format="dimension" />
    </declare-styleable>

</resources>
解释:attrs.xml放在res/values中。第4行的name需要指定使用参数的类。第5~12行写的需要在布局文件中设置的参数。name是名称,format是数据类型。系统会自动生成R文件中的变量。

类TextViewPlus

/**
 * 添加可以设置drawable大小的功能
 * 
 * @author Daniel
 * @version 创建时间: Jul 26, 2012 5:28:59 PM
 * */
public class TextViewPlus extends TextView {
	// 需要从xml中读取的各个方向图片的宽和高
	private int leftHeight = -1;
	private int leftWidth = -1;
	private int rightHeight = -1;
	private int rightWidth = -1;
	private int topHeight = -1;
	private int topWidth = -1;
	private int bottomHeight = -1;
	private int bottomWidth = -1;

	public TextViewPlus(Context context) {
		super(context);
	}

	public TextViewPlus(Context context, AttributeSet attrs) {
		super(context, attrs);
		// super一定要在我们的代码之前配置文件
		init(context, attrs, 0);
	}

	public TextViewPlus(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		// super一定要在我们的代码之前配置文件
		init(context, attrs, defStyle);
	}

	/**
	 * 初始化读取参数
	 * */
	private void init(Context context, AttributeSet attrs, int defStyle) {
		// TypeArray中含有我们需要使用的参数
		TypedArray a = context.obtainStyledAttributes(attrs,
				R.styleable.TextViewPlus, defStyle, 0);
		if (a != null) {
			// 获得参数个数
			int count = a.getIndexCount();
			int index = 0;
			// 遍历参数。先将index从TypedArray中读出来,
			// 得到的这个index对应于attrs.xml中设置的参数名称在R中编译得到的数
			// 这里会得到各个方向的宽和高
			for (int i = 0; i < count; i++) {
				index = a.getIndex(i);
				switch (index) {
				case R.styleable.TextViewPlus_bottom_height:
					bottomHeight = a.getDimensionPixelSize(index, -1);
					break;
				case R.styleable.TextViewPlus_bottom_width:
					bottomWidth = a.getDimensionPixelSize(index, -1);
					break;
				case R.styleable.TextViewPlus_left_height:
					leftHeight = a.getDimensionPixelSize(index, -1);
					break;
				case R.styleable.TextViewPlus_left_width:
					leftWidth = a.getDimensionPixelSize(index, -1);
					break;
				case R.styleable.TextViewPlus_right_height:
					rightHeight = a.getDimensionPixelSize(index, -1);
					break;
				case R.styleable.TextViewPlus_right_width:
					rightWidth = a.getDimensionPixelSize(index, -1);
					break;
				case R.styleable.TextViewPlus_top_height:
					topHeight = a.getDimensionPixelSize(index, -1);
					break;
				case R.styleable.TextViewPlus_top_width:
					topWidth = a.getDimensionPixelSize(index, -1);
					break;
				}
			}

			// 获取各个方向的图片,按照:左-上-右-下 的顺序存于数组中
			Drawable[] drawables = getCompoundDrawables();
			int dir = 0;
			// 0-left; 1-top; 2-right; 3-bottom;
			for (Drawable drawable : drawables) {
				// 设定图片大小
				setImageSize(drawable, dir++);
			}
			// 将图片放回到TextView中
			setCompoundDrawables(drawables[0], drawables[1], drawables[2],
					drawables[3]);

		}

	}

	/**
	 * 设定图片的大小
	 * */
	private void setImageSize(Drawable d, int dir) {
		if (d == null) {
			return;
		}

		int height = -1;
		int width = -1;
		// 根据方向给宽和高赋值
		switch (dir) {
		case 0:
			// left
			height = leftHeight;
			width = leftWidth;
			break;
		case 1:
			// top
			height = topHeight;
			width = topWidth;
			break;
		case 2:
			// right
			height = rightHeight;
			width = rightWidth;
			break;
		case 3:
			// bottom
			height = bottomHeight;
			width = bottomWidth;
			break;
		}
		// 如果有某个方向的宽或者高没有设定值,则不去设定图片大小
		if (width != -1 && height != -1) {
			d.setBounds(0, 0, width, height);
		}
	}
}

解释:那个读取TypedArray是主要部分。你可以把TypedArray当成一个Map<Integer key, Object value>。通过遍历key,来获得各个value。而这个key的值是写在R.stylable中的。而value需要用getDimensionPixelSize()等方法读取,这个和调用数据库从cursor中读取数据有点像。


布局文件main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:myview="http://schemas.android.com/apk/res/org.daniel.android.test"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <org.daniel.android.test.TextViewPlus
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:drawableBottom="@drawable/ic_launcher"
        android:drawableLeft="@drawable/ic_launcher"
        android:drawableRight="@drawable/ic_launcher"
        android:drawableTop="@drawable/ic_launcher"
        android:text="here is a test"
        myview:left_height="30dp"
        myview:left_width="30dp" />

</LinearLayout>

解释:主要注意第3行和第17~18行。第3行用于声明我需要使用这个项目自己定义的属性。第17~18行就是使用属性了。这个属性就是在attrs.xml中定义的属性。3行和17~18行的myview是对应的,这个名字可以任意换,只要不是关键词和同时对应就行。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值