Android自定义组合控件

自定义组合控件步奏略繁琐,为了避免再次忘记,记之且共勉

这里以我自定义的MyActionBar为例

1. 定义组合控件的xml文件

例:actionbar.xml

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

    <View android:id="@+id/view_status_bar" android:layout_width="match_parent" android:layout_height="0.1dip" android:visibility="gone" android:background="@color/theme_color_normal"/>

    <LinearLayout android:layout_width="match_parent" android:layout_height="48dip" android:gravity="center_vertical" android:background="@color/theme_color_normal" android:orientation="horizontal">

        <ImageView android:id="@+id/iv_back" android:layout_width="32dip" android:layout_height="32dip" android:layout_margin="8dip" android:clickable="true" android:background="@drawable/actionbar_back_selector"/>

        <cn.edu.wust.hospital.widget.ScrollTextView android:id="@+id/stv_title" android:layout_width="0dip" android:layout_height="match_parent" android:layout_weight="1" android:text="武汉市五医" android:gravity="center" android:textSize="22sp" android:textColor="@color/whtie"/>

        <ImageView android:id="@+id/iv_more" android:layout_width="32dip" android:layout_height="32dip" android:layout_margin="8dip" />

    </LinearLayout>

</LinearLayout>

2.实现该组合控件的Java代码

例:MyActionBar.java

package cn.edu.wust.hospital.widget;

import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.LinearLayout;
import cn.edu.wust.hospital.R;
import cn.edu.wust.hospital.config.AppConfig;

/** * <b>自定义的ActionBar</b><p /> * xml文件中通过设置属性<b>yorek:title_name</b>可以设置title文字<br /> * 设置<b>yorek:set_back_visible</b>属性可以选择是否显示返回按钮(<b>返回事件已经实现了,不用重复实现</b>)<br /> * @author Yorek Liu * @date 2015年4月8日13:58:31 * @version 1.0 */
public class MyActionBar extends LinearLayout {
    private ImageView backImgView;
    private ScrollTextView titleView;
    private Activity basedActivity;

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

    // 这个构造器很重要
    public MyActionBar(final Context context, AttributeSet attrs) {
        super(context, attrs);

        // 且待第4步再来看这里的代码
        LayoutInflater.from(context).inflate(R.layout.actionbar, this, true);//将上面的布局填充进来,不然findViewById会nullpointer

        // 取出使用该控件时设置的key-value对
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyActionBar);
        // 获取key为title_name的值
        String title = typedArray.getString(R.styleable.MyActionBar_title_name);
        basedActivity = (Activity) context;

        if (!TextUtils.isEmpty(title)) {
            // 操作自定义组合控件中的某个控件
            titleView = (ScrollTextView) this.findViewById(R.id.stv_title);
            titleView.setText(title);
        }

        // 与上面一致
        boolean isVisible = typedArray.getBoolean(R.styleable.MyActionBar_set_back_visible, true);

        backImgView = (ImageView) this.findViewById(R.id.iv_back);
        if (!isVisible) {
            backImgView.setVisibility(View.INVISIBLE);
        } else {
            if (!isInEditMode()) {
                backImgView.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        basedActivity.finish();
                    }
                });
            }
        }

        typedArray.recycle();
    }
}

3.在values文件夹下定义attrs.xml文件

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyActionBar">    <!- name里面写自定义控件的类名 -->
   <attr name="title_name" format="string"/>  <!- name里面写自定义控件的属性 -->
    <attr name="set_back_visible" format="boolean"/>
   </declare-styleable>  
</resources>

format里面可有的属性为
string , integer , boolean, dimension , reference , color , enum.
前面几种的声明方式都是一致的,例如:<attr name="buttonNum" format="integer"/>
只有enum是不同的,用法举例:

<attr name="testEnum">  
    <enum name="fill_parent" value="-1"/>  
    <enum name="wrap_content" value="-2"/>  
</attr>   

4.在构造器中获取属性并操作控件

参考第二步的代码

5.使用自定义组合控件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:yorek="http://schemas.android.com/apk/res/cn.edu.wust.hospital"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <cn.edu.wust.hospital.widget.MyActionBar
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        yorek:title_name="什么鬼"
        yorek:set_back_visible="false" />

    <TextView 
        android:id="@+id/tv_info"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"/>
    ......

</RelativeLayout>

在这一步中要注意自定义控件的命名空间

xmlns:yorek="http://schemas.android.com/apk/res/cn.edu.wust.hospital"

xmlns:yorek这里的yorek可以是随意的名称,但下面使用属性时需要与这里的名称保持一致
value中的写法应该是http://schemas.android.com/apk/res/ + 包名
(此处的包名应该是AndroidManifest.xml中的package名称)

<cn.edu.wust.hospital.widget.MyActionBar
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    yorek:title_name="什么鬼"       <!- 注意命名空间 -->
    yorek:set_back_visible="false" />

运行效果:

你可能感兴趣的:(android)