android实现自定义控件及如何在其他项目中使用

自定义控件

当android提供的控件不满足需求时, 我们需要自己去定制所需要的控件. 例如在一个TV项目中, 我们需要一种button, 当不选择时, 文本颜色是白色, 当选中时, 文本颜色是黑色, 这时android中自带的button是无法实现的, 那么我们需要去自己定制这种控件.


自定义控件的步骤一般分为:

(1). 声明一个view对象, 继承相对布局,或者线性布局或者其他的ViewGroup.

(2). 在自定义的View对象的构造方法里面就把布局都初始化完毕.

(3). 根据需求, 扩展自定义控件.


根据需求我们去实现改变文本颜色的button, 命名为DButton, 首先:

1设置自定属性

在 value 目录下创建 名为 attrs.xml文件, 在此文件中声明自定义的属性

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

    <declare-styleable name="DButton">
        <attr name="normalColor" format="reference|color" />
        <attr name="selectedColor" format="reference|color" />
        <attr name="text" format="reference|string" />
        <attr name="textSize" format="dimension" />
    </declare-styleable>

</resources>
通过normalColor属性来设置button没有选中时的文本颜色, selectedColor属性来设置button选中时的文本状态.

关于format属性有:

dimension 尺寸值

reference  资源ID

color          颜色值

boolean    布尔值

float           浮点值

integer     整型值

string       字符串

enum       枚举值

flag          位或运算

这些属性可以组合使用, 例如上面的 format="reference | color"


2. 创建DButton对象, 继承LinearLayout

public class DButton extends LinearLayout {

    private TextView mTextView;
    private Context mContext = null;
    private int mNormalColor;
    private int mSelectedColor;


    public DButton(Context context) {
        super(context);
        initController(context);
        setGravity(Gravity.CENTER);

        LayoutParams params = new LayoutParams(R.dimen.ltbutton_default_width, R.dimen.ltbutton_default_height);
        setLayoutParams(params);
    }

    public DButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initController(context);
        setAttributeSet(attrs);
    }

    public DButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        initController(context);
        setAttributeSet(attrs);
    }

    private void initController(Context context) {
        mContext = context;
        mNormalColor = Color.WHITE;
        mSelectedColor = Color.BLACK;

        mTextView = new TextView(context);
        mTextView.setTextColor(mNormalColor);
        addView(mTextView);
        setProperty();
        setFocusDrawer(getResources().getDrawable(R.drawable.focus_1));
    }

    private void setProperty() {
        setFocusable(true);
        setFocusableInTouchMode(true);
    }

    private void setAttributeSet(AttributeSet attrs) {
        TypedArray typeArray = mContext.obtainStyledAttributes(attrs, R.styleable.DButton);
        final String text = typeArray.getString(R.styleable.DButton_text);
        if (!TextUtils.isEmpty(text)) {
            setText(text);
        }
        final int normalColor = typeArray.getColor(R.styleable.DButton_normalColor, Color.WHITE);
        if (normalColor != Color.WHITE) {
            mNormalColor = normalColor;
            setTextColor(mNormalColor);
        }
        final int selectColor = typeArray.getColor(R.styleable.DButton_selectedColor, Color.BLACK);
        if (selectColor != Color.BLACK) {
            mSelectedColor = selectColor;
        }
        final int size = typeArray.getDimensionPixelOffset(R.styleable.DButton_textSize, 0);
        if (size != 0) {
            setTextSize(size);
        }

        typeArray.recycle();
    }

    public void setTextColor(int color) {
        mTextView.setTextColor(color);
    }

    public void setTextSize(float size) {
        mTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);
    }

    public void setText(String text) {
        mTextView.setText(text);
    }

    @Override
    protected void onFocusChanged(boolean gainFocus, int direction,
            Rect previouslyFocusedRect) {
        int color = isFocused() ? mSelectedColor : mNormalColor;
        mTextView.setTextColor(color);

        super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
    }
}

这段代码主要是重写onFocusChanged方法, 来实现选中与不选中时控制文本颜色.

在setAttributeSet方法中调用 obtainStyledAttributes获取attrs中的属性, 存入到typearray数组容器中.当操作完需要调用recycle()方法来实现回收.

这样就能解析自定义控件的属性设置, 来进行后续操作, 在这里去获取两种color, 设置button的text与textsize.

3. 使用自定义控件

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

    <com.example.DButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        custom:text="DButton" />

</LinearLayout>
声明自定义空间  xmlns:custom="http://schemas.android.com/apk/res/custom“ 使用自定义控件属性。下面会说道在其他项目中使用自定义控件的声明定义空间不太一样。

至此, 自定义控件实现完成.


如何在其他工程中使用自定义控件?

1. 在eclipse(或ADT)中

(1) 通过jar包的方式

     将自定义控件工程打成jar包, 然后将此jar包copy到引用的工程的libs目录下, 这时候需要注意:(当你的自定义控件引用了资源文件,需要将这些资源文件copy一份到引用控件的工程中. 例如DButton中使用了focus_1的图片作为DButton的背景, 那么这个时候我们再去使用DButton控件时, 需要将图片资源和attrs.xml复制到引用工程中).

     在xml中去使用DButton控件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res-auto/custom"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#999999"
    android:orientation="vertical"
    tools:ignore="ResAuto">

    <com.example.DButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        custom:text="DButton" />

</LinearLayout>

使用 xmlns:custom="http://schemas.android.com/apk/res-auto/custom"来加载命名空间, 这时候会报错, 需要加上tools:ignore="ResAuto" 来忽视错误.

(2) 通过library方式

如果不想将资源文件和attrs.xml复制到工程中, 将自定义控件作为library来进行编译, 在引用工程中去add这个library.

将项目作为library:

选中项目, 右键-->properties->android->选中is library--> 点击确定. 此时项目作为library.

引用项目使用自定义控件:

1).选中项目, 右键-->properties->android->在is library下有add按钮去添加library, 点击add选中自定义控件library.

2).在项目的配置文件中增加:android.library.reference.1=../library的名字

注意: 引入的project需要与当前使用项目统一目录,而且R文件会生成在当前项目中,要避免资源重名

接下来使用自定义控件方式和上面一样.


2. 在android studio中

android studio提供一种类似jar包的方式, aar包.通过aar包我们也不需要将资源文件与attrs文件copy到引用工程中.

生成aar包需要将项目作为android library, 所以如果想使用aar包, 需要在android studio中创建一个moudle(其实就是eclipse中的project) 作为android library, 然后再把代码移植到这里, 然后编译出aar包, aar包在build-->outputs-->aar目录下.

使用aar包:

(1) 把打好的aar包copy到引用的工程libs目录下

(2) 修改Android studio的gradle设置

 添加下面代码

repositories{
   flatDir{
        dirs 'libs'
   }
}
并且在dependencies中导入arr包

repositories {
    flatDir {
        dirs 'libs'
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.3.0'
    compile(name: 'app', ext: 'aar')  //导入名为app的aar包
}

接下来就可以使用自定义控件了, 使用方法和在eclipse中一样.




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章