Android中自定义组合控件

Android中自定义控件的情况非常多,一般自定义控件可以分为两种:继承控件及组合控件。前者是通过继承View或其子类,重写方法实现自定义的显示及事件处理方式;后者是通过组合已有的控件,来实现结构的简化和代码的重用。

本篇文章主要介绍自定义组合控件,继承控件后续有机会再述。

自定义组合控件一般来说都是以ViewGroup及其子类(LinearLayout、RelativeLayout、FrameLayout等)为主,内部嵌套其他控件,来组合成一个新的控件,实现一些特定的需要,可以是代码简化,结构清晰,重用性较高。

通常来说,我们会实现定义好一个Layout.xml文件,然后让我们的自定义控件去加载此xml,并获取子控件,然后设置属性(可以通过代码,也可以从资源文件中加载)、添加事件。

自定义要点:

1.加载xml文件是在构造方法中完成的,通过调用inflate(R.layout.my_layout, this , true ),注意第二个和第三个参数;

2.如果需要从资源文件中加载自定义的属性,则必须 重写Constructor(Context context, AttributeSet attrs) 此构造方法,属性是定义在attrs.xml中的;

3.获取子控件对象,可以在构造方法中获取,也可以 重写onFinishInflate()方法 来获取,个人建议采用第二种,可以保证控件已经完全加载好了。

4.添加事件可以直接在控件中写,不过考虑到扩展性及复用性,建议对外暴露接口。

示例代码(代码比较简单,只是描述一下思路)

自定义控件layout:header.xml

[XML]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
<? 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 = "wrap_content" >
   < ImageButton android:id = "@+id/ib_header"
     android:layout_width = "wrap_content"
     android:layout_height = "wrap_content"
     android:layout_alignParentRight = "true"
     android:layout_centerVertical = "true"
     android:src = "@android:drawable/ic_menu_zoom" />
   < TextView android:id = "@+id/tv_header"
     android:layout_width = "wrap_content"
     android:layout_height = "wrap_content"
     android:layout_centerInParent = "true" />
</ RelativeLayout >

自定义控件类:Header.java

[Java]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package com.ivan.app1.widgets;
import com.ivan.app1.R;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
/**
  * 自定义标题栏组合控件,内部包含一个TextView和一个ImageButton
  * User: xyh
  * Date: 2015/6/2
  * Time: 9:39
  */
public class Header extends RelativeLayout {
   private TextView mTextView;
   private ImageButton mImageButton;
   private String titleText;
   private int titleTextColor;
   private float titleTextSize;
   public Header(Context context) {
     super (context);
   }
   public Header(Context context, AttributeSet attrs) {
     super (context, attrs);
     //加载视图的布局
     LayoutInflater.from(context).inflate(R.layout.header, this , true );
     //加载自定义的属性
     TypedArray a=context.obtainStyledAttributes(attrs,R.styleable.Header);
     titleText=a.getString(R.styleable.Header_titleText);
     titleTextColor=a.getColor(R.styleable.Header_titleTextColor, Color.WHITE);
     titleTextSize=a.getDimension(R.styleable.Header_titleTextSize,20f);
     //回收资源,这一句必须调用
     a.recycle();
   }
   /**
    * 此方法会在所有的控件都从xml文件中加载完成后调用
    */
   @Override
   protected void onFinishInflate() {
     super .onFinishInflate();
     //获取子控件
     mTextView= (TextView) findViewById(R.id.tv_header);
     mImageButton= (ImageButton) findViewById(R.id.ib_header);
     //将从资源文件中加载的属性设置给子控件
     if (!TextUtils.isEmpty(titleText))
       setPageTitleText(titleText);
     setPageTitleTextColor(titleTextColor);
     setPageTitleTextSize(titleTextSize);
   }
   /**
    * 设置标题文字
    * @param text
    */
   public void setPageTitleText(String text) {
     mTextView.setText(text);
   }
   /**
    * 设置标题文字颜色
    * @param color
    */
   public void setPageTitleTextColor( int color) {
     mTextView.setTextColor(color);
   }
   /**
    * 设置标题文字大小
    * @param size
    */
   public void setPageTitleTextSize( float size) {
     mTextView.setTextSize(size);
   }
   /**
    * 设置按钮点击事件监听器
    * @param listener
    */
   public void setOnHeaderClickListener(OnClickListener listener) {
     mImageButton.setOnClickListener(listener);
   }
}

自定义属性文件:attrs.xml

[XML]  纯文本查看  复制代码
?
1
2
3
4
5
6
7
8
9
<? xml version = "1.0" encoding = "utf-8" ?>
< resources >
   <!-- 自定义的属性-->
   < declare-styleable name = "Header" >
     < attr name = "titleTextSize" format = "dimension" />
     < attr name = "titleTextColor" format = "color" />
     < attr name = "titleText" format = "string" />
   </ declare-styleable >
</ resources >

以下是引用方式,activity布局文件:main.xml

[XML]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<? xml version = "1.0" encoding = "utf-8" ?>
< LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android"
   android:orientation = "vertical"
   android:layout_width = "match_parent"
   android:layout_height = "match_parent" >
   <!-- 注意需要加上命名空间 在eclipse开发工具中:使用 xmlns:app="http://schemas.android.com/apk/res/com.ivan.app1.widgets"
      在IntelliJ Idea或者Android Studio中以Gradle构建时,使用 xmlns:app="http://schemas.android.com/apk/res-auto"
   -->
   <!-- 通过包的类的全名来引用自定义视图-->
   < com.ivan.app1.widgets.Header
     android:id = "@+id/header"
     android:layout_width = "match_parent"
     android:layout_height = "48dp"
     android:background = "@color/black"
     app:titleText = "我是标题"
     app:titleTextColor = "#ff0000"
     app:titleTextSize = "12sp" />
   < TextView android:layout_width = "match_parent"
     android:layout_height = "match_parent"
     android:gravity = "center"
     android:text = "我是内容"
     android:textSize = "60sp" />
</ LinearLayout >

主Activity类:MainActivity.java

[Java]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.ivan.app1;
import com.ivan.app1.widgets.Header;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Toast;
/**
  * User: xyh
  * Date: 2015/6/2
  * Time: 10:30
  */
public class MainActivity extends AppCompatActivity {
   @Override
   public void onCreate(Bundle savedInstanceState) {
     super .onCreate(savedInstanceState);
     setContentView(R.layout.main);
     ((Header)findViewById(R.id.header)).setOnHeaderClickListener( new View.OnClickListener() {
       @Override
       public void onClick(View v) {
         Toast.makeText(getApplicationContext(), "标题栏的按钮被点击了" ,Toast.LENGTH_LONG).show();
       }
     });
   }
}

运行结果:


原地址:http://www.cnblogs.com/ivan-xu/p/4545929.html?utm_source=tuicool
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值