- 创建复合控件可以很好的创建具有重用功能的控件集合,这种方式通常需要
- 继承一个合适的ViewGroup。在给它添加指定功能的控件,从而组合成一个新的复合
- 控件。通过这种方式创建的控件,我们一般会给它指定一些可配置的属性。
1、 如何创建自定义属性
- 在Android中要增加自定义属性,需要依靠attrs.xml文件。(建立在res资源文
- 件下的values目录下),并通过该文件定义相应的属性即可。
- 以一个topBar为例,一个APP中,每个活动都有一个共同的topBar,我们可以
- 把它提取出来形成一个共通的UI组件,这里自定义了文字,大小,背景图片,
- 颜色属性。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="TopBar">
<!--标题属性 -->
<attr name="myTitle" format="string" />
<!-- dimension dp-->
<attr name="titleTextSize" format="dimension" />
<attr name="titleColor" format="color" />
<attr name="titleGravity" format="integer" />
<!-- 左按钮-->
<attr name="leftText" format="string" />
<attr name="leftBackGround" format="color|reference" />
<attr name="leftTextColor" format="color" />
<!--右按钮-->
<attr name="rightText" format="string" />
<attr name="rightBackground" format="color|reference" />
<attr name="rightTextColor" format="color" />
</declare-styleable>
</resources>
- < declare-styleable> 声明使用自定义属性。并通过name属性来确定引用的
- 名称。
在通过< attr/>来声明具体的自定义属性。
4.通过 format 属性来指定属性的类型。可以使用|来分隔不同
的属性
目前已知的属性有这些:
reference 资源类型,通常是@开头,例如@+id/xxxx,@id/xxxxx
string 字符串类型,通常是文字信息
dimension 浮点类型,通常是尺寸度量,单位有很多px,dp,sp,dip等
color 颜色类型,通常是颜色16进制代码,支持ARGB。
boolean 布尔类型,true和false
enum 枚举类型,通常是代表这个属性提供了几种值来进行选择,并且只能选择这几种中的一个
flag 与enum基本没有区别。
integer 整数类型,通常是整数获取XML中自定义的属性
TypedArray typedArray =
context.obtainStyledAttributes(attrs, R.styleable.TopBar);
- R.styleable .TopBar指定的就是 < declare-styleable name=”TopBar”>指
- 定的name名。接下来就可以通过typearray.getString(),getColor(),get…
- 获取到定义的属性值。代码如下
/**
* 组合新的复合控件,添加到ViewGroup中
* */
private void initTopbar(Context context,AttributeSet attrs){
//获取xml中定义的属性
TypedArray typedArray =context.obtainStyledAttributes(attrs, R.styleable.TopBar);
titleName = typedArray.getString(R.styleable.TopBar_myTitle);
titleTextSize = typedArray.getDimension(R.styleable.TopBar_titleTextSize,10);
titleColor = typedArray.getColor(R.styleable.TopBar_titleColor,0);
titleGravity = typedArray.getInteger(R.styleable.TopBar_titleGravity,10);
leftText = typedArray.getString(R.styleable.TopBar_leftText);
leftBackGround = typedArray.getDrawable(R.styleable.TopBar_leftBackGround);
leftTextColor = typedArray.getColor(R.styleable.TopBar_leftTextColor,0);
rightText = typedArray.getString(R.styleable.TopBar_rightText);
rightBackGround = typedArray.getDrawable(R.styleable.TopBar_rightBackground);
rightTextColor = typedArray.getInt(R.styleable.TopBar_rightTextColor,0);
typedArray.recycle();
Button leftBtn = new Button(context);
Button rightBtn = new Button(context);
TextView titleText = new TextView(context);
leftBtn.setText(leftText);
leftBtn.setBackground(leftBackGround);
leftBtn.setTextColor(leftTextColor);
LayoutParams leftParams =
new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.MATCH_PARENT);
leftParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT,TRUE);
addView(leftBtn,leftParams);
rightBtn.setText(rightText);
rightBtn.setBackground(rightBackGround);
rightBtn.setTextColor(rightTextColor);
LayoutParams rightParams =
new LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
rightParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,TRUE);
addView(rightBtn,rightParams);
titleText.setText(titleName);
titleText.setTextSize(titleTextSize);
titleText.setTextColor(titleColor);
titleText.setGravity(titleGravity);
LayoutParams titleParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
titleParams.addRule(RelativeLayout.CENTER_IN_PARENT,TRUE);
addView(titleText,titleParams);
addListener(leftBtn,rightBtn);
}
/**
* 为左右按钮添加了点击监听的接口回调
* @param leftBtn 左边button
* @param rightBtn 右边 button
* */
private void addListener(Button leftBtn,Button rightBtn) {
leftBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mListener.leftClick();
}
});
rightBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mListener.rightClick();
}
});
}
/**
* 对外暴漏一个方法来给调用者注册接口
* 通过接口来获得回调着对接口方法的实现。
* */
public void setOntopbarClickListener(TopbarClickListener mListener){
this.mListener = mListener;
}
public interface TopbarClickListener{
void leftClick();
void rightClick();
}
- 这样一个TopBar的模板就已经制定完成了。并提供了接口回调,并将
- 左右按钮的点击事件交给调用方处理。(接口回调的思想)
- 调用方,引用自定义的ViewGroup,并设置属性
<?xml version="1.0" encoding="utf-8"?>
<com.xiaoxu.administrator.myserviceapp.view.MyTopbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:topbar ="http://schemas.android.com/apk/res-auto"
android:id="@+id/topBar"
android:layout_width="wrap_content"
android:layout_height="50dp"
topbar:myTitle ="自定义标题"
topbar:titleTextSize="10dp"
topbar:titleColor ="#123412"
topbar:titleGravity ="20"
topbar:leftText="返回"
topbar:leftBackGround="@drawable/left_pic"
topbar:leftTextColor ="#FFFFFF"
topbar:rightText="下一页"
topbar:rightBackground="@drawable/right_pic"
topbar:rightTextColor="#FFFFFF">
</com.xiaoxu.administrator.myserviceapp.view.MyTopbar>
-然后 再任何一个活动的布局中都可以引用如下
- 就将设置好的属性设置到当前的活动中了。
<include layout="@layout/topbar_layout"/>
- 找到标题的group的实例,并将接口的对象传入,自身实现具体的逻辑。
MyTopbar myTopbar = (MyTopbar) findViewById(R.id.topBar);
myTopbar.setOntopbarClickListener(new MyTopbar.TopbarClickListener() {
@Override
public void leftClick() {
//点击左按钮
Toast.makeText(SecondActivity.this," LeftClick ",Toast.LENGTH_SHORT).show();
}
@Override
public void rightClick() {
//点击右按钮
Toast.makeText(SecondActivity.this," RightClick ",Toast.LENGTH_SHORT).show();
}
});
效果如图,看着挺low的,没有好图片,随意弄了两张,有图片再改也不费事。哈哈