以下内容整理自慕课网 Andoid UI模板设计
自定义控件的实现主要步骤
1.设计需要的属性
2.实现一个我们要定义的View
3.引用View,基本相同于引用系统的控件
这里,我们实现一个简单的Topbar为例,只有leftButton,tittle,rightButton三个部分
首先,在values 下新建一个 attr.xml ,用于保存要自定义的控件需要用到的属性
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="Topbar">
<attr name="tittle" format="string"/>
<attr name="tittleTextSize" format="dimension"/>
<attr name="tittleTextColor" format="color"/>
<attr name="leftTextColor" format="color"/>
<attr name="leftBackground" format="reference|color"/>
<attr name="leftText" format="string"/>
<attr name="rightTextColor" format="color"/>
<attr name="rightBackground" format="reference|color"/>
<attr name="rightText" format="string"/>
</declare-styleable>
</resources>
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView;
/**
* Created by wjc on 2017/1/9.
*/
public class Topbar extends RelativeLayout {
private Button leftButton,rightButton;
private TextView tvTittle;
private int leftTextColor;
private Drawable leftBackground;
private String leftText;
private int rightTextColor;
private Drawable rightBackground;
private String rightText;
private float titleTextSize;
private int tittleTextColor;
private String tittle;
private LayoutParams leftParams,rightParams,tittleParams;
private topbarClickListener listener;
//回调接口,具体的点击事件可以在调用方实现接口的时候设定
public interface topbarClickListener{
public void leftClick();
public void rightClick();
}
//为两个Buttton定义点击事件
public void setOnTopbarClickListener(topbarClickListener listener){
this.listener=listener;
}
public Topbar(Context context, AttributeSet attrs) {
super(context, attrs);
//使用TypedArray保存在xml文件中自定义的值
TypedArray ta=context.obtainStyledAttributes(attrs,R.styleable.Topbar);
//默认值为0
leftTextColor=ta.getColor(R.styleable.Topbar_leftTextColor,0);
leftBackground=ta.getDrawable(R.styleable.Topbar_leftBackground);
leftText=ta.getString(R.styleable.Topbar_leftText);
rightTextColor=ta.getColor(R.styleable.Topbar_rightTextColor,0);
rightBackground=ta.getDrawable(R.styleable.Topbar_rightBackground);
rightText=ta.getString(R.styleable.Topbar_rightText);
titleTextSize=ta.getDimension(R.styleable.Topbar_tittleTextSize,0);
tittleTextColor=ta.getColor(R.styleable.Topbar_tittleTextColor,0);
tittle=ta.getString(R.styleable.Topbar_tittle);
//在使用完TypedArray之后,进行回收,避免浪费资源和一些其他的错误
ta.recycle();
//实例化所需的子控件
leftButton=new Button(context);
rightButton=new Button(context);
tvTittle=new TextView(context);
//将xml中定义过的属性赋值给控件,也可以新加入一些属性作为默认属性设置
leftButton.setTextColor(leftTextColor);
leftButton.setBackground(leftBackground);
leftButton.setText(leftText);
rightButton.setTextColor(rightTextColor);
rightButton.setBackground(rightBackground);
rightButton.setText(rightText);
tvTittle.setTextColor(tittleTextColor);
tvTittle.setTextSize(titleTextSize);
tvTittle.setText(tittle);
tvTittle.setGravity(Gravity.CENTER);
setBackgroundColor(0xFFF33333);
//所有的布局属性都是设置在LayoutParams
//设定自定义子控件的宽高参数,以及在ViewGroup(RelativeLayout)中的位置
leftParams=new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
leftParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT,TRUE);//这里的TRUE是一个int
rightParams=new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
rightParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,TRUE);
tittleParams=new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.MATCH_PARENT);
tittleParams.addRule(RelativeLayout.CENTER_IN_PARENT,TRUE);
//将自控件加入ViewGroup中
addView(leftButton,leftParams);
addView(rightButton,rightParams);
addView(tvTittle,tittleParams);
//这里的点击事件实际是由Topbar的调用方来实现的
leftButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
listener.leftClick();
}
});
rightButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
listener.rightClick();
}
});
}
}
自定义控件在xml布局文件中的使用,需要先引入自定义的namespace
这里的属性就是一开始自定义的控件属性,引用控件的时候使用完整的包名
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:myns="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="jintong.slidemenu.MainActivity">
<jintong.slidemenu.Topbar
android:id="@+id/topbar"
android:layout_width="match_parent"
android:layout_height="50dp"
myns:leftBackground="#734f4f"
myns:leftText="Back"
myns:leftTextColor="#ffffff"
myns:rightText="More"
myns:rightTextColor="#ffffff"
myns:rightBackground="#734f4f"
myns:tittle="我的标题"
myns:tittleTextColor="#6d9bc2"
myns:tittleTextSize="10sp"
>
</jintong.slidemenu.Topbar>
</RelativeLayout>
Topbar topbar= (Topbar) findViewById(R.id.topbar);
assert topbar != null;
topbar.setOnTopbarClickListener(new Topbar.topbarClickListener() {
@Override
public void leftClick() {
Toast.makeText(MainActivity.this,"left",Toast.LENGTH_SHORT).show();
}
@Override
public void rightClick() {
Toast.makeText(MainActivity.this,"right",Toast.LENGTH_SHORT).show();
}
});