前言
在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中對外提供的設置方法就行