Android自定义View TitleBar,通用标题栏

学过的东西把它记录下来,不仅加深印象,以后也会用的到……..(相信以后的你一定会感激现在拼命的自己)

绪论:

最近小编在学徐大牛的群英传,学到的东西记下来。今天小编来说一下Android自定义View中的自定义标题栏,因为标题栏在我们开发过程中用到的特别多,可以说每一个Activity中都会有标题栏,我们不可能每个布局文件中都去写那么多的代码,为了优化,我们可以定义一个通用的titlebar适合我们每个Activity用。接下来小编将会介绍两种自定义TitleBar的方法.

方法一:

创建复合控件,自定义属性。

  • 1.思路:

    • 1》自定义titlebar的属性
    • 2》组合控件
    • 3》实现接口
    • 4》引用自定义View
  • 2.实现方法:
    首先我们在values文件夹下新建一个attrs.xml,里面包含我们的titlebar中要用到的控件的一些属性,例如标题文本,颜色,字体大小等…

1
2
3
4
5
6
7
8
9
10
11
12
13
<resources>
<declare-styleable name="Title_bar">
<attr name="titleText" format="string"/>
<attr name="titleTextSize" format="dimension"/>
<attr name="titleColor" format="color"/>
<attr name="leftBtnText" format="string"/>
<attr name="leftBtnTextSize" format="dimension"/>
<attr name="leftBtnBackground" format="reference|color"/>
<attr name="rightBtnText" format="string"/>
<attr name="rightBtnTextSize" format="dimension"/>
<attr name="rightBtnBackground" format="reference|color"/>
</declare-styleable>
</resources>

定义好了属性时候,我们新建一个TitleBarView继承RelativeLayout,在构造方法中获取我们定义的属性值,通过TypeArray来获取自定义的属性值,并做一些初始化的工作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.Title_bar);
/**
* 初始化参数,获取属性值
* @param context 上下文
* @param ta
*/
private void init(Context context,TypedArray ta){
title = ta.getString(R.styleable.Title_bar_titleText);
leftBtnText = ta.getString(R.styleable.Title_bar_leftBtnText);
leftBtnBackground = ta.getDrawable(R.styleable.Title_bar_leftBtnBackground);
rightBtnText = ta.getString(R.styleable.Title_bar_rightBtnText);
rightBtnBackground = ta.getDrawable(R.styleable.Title_bar_rightBtnBackground);
titleTextSize = ta.getDimension(R.styleable.Title_bar_titleTextSize, 10);
leftBtnTextSize = ta.getDimension(R.styleable.Title_bar_leftBtnTextSize, 8);
rightBtnTextSize = ta.getDimension(R.styleable.Title_bar_rightBtnTextSize, 8);
titleTextColor = ta.getColor(R.styleable.Title_bar_titleColor, 0);
ta.recycle();
titleTv = new TextView(context);
leftBtn = new Button(context);
rightBtn = new Button(context);
/*设置标题文本*/
titleTv.setTextSize(titleTextSize);
titleTv.setText(title);
titleTv.setTextColor(titleTextColor);
/*设置左侧按钮*/
leftBtn.setText(leftBtnText);
leftBtn.setTextSize(leftBtnTextSize);
leftBtn.setBackground(leftBtnBackground);
/*设置右侧按钮*/
rightBtn.setText(rightBtnText);
rightBtn.setTextSize(rightBtnTextSize);
rightBtn.setBackground(rightBtnBackground);
/*设置控件参数*/
leftParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT);
leftParams.addRule(ALIGN_PARENT_LEFT,TRUE);
addView(leftBtn, leftParams);
rightParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT);
rightParams.addRule(ALIGN_PARENT_RIGHT,TRUE);
addView(rightBtn, rightParams);
titleParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT);
titleParams.addRule(CENTER_IN_PARENT,TRUE);
titleParams.addRule(CENTER_VERTICAL);
addView(titleTv, titleParams);
leftBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
listener.leftClick();
}
});
rightBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
listener.rightClick();
}
});
}

接下来我们定义一个接口,并创建左右按钮的点击事件

1
2
3
4
5
6
7
* 定义按钮点击接口,实现回调机制,通过映射的接口对象调用接口中的方法
* 而不用去考虑如何实现,具体实现由调用者去创建
*/
public interface TitleBarClickListener{
void leftClick(); //左侧按钮点击事件
void rightClick(); //右侧按钮点击事件
}

实现接口回调,在MainActivity中调用我们的按钮点击接口

1
2
3
4
5
6
7
8
9
10
11
12
titleBarView = (TitleBarView) findViewById(R.id.title_bar);
titleBarView.setOnTitleBarClickListener(new TitleBarView.TitleBarClickListener() {
@Override
public void leftClick() {
Toast.makeText(getApplicationContext(),"left",Toast.LENGTH_SHORT).show();
}
@Override
public void rightClick() {
Toast.makeText(getApplicationContext(),"right",Toast.LENGTH_SHORT).show();
}
});

当然我们还可以设置按钮的显示隐藏以及文字和其他的一些事件,随便定义好了,然后在调用者的地方进行调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**
* 设置左侧按钮是否可见
* @param flag 是否可见
*/
public void setLeftBtnVisable(boolean flag){
if (flag){
leftBtn.setVisibility(VISIBLE);
}else {
leftBtn.setVisibility(GONE);
}
}
/**
* 设置右侧按钮是否可见
* @param flag 是否可见
*/
public void setRightBtnVisable(boolean flag){
if (flag){
rightBtn.setVisibility(VISIBLE);
}else {
rightBtn.setVisibility(GONE);
}
1
2
3
4
5
6
7
8
9
10
11
12
btnLeft.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
titleBarView.setLeftBtnVisable(false);
}
});
btnRight.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
titleBarView.setRightBtnVisable(false);
}
});

最后是怎样引用我们的自定义的view了,在我们的布局中添加如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<com.hankkin.textviewdemo.view.TitleBarView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="55dp"
android:id="@+id/title_bar"
custom:titleText="标题1"
custom:titleTextSize="15sp"
custom:titleColor="#000"
custom:leftBtnText="返回"
custom:leftBtnTextSize="10sp"
custom:leftBtnBackground="#f8f8ff"
custom:rightBtnText="下一步"
custom:rightBtnTextSize="10sp"
custom:rightBtnBackground="#f8f8ff"
>
</com.hankkin.textviewdemo.view.TitleBarView>

自定标题栏就OK了

  • 3.总结:

个人在用的时候总觉得这种定义方式不是很方便,因为我们不好把控组件的样式和大小,而且还需要定义那么多的属性感觉有点麻烦,不要着急,下面介绍另一种方法:

方法二:

上一种是我们自定义属性来自定义我们的TitleBar,下面我们直接用LayoutInflate来直接引用我们的布局,然后在里面去修改我们的控件的样式属性

实现方法:

同样我们在构造方法中初始化一些组件属性,并把布局文件引用过来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public TitleBarView1(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
/**
* 初始化组件
* @param context
*/
private void init(Context context){
LayoutInflater.from(context).inflate(R.layout.titlebar1,this);
btnLeft = (Button) findViewById(R.id.btn_titlebar_left);
btnRight = (Button) findViewById(R.id.btn_titlebar_right);
tvTitle = (TextView) findViewById(R.id.tv_titlebar_name);
btnLeft.setOnClickListener(this);
btnRight.setOnClickListener(this);
}

其他的思路基本都差不多这里就不给大家多介绍了,把代码粘贴过来,小伙伴应该都可以看懂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
public void setTitleBarListener(BtnClickListener listener){
this.listener = listener;
}
/**
* 按钮点击接口
*/
public interface BtnClickListener{
void leftClick();
void rightClick();
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_titlebar_left:
listener.leftClick();
break;
case R.id.btn_titlebar_right:
listener.rightClick();
break;
default:
break;
}
}
/**
* 设置左侧按钮是否可见
* @param flag 是否可见
*/
public void setLeftBtnVisable(boolean flag){
if (flag){
btnLeft.setVisibility(VISIBLE);
}
else {
btnLeft.setVisibility(GONE);
}
}
/**
* 设置右侧按钮是否可见
* @param flag 是否可见
*/
public void setRightBtnVisable(boolean flag){
if (flag){
btnRight.setVisibility(VISIBLE);
}
else {
btnRight.setVisibility(GONE);
}
}

在MainActivity中调用

1
2
3
4
5
6
7
8
9
10
11
titleBarView1 = (TitleBarView1) findViewById(R.id.tbv_titlebar);
titleBarView1.setTitleBarListener(this);
@Override
public void leftClick() {
Toast.makeText(getApplicationContext(),"left",Toast.LENGTH_SHORT).show();
}
@Override
public void rightClick() {
Toast.makeText(getApplicationContext(),"right",Toast.LENGTH_SHORT).show();
}

最后看一下效果,样式不好看大家多包含,为了方便我把两个TitleBarView放在了一个布局文件中

好了代码放到了github上,小伙伴们求star

https://github.com/Hankkin/TitleBarViewDemo.git

在书上我们自定义的属性title、和titleTex跟最新的SDK冲突了,所以这两个属性值修改了,找到了徐哥也给徐哥提了issuse
推荐大家可以看看徐哥的Android群英传比较不错。