我们在开发Android界面时常常要在许多页面中共用风格相似的标题栏,为了减少重复性工作我们可以将标题栏做成一个通用的自定义控件。
我将通过两种形式的自定义方式介绍自定义TitleBar
第一种方式(不涉及自定义属性)
首先通过在Layout中建一个布局文件先确定Title的主要子控件titlebar.xml 如下包含2个Button 一个TextView
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="50dp"
android:background="@color/bg_title_bar"
android:orientation="horizontal" >
<Button
android:id="@+id/btn_left"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"/>
<TextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center" />
<Button
android:id="@+id/btn_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
当然如果我们之后不需要频繁改变上述布局中各个子控件的样式和内容,就可以直接在JAVA代码中获取并绑定监控器如下;
package com.example.briefvideo;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
/**
* 自定义的TitleBar控件
*
* @author baron 提供监听器接口,调用者可以实现监听器接口包含左右两个按钮的点击事件方法 然后绑定监听器
*/
public class TitleBarView extends LinearLayout {
// 右侧按钮属性
Button btnRight;
// 左侧按钮属性
Button btnLeft;
// 标题
TextView tvTitle;
BtnClickListener listener;
public TitleBarView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
/**
* 初始化组件
*
* @param context
*/
private void init(Context context) {
LayoutInflater.from(context).inflate(R.layout.titlebar, this);
btnLeft = (Button) findViewById(R.id.btn_left);
btnRight = (Button) findViewById(R.id.btn_right);
tvTitle = (TextView) findViewById(R.id.title);
btnLeft.setText(leftTxt);
if(leftable==false){
btnLeft.setVisibility(View.GONE);
}
btnRight.setText(rightTxt);
if(rightable==false){
btnRight.setVisibility(View.GONE);
}
btnLeft.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
listener.leftClick();
}
});
btnRight.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
listener.rightClick();
}
});
}
/**
* 提供加载自定义监听器方法
*
* @param listener
*/
public void setTitleBarListener(BtnClickListener listener) {
this.listener = listener;
}
/**
* 按钮点击接口,调用者实现
*/
public interface BtnClickListener {
void leftClick();
void rightClick();
}
/**
* 设置Titlebar内容(Java代码中设置)
*
* @param leftDrabable
* 左侧背景
* @param leftTxt
* 左侧文字
* @param titleTxt
* 中间标题
* @param rightDrawable
* @param rightleftTxt
* 右侧文字
*/
public void setTitleBarView(int leftDrabable, String leftTxt,
String titleTxt, int rightDrawable, String rightTxt) {
tvTitle.setText(titleTxt);
btnLeft.setText(leftTxt);
}
}
至此我们可以直接在代码中引用TitleBarView
<com.example.briefvideo.TitleBarView
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
</com.example.briefvideo.TitleBarView>
可以直接在java中利用TitleBar中提供的点击事件监听器给左右两个Button设置点击事件,同时可以通过setTitleBarView方法修改一些属性(buttong可见或不可见等)
第二种方式(利用自定义属性)
首先依旧是通过在Layout中建一个布局文件先确定Title的主要子控件titlebar.xml 如下包含2个Button 一个TextView
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="50dp"
android:background="@color/bg_title_bar"
android:orientation="horizontal" >
<Button
android:id="@+id/btn_left"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"/>
<TextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center" />
<Button
android:id="@+id/btn_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
然后我们在attrs.xml(如果values文件夹中没有attrs.xml则新建一个)添加自定义的属性
<resources>
<declare-styleable name="TitleBarView">
<attr name="titleText" format="string"/>
<attr name="titleSize" format="dimension"/>
<attr name="titleColor" format="color"/>
<attr name="leftText" format="string"/>
<attr name="leftDrawable" format="reference"/>
<attr name="leftTextColor" format="color"/>
<attr name="leftBackground" format="reference|color"/>
<attr name="leftable" format="boolean"/>
<attr name="rightText" format="string"/>
<attr name="rightTextColor" format="color"/>
<attr name="rightDrawable" format="reference"/>
<attr name="rightable" format="boolean"/>
<attr name="rightBackground" format="reference|color"/>
</declare-styleable>
<!-- between the icon and text. -->
<attr name="leftText">
<enum name="maintitle" value="极致影音" />
</attr>
</resources>
然后我们就可以在TitleBarView代码中获取到这些属性,并将属性与titlebar.xml布局中的3个子控件相绑定设置
/**
* 自定义的TitleBar控件
*
* @author baron 提供监听器接口,调用者可以实现监听器接口包含左右两个按钮的点击事件方法 然后绑定监听器
*/
public class TitleBarView extends LinearLayout {
// 右侧按钮属性
Button btnRight;
Drawable rightDrawable;
String rightTxt;
boolean rightable;
// 左侧按钮属性
Button btnLeft;
Drawable leftDrawable;
String leftTxt;
boolean leftable;
// 标题
TextView tvTitle;
tring titleTxt;
BtnClickListener listener;
public TitleBarView(Context context, AttributeSet attrs) {
super(context, attrs);
getStyle(context, attrs);
init(context);
}
public void getStyle(Context context, AttributeSet attrs) {
// 获取在attrs中设置的属性组
TypedArray array = context.obtainStyledAttributes(attrs,
R.styleable.TitleBarView);
// 右侧按钮属性
rightTxt = array.getString(R.styleable.TitleBarView_rightText);
rightDrawable = array
.getDrawable(R.styleable.TitleBarView_rightDrawable);
rightable= array.getBoolean(R.styleable.TitleBarView_rightable, true);
// 左侧按钮属性
leftTxt = array.getString(R.styleable.TitleBarView_leftText);
leftDrawable = array.getDrawable(R.styleable.TitleBarView_leftDrawable);
leftable= array.getBoolean(R.styleable.TitleBarView_rightable, true);
// 标题
titleTxt = array.getString(R.styleable.TitleBarView_titleText);
}
/**
* 初始化组件
*
* @param context
*/
private void init(Context context) {
LayoutInflater.from(context).inflate(R.layout.titlebar, this);
btnLeft = (Button) findViewById(R.id.btn_left);
btnRight = (Button) findViewById(R.id.btn_right);
tvTitle = (TextView) findViewById(R.id.title);
btnLeft.setText(leftTxt);
if(leftable==false){
btnLeft.setVisibility(View.GONE);<span style="white-space:pre"> </span>
}
btnRight.setText(rightTxt);
if(rightable==false){
btnRight.setVisibility(View.GONE);<span style="white-space:pre"> </span>
}
btnLeft.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
listener.leftClick();
}
});
btnRight.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
listener.rightClick();
}
});
}
/**
* 提供加载自定义监听器方法
*
* @param listener
*/
public void setTitleBarListener(BtnClickListener listener) {
this.listener = listener;
}
/**
* 按钮点击接口,调用者实现
*/
public interface BtnClickListener {
void leftClick();
void rightClick();
}
/**
* 设置Titlebar内容(Java代码中设置)
*
* @param leftDrabable
* 左侧背景
* @param leftTxt
* 左侧文字
* @param titleTxt
* 中间标题
* @param rightDrawable
* @param rightleftTxt
* 右侧文字
*/
public void setTitleBarView(int leftDrabable, String leftTxt,
String titleTxt, int rightDrawable, String rightTxt) {
tvTitle.setText(titleTxt);
btnLeft.setText(leftTxt);
}
}
至此我们可以直接在代码中引用TitleBarView,并且可以给我们自定义的属性设值
<com.example.briefvideo.TitleBarView
xmlns:titlebarview="http://schemas.android.com/apk/res/com.example.briefvideo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
titlebarview:titleText="极致影音">
</com.example.briefvideo.TitleBarView>
其中注意,一般我们在使用空间的属性时前面都会有 android: 这个是命名空间的指定
我们在XML布局中使用空间时都必须有<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
其实这里就是指定一个命名空间,意思就是android:这个命名的控件指向哪里。
显然我们要用自己定义的属性,也要指定命名空间,否则是无法识别的
如
xmlns:titlebarview="http://schemas.android.com/apk/res/com.example.briefvideo"
android:layout_width="match_parent"
titlebarview:titleText="极致影音"