Android自定義HeadView實現導航欄效果

前言

在Android應用的開發中少不了導航欄的使用,Android 3.0? 推了 ActionBar, 5.0開始推出的一個 Material Design 風格的導航控件Toolbar,這些控件也是在致力于幫助我們在App中打造一個統一的導航欄規范,在App上顯得更加整體化。Toolbar相比ActionBar更加靈活,可以放到布局中的任何位置,不局限于頂部,開放了很多API,留給了開發者更多的擴展余地,相信很多開發者更樂于使用Toolbar,但是在這里我不打算遵循傳統。

在項目開發中谷歌提供的這些控件可能無法滿足我們項目需求,這個時候就需要通過自定義來實現,當然,這里我們就自定義一個HeadView,同樣可以實現靈活,可擴展性強的導航欄。

通過自定義控件不僅僅是實現了導航欄的功能,更重要的是我們對自定義流程的明晰和實踐的總結。

先上效果圖:


效果圖

分析

導航欄一般分為三個內容區域:左側區域,中間標題欄,右側區域,左側和右側通常是一個按鈕或者ImageView,中間標題為TextView.因此我們可以把它分為三部分來實現,整體的父布局采用RelativeLayout,里面的三個區域采用LinearLayout,對外提供設置方法傳遞資源文件和監聽接口回調。

實現

整體父布局common_head.xml

common_head
common_head

style樣式

style樣式


左側區域common_head_left_img.xml

common_head_left_img

右側區域common_head_right_img.xml

common_head_right_img

layout_actionbar.xml

layout_actionbar


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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容