前言
在Android應(yīng)用的開發(fā)中少不了導(dǎo)航欄的使用,Android 3.0? 推了 ActionBar, 5.0開始推出的一個(gè) Material Design 風(fēng)格的導(dǎo)航控件Toolbar,這些控件也是在致力于幫助我們?cè)贏pp中打造一個(gè)統(tǒng)一的導(dǎo)航欄規(guī)范,在App上顯得更加整體化输涕。Toolbar相比ActionBar更加靈活,可以放到布局中的任何位置,不局限于頂部寄雀,開放了很多API,留給了開發(fā)者更多的擴(kuò)展余地,相信很多開發(fā)者更樂于使用Toolbar,但是在這里我不打算遵循傳統(tǒng)陨献。
在項(xiàng)目開發(fā)中谷歌提供的這些控件可能無法滿足我們項(xiàng)目需求盒犹,這個(gè)時(shí)候就需要通過自定義來實(shí)現(xiàn),當(dāng)然,這里我們就自定義一個(gè)HeadView,同樣可以實(shí)現(xiàn)靈活急膀,可擴(kuò)展性強(qiáng)的導(dǎo)航欄沮协。
通過自定義控件不僅僅是實(shí)現(xiàn)了導(dǎo)航欄的功能,更重要的是我們對(duì)自定義流程的明晰和實(shí)踐的總結(jié)卓嫂。
先上效果圖:
分析
導(dǎo)航欄一般分為三個(gè)內(nèi)容區(qū)域:左側(cè)區(qū)域慷暂,中間標(biāo)題欄,右側(cè)區(qū)域晨雳,左側(cè)和右側(cè)通常是一個(gè)按鈕或者ImageView,中間標(biāo)題為TextView.因此我們可以把它分為三部分來實(shí)現(xiàn)行瑞,整體的父布局采用RelativeLayout,里面的三個(gè)區(qū)域采用LinearLayout餐禁,對(duì)外提供設(shè)置方法傳遞資源文件和監(jiān)聽接口回調(diào)血久。
實(shí)現(xiàn)
整體父布局common_head.xml
style樣式
左側(cè)區(qū)域common_head_left_img.xml
右側(cè)區(qū)域common_head_right_img.xml
layout_actionbar.xml
HeadView的實(shí)現(xiàn)
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;
一個(gè)參數(shù)的構(gòu)造方法
public HeadView(Context context) {
this(context,null);
}
兩個(gè)參數(shù)的構(gòu)造方法
public HeadView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
三個(gè)構(gòu)造參數(shù)的方法里面進(jìn)行初始化操作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();
}
枚舉類型用于標(biāo)示顯示的模式
/**
*
*@authorMersens
*枚舉類型的標(biāo)題欄顯示類型DEFAULT--默認(rèn)顯示左側(cè)圖標(biāo),右側(cè)圖標(biāo)和標(biāo)題ONLYTITLE--只顯示標(biāo)題
*? LEFT--只顯示左側(cè)圖標(biāo)LEFTANDTITLE--只顯示左側(cè)圖標(biāo)和標(biāo)題
*/
public enum HeaderStyle {
DEFAULT,ONLYTITLE,LEFT,LEFTANDTITLE,RIGHTANDTITLE;
}
對(duì)外提供init初始化方法帮非,改方法傳遞一個(gè)枚舉氧吐,用于初始化時(shí)候的模式
/**
*@authorMersens
根據(jù)類型進(jìn)行初始化,可以通過addView()方法動(dòng)態(tài)添加控件,然后設(shè)置其控件的顯示
*@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;
}}
初始化右側(cè)布局和title
private void rightandtitle() {
//設(shè)置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);
//初始化右側(cè)按鈕,并添加到右側(cè)父布局內(nèi)
header_layout_rightview_container.addView(right_button_view);
right_button.setOnClickListener(newOnClickListener() {
@Override
public voidonClick(View v) {
//接口回調(diào)
if(onrightclicklistener!=null) {
onrightclicklistener.onClick();
}}});}
移除父布局內(nèi)部的所有子控件
/**
*移除左右控件的子View
*/
private void removeViews() {
header_leftview_container.removeAllViews();
header_layout_rightview_container.removeAllViews();
}
初始化設(shè)置默認(rèn)的模式喜鼓,左側(cè)副砍,右側(cè)和中間的標(biāo)題都會(huì)顯示
@SuppressLint("InflateParams")
public void defaultMethod() {
//設(shè)置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);
//初始化左側(cè)按鈕,并添加到左側(cè)父布局內(nèi)
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);
//初始化右側(cè)按鈕庄岖,并添加到右側(cè)父布局內(nèi)
header_layout_rightview_container.addView(right_button_view);
left_button.setOnClickListener(newOnClickListener() {
@Override
public voidonClick(View v) {
//接口回調(diào)
if(onleftclicklistener!=null) {
onleftclicklistener.onClick();
}}});
right_button.setOnClickListener(newOnClickListener() {
@Override
public voidonClick(View v) {
//接口回調(diào)
if(onrightclicklistener!=null) {
onrightclicklistener.onClick();
}}});}
初始化只顯示中間標(biāo)題
public void tileMethod() {
tv_title.setVisibility(View.VISIBLE);
}
初始化左側(cè)按鈕布局
public void leftMethod() {
//初始化左側(cè)按鈕豁翎,并添加到左側(cè)父布局內(nèi)
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);
//添加監(jiān)聽事件
left_button.setOnClickListener(newOnClickListener() {
@Override
public voidonClick(View v) {
if(onleftclicklistener!=null) {
onleftclicklistener.onClick();
}}});}
對(duì)外提供設(shè)置左側(cè)和中間標(biāo)題的方法
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();
}}});}
對(duì)外提供設(shè)置默認(rèn)的顯示模式,需要傳遞資源文件
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);
}
設(shè)置右側(cè)和中間標(biāo)題的方法
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);
}
設(shè)置顯示左側(cè)和中間內(nèi)容方法
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);
}
設(shè)置只顯示中間標(biāo)題的方法
public void setOnlyTileViewMethod(String title) {
if(!TextUtils.isEmpty(title)) {
tv_title.setText(title);
}}
設(shè)置只有右側(cè)區(qū)域內(nèi)容的方法
public void setLeftViewMethod(intleftsrcid,
OnLeftClickListener onleftclicklistener) {
if(leftsrcid !=0)
left_button.setBackgroundResource(leftsrcid);
else
left_button.setBackgroundResource(R.mipmap.ic_menu_back);
setOnLeftClickListener(onleftclicklistener);
}
左側(cè)區(qū)域的點(diǎn)擊回調(diào)接口
/**
*@author Mersens
*自定義接口回調(diào)隅忿,用于處理左側(cè)按鈕的點(diǎn)擊事件
*/
public interfaceOnLeftClickListener {
voidonClick();
}
提供左側(cè)區(qū)域set設(shè)置方法
public void setOnLeftClickListener(OnLeftClickListener onleftclicklistener) {
this.onleftclicklistener= onleftclicklistener;
}
右側(cè)區(qū)域的點(diǎn)擊回調(diào)接口
/**
*@author Mersens
*自定義接口回調(diào)心剥,用于處理右側(cè)側(cè)按鈕的點(diǎn)擊事件
*/
public interface OnRightClickListener {
voidonClick();
}
提供右側(cè)區(qū)域set設(shè)置方法
public void setOnRightClickListener(
OnRightClickListener onrightclicklistener) {
this.onrightclicklistener= onrightclicklistener;
}
我們?cè)陂_發(fā)中通常會(huì)封裝一些東西在BaseActivity中,當(dāng)然背桐,這里我們也采用封裝的方式优烧,我們寫一個(gè)BaseActivity,讓他繼承AppCompatActivity,然后再內(nèi)部提供設(shè)置的方法就可以:
設(shè)置默認(rèn)方式
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);
}
設(shè)置右側(cè)內(nèi)容和標(biāo)題
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);
}
設(shè)置左側(cè)內(nèi)容和標(biāo)題
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);
}
設(shè)置僅顯示標(biāo)題文字
public void setOnlyTileViewMethod(String title) {
mHeadView= (HeadView) findViewById(R.id.common_actionbar);
mHeadView.init(HeadView.HeaderStyle.ONLYTITLE);
mHeadView.setOnlyTileViewMethod(title);
}
設(shè)置僅顯示左側(cè)區(qū)域內(nèi)容
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中只需要調(diào)用BaseActivity中對(duì)外提供的設(shè)置方法就行