Android自定義HeadView實(shí)現(xiàn)導(dǎo)航欄效果

前言

在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

common_head
common_head

style樣式

style樣式


左側(cè)區(qū)域common_head_left_img.xml

common_head_left_img

右側(cè)區(qū)域common_head_right_img.xml

common_head_right_img

layout_actionbar.xml

layout_actionbar


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è)置方法就行

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末链峭,一起剝皮案震驚了整個(gè)濱河市畦娄,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌弊仪,老刑警劉巖熙卡,帶你破解...
    沈念sama閱讀 211,290評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異励饵,居然都是意外死亡驳癌,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門役听,熙熙樓的掌柜王于貴愁眉苦臉地迎上來颓鲜,“玉大人表窘,你說我怎么就攤上這事√鸨酰” “怎么了乐严?”我有些...
    開封第一講書人閱讀 156,872評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長衣摩。 經(jīng)常有香客問我麦备,道長,這世上最難降的妖魔是什么昭娩? 我笑而不...
    開封第一講書人閱讀 56,415評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮黍匾,結(jié)果婚禮上栏渺,老公的妹妹穿的比我還像新娘。我一直安慰自己锐涯,他們只是感情好磕诊,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評(píng)論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著纹腌,像睡著了一般霎终。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上升薯,一...
    開封第一講書人閱讀 49,784評(píng)論 1 290
  • 那天莱褒,我揣著相機(jī)與錄音,去河邊找鬼涎劈。 笑死广凸,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蛛枚。 我是一名探鬼主播谅海,決...
    沈念sama閱讀 38,927評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼蹦浦!你這毒婦竟也來了扭吁?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,691評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤盲镶,失蹤者是張志新(化名)和其女友劉穎侥袜,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體徒河,經(jīng)...
    沈念sama閱讀 44,137評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡系馆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評(píng)論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了顽照。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片由蘑。...
    茶點(diǎn)故事閱讀 38,622評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡闽寡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出尼酿,到底是詐尸還是另有隱情爷狈,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評(píng)論 4 329
  • 正文 年R本政府宣布裳擎,位于F島的核電站涎永,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏鹿响。R本人自食惡果不足惜羡微,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望惶我。 院中可真熱鬧妈倔,春花似錦、人聲如沸绸贡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽听怕。三九已至捧挺,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間尿瞭,已是汗流浹背闽烙。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留声搁,地道東北人鸣峭。 一個(gè)月前我還...
    沈念sama閱讀 46,316評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像酥艳,于是被迫代替她去往敵國和親摊溶。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容