先看看效果图
首先我们需要在values文件夹下新建一个attr.xml文件,保存我们自定义的属性
<resources>
<declare-styleable name="TopBar">
<attr name="tvTitle" format="string"/>
<attr name="titleTextSize" format="dimension"/>
<attr name="tvTitleTextColor" format="color"/>
<attr name="leftText" format="string"/>
<attr name="leftTextColor" format="color"/>
<attr name="leftBackGround" format="reference|color"/>
<attr name="rightText" format="string"/>
<attr name="rightBackGround" format="reference|color"/>
<attr name="rightTextColor" format="color"/>
</declare-styleable>
</resources>
这里说一下值得注意的地方:
1.根节点是declare-styleable
2.name属性用来指定属性的前缀,我们再代码中获取自定义属性时会用到,格式是”前缀_属性名”,这个前缀名是可以任意取得,不过一般我们让它和控件名称相同,便于识别
3.format定义属性类型,如果是背景,可以使用format=”reference|color”,因为背景可以是引用,也可以是颜色
然后看我们的TopBar.java文件
public class TopBar extends RelativeLayout {
private final Drawable mLeftBackground;
private final int mLeftTextColor;
private final String mLeftText;
private final String mRigthText;
private final Drawable mRightBackground;
private final int mRightTextColor;
private final int mColor;
private final float mTvTitleSize;
private final String mTvTitle;
public OnTopBarClickListener mListener;
private Button mRightButton;
private Button mLeftButton;
private TextView mTvTitle1;
public interface OnTopBarClickListener{
void leftClick();
void rightClick();
}
public TopBar(Context context, AttributeSet attrs) {
super(context, attrs);
//将declare-styleable中定义的属性值封装到typedArray中
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TopBar);
mTvTitle = typedArray.getString(R.styleable.TopBar_tvTitle);
mTvTitleSize = typedArray.getDimension(R.styleable.TopBar_titleTextSize, 20);
mColor = typedArray.getColor(R.styleable.TopBar_tvTitleTextColor, 0);
mLeftText = typedArray.getString(R.styleable.TopBar_leftText);
mLeftTextColor = typedArray.getColor(R.styleable.TopBar_leftTextColor, 0);
mLeftBackground = typedArray.getDrawable(R.styleable.TopBar_leftBackGround);
mRigthText = typedArray.getString(R.styleable.TopBar_rightText);
mRightBackground = typedArray.getDrawable(R.styleable.TopBar_rightBackGround);
mRightTextColor = typedArray.getColor(R.styleable.TopBar_rightTextColor, 0);
//回收资源,以便下次使用,在这之后,不能使用typedArray
typedArray.recycle();
initChildView(context);
}
/**
* 初始化控件
* @param context
*/
public void initChildView(Context context){
mTvTitle1 = new TextView(context);
mTvTitle1.setText(mTvTitle);
mTvTitle1.setTextColor(mColor);
mTvTitle1.setTextSize(mTvTitleSize);
mLeftButton = new Button(context);
mLeftButton.setText(mLeftText);
mLeftButton.setBackground(mLeftBackground);
mLeftButton.setTextColor(mLeftTextColor);
mRightButton = new Button(context);
mRightButton.setText(mRigthText);
mRightButton.setTextColor(mRightTextColor);
mRightButton.setBackground(mRightBackground);
//设置布局参数
RelativeLayout.LayoutParams leftParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.MATCH_PARENT);
//设定布局规则
leftParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT,TRUE);
addView(mLeftButton,leftParams);//添加到容器中
RelativeLayout.LayoutParams titleParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
titleParams.addRule(RelativeLayout.CENTER_IN_PARENT,TRUE);
addView(mTvTitle1, titleParams);
RelativeLayout.LayoutParams rightParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.MATCH_PARENT);
rightParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,TRUE);
addView(mRightButton,rightParams);
/**
* 设置监听
*/
mLeftButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mListener.leftClick();
}
});
mRightButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mListener.rightClick();
}
});
}
public void setOnTopBarClickListener(OnTopBarClickListener listener){
mListener = listener;
}
/**
* 设置可见性
* @param leftState
* @param rightState
*/
public void setTopBarVisible(boolean leftState,boolean rightState){
if(leftState){
mLeftButton.setVisibility(VISIBLE);
}else{
mLeftButton.setVisibility(GONE);
}
if(rightState){
mRightButton.setVisibility(VISIBLE);
}else{
mRightButton.setVisibility(GONE);
}
}
}
接下来我们再布局文件中定义这个标题栏布局
<?xml version="1.0" encoding="utf-8"?>
<com.example.administrator.myapplication.TopBar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:id="@+id/topbar"
android:background="#ff0000"
android:layout_width="match_parent"
android:layout_height="50dp"
custom:tvTitle="自定标题栏"
custom:titleTextSize="12sp"
custom:tvTitleTextColor="#ff00ff"
custom:leftText="返回"
custom:leftBackGround="#0000ff"
custom:leftTextColor="#000000"
custom:rightText="提交"
custom:rightTextColor="#FFFFFF"
custom:rightBackGround="#00ff00"
>
</com.example.administrator.myapplication.TopBar>
这里要注意,我们再attr.xml文件中使用的布局都要用到,否则就会出现某一个控件没法显示的问题
最后,在我们的布局文件中使用include包含这个标题栏就可以了
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.administrator.myapplication.MainActivity">
<include layout="@layout/topbar"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="内容"
/>
</LinearLayout>
public class MainActivity extends AppCompatActivity {
private TopBar mTopBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTopBar = (TopBar) findViewById(R.id.topbar);
mTopBar.setOnTopBarClickListener(new TopBar.OnTopBarClickListener() {
@Override
public void leftClick() {
Toast.makeText(MainActivity.this, "返回", Toast.LENGTH_SHORT).show();
}
@Override
public void rightClick() {
Toast.makeText(MainActivity.this, "提交", Toast.LENGTH_SHORT).show();
}
});
mTopBar.setTopBarVisible(true,true);
}
}