Android 自定义组合控件及原理

  关于自定义组合控件,我相信大家在百度、谷歌的时候,会出来一大把,可是,我们百度出来的自定义组合控件,能讲出其中原理的,少之又少,在看这篇文章的你是否想到了我要说什么呢?对,你想的没错,我就是要讲讲自定义组合控件的原理.

自定义组合控件的第一步当然就是要去继承了,并且实现他们的构造方法:

  public class SettingView extends RelativeLayout {

	private TextView tv_content,tv_title;

	public SettingView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		System.out.println("3个参数");
	}
	
	public SettingView(Context context, AttributeSet attrs) {
		super(context, attrs);
		initView( context);
		System.out.println("2个参数");
	
	}

	public SettingView(Context context) {
		super(context);
	
		System.out.println("1个参数");
	}
}

其次,你需要去组合一些控件了,在布局里面放置一些控件,比如:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="80dip" >

    <TextView
        android:id="@+id/tv_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="我是设置文本1"
        android:textSize="25dip" />

    <TextView
        android:id="@+id/tv_content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/tv_title"
        android:padding="5dip"
        android:textColor="#88000000"
        android:text="我是描述文本1"
        android:textSize="15dip" />

    <View
        android:layout_width="match_parent"
        android:layout_height="1dip"
        android:layout_alignParentBottom="true"
        android:background="@drawable/qb_tenpay_list_line" />

    <CheckBox
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true" />

</RelativeLayout>


这样,一个自定义的组合控件就好了,下面呢,我们要讲解一下给自定义的组合控件加上属性,就跟那个TextView控件一样,比如说,当我们给TextView添加文本属性的时候,你会看到,你给两个相同的控件添加不同的文字的时候,他们的文字是不一样的,但是到这步之前,我们的自定义组合控件的是没法给其添加属性的,因为,它压根就没有这个能力,所以就不能做这个事情,那怎么办呢?不过我们也可以办到,如果在、不能这样的话,我们自定义什么组合控件啊,,好了,我们接下来去给我们自定义的组件增加我们想要的属性呗,好,回到我们刚才布局的XML文件中,我们看看布局页面的声明,在这张图片中你可以看到我自己声明了一个命名空间,可是我们自己所写的属性资源在那里呢?其实,我们自己声明的,就是在我们当前的应用,我们可以用我们的包名来声明资源的所在地,OK


但是我们为什么要这样做呢?这么做是有原因的,我们看到系统自带的控件,如TextView控件,我们为什么可以给他增加属性呢?这是因为,他们把属性全部定义在android.jar包下,不信的话,你可以在你们放置的SDK目录下找到一个叫attrs的xml文件,这是我的SDK路径:E:\android-sdk-windows\platforms\android-18\data\res\values,在这个values文件夹下可以看到一个叫attrs.xml文件,这里定义了TextView、EditText等等这些控件的属性声明,好了,看了这些,你是不是有些感触呢?这样我们就可以依葫芦画瓢的方式,来给我们自己定义的组合控件生成属性了.当我们完成这些自定义的属性之后,我们再去看看R.java文件,我们可以看到生成了一个attr的内部类和一个styleable的内部类,在后者这个内部类里面我们可以看到有个数组,这个数组的名字就是你刚才定义的属性时,给他起的一个名字,这样说可能很抽象,放心,待会我会提供一个图片让大家看看.


通过以上步骤,我们已经完成了自定义组合控件的三分之二了,为什么说是只完成了其中的三分之二呢?因为我们还有事情没有做,那就是我们所定义的这些属性,还没有正式生效,要让他生效,我们必须通过code来实现,这就是我们刚才为什么说只完成了其三分之二,好了。下面看看怎么通过代码实现:

public class SettingView extends RelativeLayout {

	private TextView tv_content,tv_title;

	public SettingView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		initView( context);
		System.out.println("3个参数");
	}
	
	public SettingView(Context context, AttributeSet attrs) {
		super(context, attrs);
		initView( context);
		System.out.println("2个参数");
		TypedArray ta  = context.obtainStyledAttributes(attrs, R.styleable.SettingView);//让属性集与自定义的属性的数组建立一个对应关系
		String content = ta.getString(R.styleable.SettingView_content);
		String title = ta.getString(R.styleable.SettingView_title);
		tv_content.setText(content);
		tv_title.setText(title);
		ta.recycle();//这个必须调用
	}

	public SettingView(Context context) {
		super(context);
		initView( context);
		System.out.println("1个参数");
	}
	
	private void initView(Context context) {
		View view = View.inflate(context, R.layout.ui_settingview, null);
		this.addView(view);
		tv_content = (TextView) view.findViewById(R.id.tv_content);
		tv_title = (TextView) view.findViewById(R.id.tv_title);
	}
}

那么刚才我们继承所实现的三个构造方法,他们执行那个呢?其实只要你们定一些log信息,然后去执行,你们就知道了,它们默认之行的是带两个参数的构造方法,那么其他的两构造函数什么时候执行呢?有三个参数的是当你该控件添加了一个样式的时候,他才会去执行的,一个参数的则是在你new的时候会调用,好了,这下你清楚了么?

如果还有不清楚的,在这里我把自定义组合控件的步骤图给大家,让大家参考参考一下:


下面贴上全部的代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="80dip" >

    <TextView
        android:id="@+id/tv_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="我是设置文本1"
        android:textSize="25dip" />

    <TextView
        android:id="@+id/tv_content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/tv_title"
        android:padding="5dip"
        android:textColor="#88000000"
        android:text="我是描述文本1"
        android:textSize="15dip" />

    <View
        android:layout_width="match_parent"
        android:layout_height="1dip"
        android:layout_alignParentBottom="true"
        android:background="@drawable/qb_tenpay_list_line" />

    <CheckBox
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true" />

</RelativeLayout>
attrs文件:

<?xml version="1.0" encoding="utf-8"?>
<resources>
        <declare-styleable name="SettingView">
            <attr name="content" format="string" />
            <attr name="title" format="string" />
    </declare-styleable>
</resources>


放置自定义的组合布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:haibo="http://schemas.android.com/apk/res/com.haibo.example"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <com.haibo.example.SettingView
        android:id="@+id/sv1"
        android:layout_width="fill_parent"
        android:layout_height="80dip"
        android:background="#D73366FF"
        haibo:content="哈哈"
        haibo:title="嘻嘻" >
    </com.haibo.example.SettingView>

    <com.haibo.example.SettingView
        android:id="@+id/sv2"
        android:layout_width="fill_parent"
        android:layout_height="80dip"
        haibo:content="哈哈"
        haibo:title="嘻嘻" >
    </com.haibo.example.SettingView>

    <com.haibo.example.SettingView
        android:id="@+id/sv3"
        android:layout_width="fill_parent"
        android:layout_height="80dip"
        haibo:content="哈哈"
        haibo:title="嘻嘻" >
    </com.haibo.example.SettingView>

    <com.haibo.example.SettingView
        android:id="@+id/sv4"
        android:layout_width="fill_parent"
        android:layout_height="80dip"
        haibo:content="哈哈"
        haibo:title="嘻嘻" >
    </com.haibo.example.SettingView>

    <com.haibo.example.SettingView
        android:id="@+id/sv5"
        android:layout_width="fill_parent"
        android:layout_height="80dip"
        haibo:content="哈哈"
        haibo:title="嘻嘻" >
    </com.haibo.example.SettingView>

</LinearLayout>


代码:

public class SettingView extends RelativeLayout {

	private TextView tv_content,tv_title;

	public SettingView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		initView( context);
		System.out.println("3个参数");
	}
	
	public SettingView(Context context, AttributeSet attrs) {
		super(context, attrs);
		initView( context);
		System.out.println("2个参数");
		TypedArray ta  = context.obtainStyledAttributes(attrs, R.styleable.SettingView);//让属性集与自定义的属性的数组建立一个对应关系
		String content = ta.getString(R.styleable.SettingView_content);
		String title = ta.getString(R.styleable.SettingView_title);
		tv_content.setText(content);
		tv_title.setText(title);
		ta.recycle();
	}

	public SettingView(Context context) {
		super(context);
		initView( context);
		System.out.println("1个参数");
	}
	
	private void initView(Context context) {
		View view = View.inflate(context, R.layout.ui_settingview, null);
		this.addView(view);
		tv_content = (TextView) view.findViewById(R.id.tv_content);
		tv_title = (TextView) view.findViewById(R.id.tv_title);
	}
}
开启的activity:

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}
}

效果图:


就此终结,如果转载的话,请注明出处,谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值