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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容