前言
在Android应用的开发中少不了导航栏的使用,Android 3.0 推了 ActionBar, 5.0开始推出的一个 Material Design 风格的导航控件Toolbar,这些控件也是在致力于帮助我们在App中打造一个统一的导航栏规范,在App上显得更加整体化。Toolbar相比ActionBar更加灵活,可以放到布局中的任何位置,不局限于顶部,开放了很多API,留给了开发者更多的扩展余地,相信很多开发者更乐于使用Toolbar,但是在这里我不打算遵循传统。
在项目开发中谷歌提供的这些控件可能无法满足我们项目需求,这个时候就需要通过自定义来实现,当然,这里我们就自定义一个HeadView,同样可以实现灵活,可扩展性强的导航栏。
通过自定义控件不仅仅是实现了导航栏的功能,更重要的是我们对自定义流程的明晰和实践的总结。
先上效果图:
分析
导航栏一般分为三个内容区域:左侧区域,中间标题栏,右侧区域,左侧和右侧通常是一个按钮或者ImageView,中间标题为TextView.因此我们可以把它分为三部分来实现,整体的父布局采用RelativeLayout,里面的三个区域采用LinearLayout,对外提供设置方法传递资源文件和监听接口回调。
实现
整体父布局common_head.xml
style样式
左侧区域common_head_left_img.xml
右侧区域common_head_right_img.xml
layout_actionbar.xml
HeadView的实现
private LinearLayout header_leftview_container;
private LinearLayout header_layout_rightview_container;
private ImageView left_button;
private ImageView right_button;
private LayoutInflater mInflater;
private TextViewtv_title;
private View header;
private OnLeftClickListener onleftclicklistener;
private OnRightClickListener onrightclicklistener;
一个参数的构造方法
public HeadView(Context context) {
this(context,null);
}
两个参数的构造方法
public HeadView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
三个构造参数的方法里面进行初始化操作init()
public HeadView(Context context, AttributeSet attrs,intdefStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
初始化方法init()
@SuppressLint("InflateParams")
private void init(Context context) {
mInflater= LayoutInflater.from(context);
header=mInflater.inflate(R.layout.common_head,null);
addView(header);
initViews();
}
枚举类型用于标示显示的模式
/**
*
*@authorMersens
*枚举类型的标题栏显示类型DEFAULT--默认显示左侧图标,右侧图标和标题ONLYTITLE--只显示标题
* LEFT--只显示左侧图标LEFTANDTITLE--只显示左侧图标和标题
*/
public enum HeaderStyle {
DEFAULT,ONLYTITLE,LEFT,LEFTANDTITLE,RIGHTANDTITLE;
}
对外提供init初始化方法,改方法传递一个枚举,用于初始化时候的模式
/**
*@authorMersens
根据类型进行初始化,可以通过addView()方法动态添加控件,然后设置其控件的显示
*@paramstyle
*/
public void init(HeaderStyle style) {
switch(style) {
caseDEFAULT:
removeViews();
defaultMethod();
break;
caseONLYTITLE:
removeViews();
tileMethod();
break;
caseLEFT:
removeViews();
leftMethod();
break;
caseLEFTANDTITLE:
removeViews();
backAndTitleMethod();
break;
caseRIGHTANDTITLE:
removeViews();
rightandtitle();
break;
}}
初始化右侧布局和title
private void rightandtitle() {
//设置title为可见
tv_title.setVisibility(View.VISIBLE);
View right_button_view =mInflater.inflate(
R.layout.common_head_right_img,null);
right_button= (ImageView) right_button_view
.findViewById(R.id.right_imageView);
//初始化右侧按钮,并添加到右侧父布局内
header_layout_rightview_container.addView(right_button_view);
right_button.setOnClickListener(newOnClickListener() {
@Override
public voidonClick(View v) {
//接口回调
if(onrightclicklistener!=null) {
onrightclicklistener.onClick();
}}});}
移除父布局内部的所有子控件
/**
*移除左右控件的子View
*/
private void removeViews() {
header_leftview_container.removeAllViews();
header_layout_rightview_container.removeAllViews();
}
初始化设置默认的模式,左侧,右侧和中间的标题都会显示
@SuppressLint("InflateParams")
public void defaultMethod() {
//设置title为可见
tv_title.setVisibility(View.VISIBLE);
View left_button_view =mInflater.inflate(
R.layout.common_head_left_img,null);
left_button= (ImageView) left_button_view.findViewById(R.id.imageView);
//初始化左侧按钮,并添加到左侧父布局内
header_leftview_container.addView(left_button_view);
View right_button_view =mInflater.inflate(
R.layout.common_head_right_img,null);
right_button= (ImageView) right_button_view
.findViewById(R.id.right_imageView);
//初始化右侧按钮,并添加到右侧父布局内
header_layout_rightview_container.addView(right_button_view);
left_button.setOnClickListener(newOnClickListener() {
@Override
public voidonClick(View v) {
//接口回调
if(onleftclicklistener!=null) {
onleftclicklistener.onClick();
}}});
right_button.setOnClickListener(newOnClickListener() {
@Override
public voidonClick(View v) {
//接口回调
if(onrightclicklistener!=null) {
onrightclicklistener.onClick();
}}});}
初始化只显示中间标题
public void tileMethod() {
tv_title.setVisibility(View.VISIBLE);
}
初始化左侧按钮布局
public void leftMethod() {
//初始化左侧按钮,并添加到左侧父布局内
View left_button_view =mInflater.inflate(
R.layout.common_head_left_img,null);
left_button= (ImageView) left_button_view.findViewById(R.id.imageView);
header_leftview_container.addView(left_button_view);
//添加监听事件
left_button.setOnClickListener(newOnClickListener() {
@Override
public voidonClick(View v) {
if(onleftclicklistener!=null) {
onleftclicklistener.onClick();
}}});}
对外提供设置左侧和中间标题的方法
private void backAndTitleMethod() {
tv_title.setVisibility(View.VISIBLE);
View left_button_view =mInflater.inflate(
R.layout.common_head_left_img,null);
left_button= (ImageView) left_button_view.findViewById(R.id.imageView);
header_leftview_container.addView(left_button_view);
left_button.setOnClickListener(newOnClickListener() {
@Override
public voidonClick(View v) {
if(onleftclicklistener!=null) {
onleftclicklistener.onClick();
}}});}
对外提供设置默认的显示模式,需要传递资源文件
public void setDefaultViewMethod(intleftsrcid, String title,
intrightsrcid, OnLeftClickListener onleftclicklistener,
OnRightClickListener onrightclicklistener) {
if(!TextUtils.isEmpty(title)) {
tv_title.setText(title);}
if(leftsrcid !=0)
left_button.setBackgroundResource(leftsrcid);
else
left_button.setBackgroundResource(R.mipmap.ic_menu_back);
if(rightsrcid !=0)
right_button.setBackgroundResource(rightsrcid);
else
right_button.setBackgroundResource(R.mipmap.ic_menu_camera);
setOnLeftClickListener(onleftclicklistener);
setOnRightClickListener(onrightclicklistener);
}
设置右侧和中间标题的方法
public void setRightAndTitleMethod(String title,intrightsrcid,
OnRightClickListeneronrightclicklistener) {
if(!TextUtils.isEmpty(title)) {
tv_title.setText(title);}
if(rightsrcid !=0)
right_button.setBackgroundResource(rightsrcid);
else
right_button.setBackgroundResource(R.mipmap.ic_menu_camera);
setOnRightClickListener(onrightclicklistener);
}
设置显示左侧和中间内容方法
public void setLeftWithTitleViewMethod(intleftsrcid, String title,
OnLeftClickListener onleftclicklistener) {
if(!TextUtils.isEmpty(title)) {
tv_title.setText(title);}
if(leftsrcid !=0)
left_button.setBackgroundResource(leftsrcid);
else
left_button.setBackgroundResource(R.mipmap.ic_menu_back);
setOnLeftClickListener(onleftclicklistener);
}
设置只显示中间标题的方法
public void setOnlyTileViewMethod(String title) {
if(!TextUtils.isEmpty(title)) {
tv_title.setText(title);
}}
设置只有右侧区域内容的方法
public void setLeftViewMethod(intleftsrcid,
OnLeftClickListener onleftclicklistener) {
if(leftsrcid !=0)
left_button.setBackgroundResource(leftsrcid);
else
left_button.setBackgroundResource(R.mipmap.ic_menu_back);
setOnLeftClickListener(onleftclicklistener);
}
左侧区域的点击回调接口
/**
*@author Mersens
*自定义接口回调,用于处理左侧按钮的点击事件
*/
public interfaceOnLeftClickListener {
voidonClick();
}
提供左侧区域set设置方法
public void setOnLeftClickListener(OnLeftClickListener onleftclicklistener) {
this.onleftclicklistener= onleftclicklistener;
}
右侧区域的点击回调接口
/**
*@author Mersens
*自定义接口回调,用于处理右侧侧按钮的点击事件
*/
public interface OnRightClickListener {
voidonClick();
}
提供右侧区域set设置方法
public void setOnRightClickListener(
OnRightClickListener onrightclicklistener) {
this.onrightclicklistener= onrightclicklistener;
}
我们在开发中通常会封装一些东西在BaseActivity中,当然,这里我们也采用封装的方式,我们写一个BaseActivity,让他继承AppCompatActivity,然后再内部提供设置的方法就可以:
设置默认方式
public void setDefaultViewMethod(intleftsrcid, String title,intrightsrcid, HeadView.OnLeftClickListener onleftclicklistener, HeadView.OnRightClickListener onrightclicklistener) {
mHeadView= (HeadView) findViewById(R.id.common_actionbar);
mHeadView.init(HeadView.HeaderStyle.DEFAULT);
mHeadView.setDefaultViewMethod(leftsrcid, title, rightsrcid, onleftclicklistener, onrightclicklistener);
}
设置右侧内容和标题
public void setRightAndTitleMethod(String title,intrightsrcid, HeadView.OnRightClickListener onRightClickListener) {
mHeadView= (HeadView) findViewById(R.id.common_actionbar);
mHeadView.init(HeadView.HeaderStyle.RIGHTANDTITLE);
mHeadView.setRightAndTitleMethod(title, rightsrcid, onRightClickListener);
}
设置左侧内容和标题
public void setLeftWithTitleViewMethod(intleftsrcid, String title, HeadView.OnLeftClickListener onleftclicklistener) {
mHeadView= (HeadView) findViewById(R.id.common_actionbar);
mHeadView.init(HeadView.HeaderStyle.LEFTANDTITLE);
mHeadView.setLeftWithTitleViewMethod(leftsrcid, title, onleftclicklistener);
}
设置仅显示标题文字
public void setOnlyTileViewMethod(String title) {
mHeadView= (HeadView) findViewById(R.id.common_actionbar);
mHeadView.init(HeadView.HeaderStyle.ONLYTITLE);
mHeadView.setOnlyTileViewMethod(title);
}
设置仅显示左侧区域内容
public void setLeftViewMethod(intleftsrcid, HeadView.OnLeftClickListener onleftclicklistener) {
mHeadView= (HeadView) findViewById(R.id.common_actionbar);
mHeadView.init(HeadView.HeaderStyle.LEFT);
mHeadView.setLeftViewMethod(leftsrcid, onleftclicklistener);
}
How to use
需要通过include把我们的HeadView添加到布局文件中
在Activit中只需要调用BaseActivity中对外提供的设置方法就行