新建工程,在values新建resour flie,取名为attrs(attr是attribute 属性的简写,因为有多个属性,所以就取名为attrs )。
先举个栗子
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="myTop">
<attr name="mTitleText" format="string"/>
<attr name="mTitleTextColor" format="color"/>
<attr name="mTitleTextSize" format="dimension"/>
<attr name="leftBackground" format="color|reference"/>
<attr name="leftText" format="string"/>
<attr name="leftTextColor" format="color"/>
<attr name="rightBackground" format="color|reference"/>
<attr name="rightText" format="string"/>
<attr name="rightTextColor" format="color"/>
</declare-styleable>
</resources>
解释一下代码,resources是根节点,不用管,创建就会自动生成。declare-styleable
标签声明了使用自定义属性,并通过name属性来确定引用的名称.
然后declare下面有多个attr,即为定义的多个属性,每个自定义属性都有name和format,name不用说,format即为属性的类型。
属性定义好了,就要自定义一个View了
创建一个Class,取名为MyView,继承自ViewGroup(或者RelativeLayout或者LinearLayout),然后重写带两个参数的方法
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
}
然后在方法里写
TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.myTop);
通过TypeArray这样的数据结构来获取自定义属性集
再通过get×××获得属性值(这里属性太多,我就只写了一条获取属性值的例子)
String rightText = typedArray.getString(R.styleable.myTop_rightText);
全部属性都获取完成之后,那么TypeArray就已经没用了,所以最后执行
typedArray.recycle();//来完成资源的回收,避免重新创建的时候发生错误
然后再将属性值赋给控件的实例(这里的context即为上面两个参数的构造函数里面的一个参数)
Button rightBtn = new Button(context);
rightBtn.setText(rightText);
OK!到现在我们已经自定义了多个属性,并把属性赋给了新建的控件,然后该为组件设置布局了吧
private LayoutParams titleParam;
titleParam= new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
addView(title,titleParam);
到此为止,自定义View就差不多结束了。该去layout里面使用了吧
进入activity_main.xml 可以看到这样一行代码
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns即xml namespace。这里指定了名字控件为”android”,所以在下面的代码里才可以使用android:layout_width、android:layout_height等等以android开头的。所以,我们在下面加上一行
xmlns:myview="http://schemas.android.com/apk/res-auto"
这样我们就可以使用我们的自定义属性了,myview是名字,可以随便起。最后的res-auto是Android Studio里面使用的,而在eclipse里面需要加完整的包名。
下面我们就可以定义属性的值了
<com.example.antact.myview.MyView
android:id="@+id/my_view"
android:layout_width="match_parent"
android:layout_height="40dp"
myview:mTitleText="自定义标题"
myview:mTitleTextColor="#123456"
myview:mTitleTextSize="8sp"
myview:leftBackground="#678905"
myview:leftText="左按钮"
myview:leftTextColor="#456789"
myview:rightBackground="#678905"
myview:rightText="右按钮"
myview:rightTextColor="#456789">
</com.example.antact.myview.MyView>
到这里就自定义View就结束了。最后展示一下效果图
如果我们想为左右Button添加点击事件,你肯定想直接在MyView里面
leftBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
//Toast
}
});
但是这样写就把代码写死了,不一定每个调用这个View的leftButton的功能都是一样的。所以这里需要定义一个接口,并把接口暴露给调用者
private OnMyViewClickListener listener;
public interface OnMyViewClickListener{
void leftClick();
void rightClick();
}
public void setOnMyViewClickListener(OnMyViewClickListener mListener){
listener = mListener;
}
所以下面的Button只用写
leftBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
listener.leftClick();
}
});
具体的方法在MainActivity里面实现
MyView myView = (MyView)findViewById(R.id.my_view);
myView.setOnMyViewClickListener(new MyView.OnMyViewClickListener() {
@Override
public void leftClick() {
Toast.makeText(MainActivity.this,"leftButton",Toast.LENGTH_LONG).show();
}
@Override
public void rightClick() {
Toast.makeText(MainActivity.this,"rightButton",Toast.LENGTH_LONG).show();
}
});
通过如上所示的代码,我们可以在其他布局文件中,直接通过include使用模板。
到这里,所有的总结完成了。
最后,贴一下源码
attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="myTop">
<attr name="mTitleText" format="string"/>
<attr name="mTitleTextColor" format="color"/>
<attr name="mTitleTextSize" format="dimension"/>
<attr name="leftBackground" format="color|reference"/>
<attr name="leftText" format="string"/>
<attr name="leftTextColor" format="color"/>
<attr name="rightBackground" format="color|reference"/>
<attr name="rightText" format="string"/>
<attr name="rightTextColor" format="color"/>
</declare-styleable>
</resources>
MyView.java
package com.example.antact.myview;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView;
/**
* Created by Antact on 2017/5/13.
*/
public class MyView extends RelativeLayout{
private TextView title;
private Button leftBtn;
private Button rightBtn;
private RelativeLayout.LayoutParams titleParam,leftParam,rightParam;
private OnMyViewClickListener listener;
public interface OnMyViewClickListener{
void leftClick();
void rightClick();
}
public void setOnMyViewClickListener(OnMyViewClickListener mListener){
listener = mListener;
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.myTop);
int titleTextColor = typedArray.getColor(R.styleable.myTop_mTitleTextColor, 0);
String titleText = typedArray.getString(R.styleable.myTop_mTitleText);
float titleTextSize = typedArray.getDimension(R.styleable.myTop_mTitleTextSize, 0);
Drawable leftBackground = typedArray.getDrawable(R.styleable.myTop_leftBackground);
String leftText = typedArray.getString(R.styleable.myTop_leftText);
int leftColor = typedArray.getColor(R.styleable.myTop_leftTextColor, 0);
Drawable rightBackground = typedArray.getDrawable(R.styleable.myTop_rightBackground);
String rightText = typedArray.getString(R.styleable.myTop_rightText);
int rightColor = typedArray.getColor(R.styleable.myTop_rightTextColor, 0);
typedArray.recycle();
title = new TextView(context);
leftBtn = new Button(context);
rightBtn = new Button(context);
title.setTextColor(titleTextColor);
title.setText(titleText);
title.setTextSize(titleTextSize);
leftBtn.setBackground(leftBackground);
leftBtn.setText(leftText);
leftBtn.setTextColor(leftColor);
rightBtn.setBackground(rightBackground);
rightBtn.setText(rightText);
rightBtn.setTextColor(rightColor);
titleParam = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
titleParam.addRule(RelativeLayout.CENTER_IN_PARENT,TRUE);
addView(title,titleParam);
leftParam = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT);
leftParam.addRule(RelativeLayout.ALIGN_PARENT_LEFT,TRUE);
addView(leftBtn,leftParam);
rightParam = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT);
rightParam.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,TRUE);
addView(rightBtn,rightParam);
leftBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
listener.leftClick();
}
});
rightBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
listener.rightClick();
}
});
}
}
activity_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:myview="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.antact.myview.MyView
android:id="@+id/my_view"
android:layout_width="match_parent"
android:layout_height="40dp"
myview:mTitleText="自定义标题"
myview:mTitleTextColor="#123456"
myview:mTitleTextSize="8sp"
myview:leftBackground="#678905"
myview:leftText="左按钮"
myview:leftTextColor="#456789"
myview:rightBackground="#678905"
myview:rightText="右按钮"
myview:rightTextColor="#456789">
</com.example.antact.myview.MyView>
</RelativeLayout>
MainActivity.java
package com.example.antact.myview;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyView myView = (MyView)findViewById(R.id.my_view);
myView.setOnMyViewClickListener(new MyView.OnMyViewClickListener() {
@Override
public void leftClick() {
Toast.makeText(MainActivity.this,"leftButton",Toast.LENGTH_LONG).show();
}
@Override
public void rightClick() {
Toast.makeText(MainActivity.this,"rightButton",Toast.LENGTH_LONG).show();
}
});
}
}
/参考自Android群英传