android自定义控件(一)

虽然Android系统提供了各种各样的控件供我们开发使用,但在实际的开发中,系统提供的控件有时候不能满足我们的需求,
或者一个类似的布局在一个布局文件里多次使用,这时我们就需要自定义一个控件。
下面我们来看看通过复用布局写的自定义控件,解决在一个布局里多次写一个类似的子布局导致代码量激增的问题。
首先,我们必须清楚的知道,Android 自定义控件的几个步骤:

1.写一个需要自定义控件要用到的布局,根据控件需要的一些属性定义出一些属性.

2.在res/values目录下建立一个attrs.xml的文件,在这个文件中增加对控件的自定义属性的定义.

3.写一个自定义控件类,这个类就是你的自定义控件的实现.

4.使用带AttributeSet参数的类的构造函数,并在构造函数中将自定义控件类中变量与attrs.xml中的属性连接起来.

5.在自定义控件类中使用这些已经连接的属性变量.

6.在界面中生成此自定义控件类对象,就完成了自定义控件的创建和使用了.

下面,我们来进行第一步:书写布局jingqi_start_end.xml,明确有哪些属性。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="10dp">

<!--TextView需要一个属性,用来做标题-->
<TextView
    android:id="@+id/tv_title"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:drawableLeft="@mipmap/jingqi_stop"
    android:drawablePadding="10dp"
    android:textSize="16sp"
    android:textColor="#333333"
    android:gravity="center"
    android:layout_centerVertical="true"
    android:layout_alignParentLeft="true"/>

    <!--开关控件,需要一个是否选中的状态的属性-->
    <Switch
        android:id="@+id/btnSwitch"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    
</RelativeLayout>

从上面可知,我们目前需要用到的属性有两个,一个是标题,一个是选中状态,分别命名为mtitle(String类型)和isSwitch(boolean类型)。

然后,我们进行第二部:在res/values目录下建立一个attrs.xml的文件

<?xml version="1.0" encoding="utf-8"?>
<resources
    <!-- 条形控制控件自定义属性 -->
    <declare-styleable name="JingQiControllerView">
        <!-- 名称 -->
        <attr name="mtitle" format="string"/>
        <!-- 是否是开关 -->
        <attr name="isSwitch" format="boolean"/>
    </declare-styleable
</resources>

在这一步,我们根据上面的那步定义了两个属性。

继续第三步和第四步:写一个自定义控件类,关联布局和属性。

package date.com.calendarviewdemo;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.RelativeLayout;
import android.widget.Switch;
import android.widget.TextView;

/**
 * 自定义控件
 */
public class JingQiControllerView extends RelativeLayout{
    private String mtitle;//标题
    private boolean isSwitch;//是否选中
    public JingQiControllerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        LayoutInflater.from(context).inflate(R.layout.jingqi_start_end, this);
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.JingQiControllerView, 0, 0);
        try {
            mtitle = ta.getString(R.styleable.JingQiControllerView_mtitle);//从布局中获取标题
            isSwitch = ta.getBoolean(R.styleable.JingQiControllerView_isSwitch,false);//从布局中获取是否选中
            setUpView();
        } finally {
            ta.recycle();
        }
    }

    //初始化控件并赋值
    private void setUpView(){
        TextView tv_title = (TextView) findViewById(R.id.tv_title);
        tv_title.setText(mtitle);

        Switch switchPanel = (Switch) findViewById(R.id.btnSwitch);
        switchPanel.setChecked(isSwitch);
    }
    /**
     * 设置文字内容
     *
     * @param title 标题
     */
    public void setMtitle(String title){
        this.mtitle = title;
        TextView tv_title = (TextView) findViewById(R.id.tv_title);
        tv_title.setText(this.mtitle);
    }

    /**
     * 是否已经选中
     * @param isSwitch
     */
    public void setCheck(boolean isSwitch) {
        this.isSwitch = isSwitch;
        Switch switchPanel = (Switch) findViewById(R.id.btnSwitch);
        switchPanel.setChecked(this.isSwitch);
    }
}

继续第五步和第六步:新建一个Activity类和对应的布局,在布局里使用我们定义好的自定义控件类。

MainActivity.java

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import date.com.calendarviewdemo.JingQiControllerView;
import date.com.calendarviewdemo.R;

/**
 * 使用自定义控件
 */
public class MainActivity extends FragmentActivity{
    JingQiControllerView jingQiControllerView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
setContentView(R.layout.activity_date);

        

jingQiControllerView= (JingQiControllerView) findViewById(R.id.jingqi_start);

        //布局里已经赋值为“经期开始”,这里可以不用赋值,但是再次使用意味着修改原先不拘礼的值

        jingQiControllerView.setMtitle("标题");

        //布局里已经设为不选中,这里改为选中

        jingQiControllerView.setCheck(true);
    }
}

activity_date.xml布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_centerInParent="true"
    android:orientation="vertical" >
    <date.com.calendarviewdemo.JingQiControllerView
        android:id="@+id/jingqi_start"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:mtitle="经期开始"
        app:isSwitch="false"/>
</LinearLayout>

至此,自定义控件完成。如果你的布局里需要用到多次这样的子布局,可以多次使用,只要定义的id不一样就可以使用了。

发表回复

后才能评论