android自定义控件并添加属性的方法以及示例

安卓系统为我们提供了丰富的控件,但是在实际项目中我们仍然需要重新通过布局来实现一些效果,比如我们需要一个上面图标,下面文字的button,类似于下面这样的:

最直接的解决办法是通过将imageview和textview放在一个垂直排列的LinearLayout中,如下:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent"

    android:gravity="center"

    android:orientation="vertical"

>

    <ImageView

        android:id="@+id/icon_part"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_gravity="center"

        />

    <TextView

        android:id="@+id/text_part"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_gravity="center"

        android:textColor="#000000"

/>

</LinearLayout>

但是每一个button都需要这么长的代码,上面三个按钮的话就需要重复写三次,而且别人一看是个LinearLayout,不会将它button联系起来。

如果有一种办法能将上面那个布局组合成一个控件就好了。

的确是有办法的。主要有两方面的工作。

1.新建一个继承自LinearLayout的类(也可以是其他布局类,不过LinearLayout好像比较合适),然后通过inflater在这个类的构造函数中将上面的布局添加进去。

2.为了能在xml中也给这个自定义控件赋予属性来获得现实效果,比如字体大小、图标资源等,我们还需要在attrs文件中申明一些自定义属性。你可以查阅declare-styleable了解这是怎么回事。

我这里有一个已经实现了这种button效果的类FlexImageButton:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

package
com.jcodecraeer.client.widget;

import
com.jcodecraeer.client.R;

import
android.content.Context;

import
android.content.res.TypedArray;

import
android.graphics.drawable.Drawable;

import
android.util.AttributeSet;

import
android.view.LayoutInflater;

import
android.view.View;

import
android.widget.ImageView;

import
android.widget.LinearLayout;

import
android.widget.TextView;

public
class FlexImageButton extends LinearLayout {

    private
ImageView imageView;

    private
TextView textView;

    private
CharSequence text;

    private
Drawable drawable;

    private
float textSize;

    public
FlexImageButton(Context context) {

        super(context);

        //
TODO Auto-generated constructor stub

    }

    public
FlexImageButton(Context context, AttributeSet attrs) {

        super(context,
attrs);

        //
TODO Auto-generated constructor stub

        TypedArray
a = context.obtainStyledAttributes(attrs, R.styleable.FlexImageButton);

        text
= a.getText(R.styleable.FlexImageButton_text);

        if(text==null){

            text="";

        }

        Drawable
d = a.getDrawable(R.styleable.FlexImageButton_src);

        if

(d !=
null)
{

            drawable=d;

        }
else

{

            throw

new

RuntimeException(
"图像资源为空");

        }

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 

        textSize
= a.getDimension(R.styleable.FlexImageButton_textSize,12);

        String
infService = Context.LAYOUT_INFLATER_SERVICE;

        LayoutInflater
inflater = (LayoutInflater) context

                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        inflater.inflate(R.layout.flex_image_button_layout,
this);

        imageView
= (ImageView) findViewById(R.id.icon_part);

        imageView.setImageDrawable(drawable);

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 

        textView
= (TextView) findViewById(R.id.text_part);

        textView.setTextSize((float)
textSize);

        textView.setText(text);

        if(text.equals("")||text==null){

            textView.setVisibility(View.GONE);

        }

        a.recycle();

    }

    public
void setImageResource(int resId) {

        imageView.setImageResource(resId);

    }

    public
void setTextViewText(String text) {

        textView.setText(text);

    }

}

在attrs.xml文件中我们声明一些自定义属性,这里我们希望我的FlexImageButton能拥有可以灵活设置的文字属性,字体大小属性、图标资源属性,因此我这样定义:


1

2

3

4

5

6

7

<resources>

    <declare-styleable
name=
"FlexImageButton">

        <attr
name=
"text"

format=
"reference"/>

        <attr
name=
"src"

format=
"reference"/>

        <attr
name=
"textSize" 

format=
"dimension"/>

    </declare-styleable>

</resources>

其中format="reference"表示这个属性的值类型是资源id,也就是说在使用FlexImageButton的时候我只可以用资源id来为这个属性赋值。属性值类型有那些,我在文章结尾的附录里面一一列出。

上面我们已经完成了一个自定义的控件,activity的布局文件中如下使用FlexImageButton:


1

2

3

4

5

6

7

8

9

10

11

12

13

<com.jcodecraeer.client.widget.FlexImageButton

    android:layout_height="fill_parent"       

    android:layout_width="50dip"

    cl:src="@drawable/toolbar_collect"

    cl:text="@string/collect"

    android:clickable="true"

    android:focusable="true"

    android:layout_marginLeft="5dip"

    android:layout_marginRight="5dip"

    android:contentDescription="收藏"

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               

    android:background="@drawable/back_selector"

/>

仔细的人会注意到所有这些属性中,有两种形式。其中凡是android:开头的都是系统属性,而


1

2

cl:src="@drawable/toolbar_collect"

cl:text="@string/collect"

为我自定义的属性,为什么是cl:开头?

你也可以不用cl开头,但是不管你用什么开头,如果你用到了自定义属性,你都必须在activity布局文件的最开始这样声明:


1

2

3

4

<?xml
version=
"1.0"

encoding=
"utf-8"?>

<RelativeLayout

    xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:cl="http://schemas.android.com/apk/res/com.jcodecraeer.client"

其中cl就是刚刚用到的,com.jcodecraeer.client为我的apk包名,注意是apk包名,而不是你自定义控件的在包中的路径。

附录:自定义属性的值类型:

1. reference:参考某一资源ID。

(1)属性定义:


1

2

3

<declare-styleable
name=
"名称">

    <attr
format=
"reference"

name=
"background"

/>

</declare-styleable>

(2)属性使用:


1

2

3

4

<ImageView

    android:layout_width="42dip"

    android:layout_height="42dip"

    android:background="@drawable/图片ID"

/>

2. color:颜色值。

(1)属性定义:


1

2

3

<declare-styleable
name=
"名称">

    <attr
format=
"color"

name=
"textColor"

/>

</declare-styleable>

(2)属性使用:


1

2

3

4

<TextView

    android:layout_width="42dip"

    android:layout_height="42dip"

    android:textColor="#00FF00"

/>

3. boolean:布尔值。

(1)属性定义:


1

2

3

<declare-styleable
name=
"名称">

    <attr
format=
"boolean"

name=
"focusable"

/>

</declare-styleable>

(2)属性使用:


1

2

3

4

<Button

    android:layout_width="42dip"

    android:layout_height="42dip"

    android:focusable="true"

/>

4. dimension:尺寸值。

(1)属性定义:


1

2

3

<declare-styleable
name=
"名称">

    <attr
format=
"dimension"

name=
"layout_width"

/>

</declare-styleable>

(2)属性使用:


1

2

3

<Button

    android:layout_width="42dip"

    android:layout_height="42dip"

/>

5. float:浮点值。

(1)属性定义:


1

2

3

4

<declare-styleable
name=
"AlphaAnimation">

    <attr
format=
"float"

name=
"fromAlpha"

/>

    <attr
format=
"float"

name=
"toAlpha"

/>

</declare-styleable>

(2)属性使用:


1

2

3

<alpha

    android:fromAlpha="1.0"

    android:toAlpha="0.7"

/>

6. integer:整型值。

(1)属性定义:


1

2

3

4

<declare-styleable
name=
"AnimatedRotateDrawable">

    <attr
format=
"integer"

name=
"frameDuration"

/>

    <attr
format=
"integer"

name=
"framesCount"

/>

</declare-styleable>

(2)属性使用:


1

2

3

4

<animated-rotate

    android:frameDuration="100"

    android:framesCount="12"

     />

7. string:字符串。

(1)属性定义:


1

2

3

<declare-styleable
name=
"MapView">

    <attr
format=
"string"

name=
"apiKey"

/>

</declare-styleable>

(2)属性使用:


1

2

3

4

<com.google.android.maps.MapView

    android:layout_width="fill_parent"

    android:layout_height="fill_parent"

    android:apiKey="0jOkQ80oD1JL9C6HAja99uGXCRiS2CGjKO_bc_g"

/>

8. fraction:百分数。

(1)属性定义:


1

2

3

4

<declare-styleable
name=
"RotateDrawable">

    <attr
format=
"fraction"

name=
"pivotX"

/>

    <attr
format=
"fraction"

name=
"pivotY"

/>

</declare-styleable>

(2)属性使用:


1

2

3

4

<rotate

    android:pivotX="200%"

    android:pivotY="300%"

    />

9. enum:枚举值。

(1)属性定义:


1

2

3

4

5

6

<declare-styleable
name=
"名称">

    <attr
name=
"orientation">

        <enum
name=
"horizontal"

value=
"0"

/>

        <enum
name=
"vertical"

value=
"1"

/>

    </attr>

</declare-styleable>

(2)属性使用:


1

2

3

<LinearLayout

    android:orientation="vertical"

>

</LinearLayout>

10. flag:位或运算。

(1)属性定义:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

<declare-styleable
name=
"名称">

    <attr
name=
"windowSoftInputMode">

        <flag
name=
"stateUnspecified"

value=
"0"

/>

        <flag
name=
"stateUnchanged"

value=
"1"

/>

        <flag
name=
"stateHidden"

value=
"2"

/>

        <flag
name=
"stateAlwaysHidden"

value=
"3"

/>

        <flag
name=
"stateVisible"

value=
"4"

/>

        <flag
name=
"stateAlwaysVisible"

value=
"5"

/>

        <flag
name=
"adjustUnspecified"

value=
"0x00"

/>

        <flag
name=
"adjustResize"

value=
"0x10"

/>

        <flag
name=
"adjustPan"

value=
"0x20"

/>

        <flag
name=
"adjustNothing"

value=
"0x30"

/>

    </attr>

</declare-styleable>

(2)属性使用:


1

2

3

<activity

    android:windowSoftInputMode="stateUnspecified
| stateUnchanged | stateHidden"

>

</activity>

注意:属性定义时可以指定多种类型值:

(1)属性定义:


1

2

3

<declare-styleable
name=
"名称">

    <attr
format=
"reference|color"

name=
"background"

/>

</declare-styleable>

(2)属性使用:


1

2

3

4

<ImageView

    android:layout_width="42dip"

    android:layout_height="42dip"

    android:background="@drawable/图片ID|#00FF00"

/>


时间: 2024-12-02 11:50:54

android自定义控件并添加属性的方法以及示例的相关文章

android 布局-Android自定义控件,引用里面的方法,如何引用

问题描述 Android自定义控件,引用里面的方法,如何引用 我自己定义了一个继承自gridview的类,主布局引用,想在主布局里再添加一个button,然后这个button点击处理事件是自定义控件里的一个方法,该怎么调用? new mygridview().方法:不能实现,点击按钮后,程序崩溃 解决方案 你自定义的控件如果是在xml文件中添加到主布局,需要通过findViewById()获取控件的实例,然后调用其方法. 自定义如果是mygridview view=new mygridview(

Javascript创建自定义对象:创建Object实例添加属性和方法

文章简介:创建自定义对象的最简单的方式就是创建一个Object实例,然后再为它添加属性和方法. 创建自定义对象的最简单的方式就是创建一个Object实例,然后再为它添加属性和方法,如下所示: var person = new Object(); person.name = "Nicholas"; person.age = "29" person.job = "Software Engineer"; person.sayName = functio

Groovy探索之MOP 八 运行期内给类和对象添加属性或方法

我们都知道,在Groovy语言中,我们可以使用MOP特性在运行期内添加属性或方法. 这种添加包括两个层面的添加: 第一, 是给一个类添加属性或方法.也就是说,如果我们在运行期内给一个类添加了属性或方法,那么添加了以后,所有这个类实例化的对象,都将拥有了这个属性或方法. 第二, 第二,是给一个对象添加属性或方法.也就是说,如果我们在运行期内给一个对象添加了属性或方法,那么添加了以后,只有这个对象才拥有这个属性或方法.换句话说,如果我们再给这个对象的类实例化一个对象,那么该对象则不能拥有我们刚添加的

Javascript 创建类并动态添加属性及方法的简单实现_javascript技巧

JavaScript 是一种很强的面向对象的语言,支持创建实例之后再添加属性和方法,虽然是小技巧,用的时候容易忘记,今天写了一个很小的例子,记录在这里,仅供参考. function MyClass() { //This function is same as a constructer alert("New Object Created"); } //Creating Object var MyObject = new MyClass (); NewObject.prototype =

iOS 运行时添加属性和方法

  第一种:runtime.h里的方法BOOL class_addProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount) #include <objc/runtime.h> #import <Foundation/Foundation.h> @interface SomeClass : NSObject { NSSt

Javascript创建自定义对象 创建Object实例添加属性和方法_javascript技巧

如下所示: 复制代码 代码如下: var person = new Object(); person.name = "Nicholas"; person.age = "29" person.job = "Software Engineer"; person.sayName = function () { alert(this.name); }; person.sayName();上面的例子创建了一个名为person的对象,并为它添加了三个属性(n

往Android系统中添加服务的方法教程

前言 最近因为公司的平台要从Android 4.4.4 转战 Android 6.0, 带来的问题是之前我们在系统中添加了一些服务, 于是要将一些系统级的服务迁移过去,以及一些Framework 的自定义包. 碰巧在Gerrit上看到了添加系统服务这一块的patch.正好做个总结.虽然我不是Framework工程师, 但是了解Android系统还是很有好处的. 如何获取系统服务 我们获取系统服务都是在context中,getSystemService获取到的. 那么我们看一下getSystemS

javascript动态添加、修改、删除对象的属性与方法详解_javascript技巧

现在介绍如何为一个对象添加.修改或者删除属性和方法.在其他语言中,对象一旦生成,就不可更改了,要为一个对象添加修改成员必须要在对应的类中修改,并重新实例化,而且程序必须经过重新编译.JavaScript 中却非如此,它提供了灵活的机制来修改对象的行为,可以动态添加.修改.删除属性和方法.例如首先使用类Object来创建一个空对象user:var user=new Object(); 1.添加属性这时user 对象没有任何属性和方法,显然没有任何用途.但可以为它动态的添加属性和方法,例如:user

javascript的函数、创建对象、封装、属性和方法、继承_javascript技巧

一,function 从一开始接触到js就感觉好灵活,每个人的写法都不一样,比如一个function就有N种写法 如:function showMsg(){},var showMsg=function(){},showMsg=function(){} 似乎没有什么区别,都是一样的嘛,真的是一样的吗,大家看看下面的例子 复制代码 代码如下: ///----------------------------------------------------------------------------