概述
寫(xiě)這篇文章的起因是當(dāng)我自定義通知欄樣式時(shí)色冀,設(shè)置的view高度最終只能顯示為通知欄的默認(rèn)高度(64dp)潭袱,讓人十分困惑,于是研究了下源碼呐伞。
除了解開(kāi)真相意外敌卓,還了解到了包括bigview,pengdingintent的點(diǎn)擊事件伶氢,通知欄限制等知識(shí)點(diǎn),收獲頗多瘪吏,在這里分享給大家癣防。希望能讓大家明白一個(gè)通知是如何添加到狀態(tài)欄上面去的,如果遇到奇怪的問(wèn)題不至于抓瞎掌眠。
前提
本文是以android5.0的源碼為基礎(chǔ)的并且假設(shè)大家都知道notification的基本用法蕾盯。
構(gòu)造通知
在我們使用NotificationCompat.Builder
對(duì)象設(shè)置完各種參數(shù)(小/大圖標(biāo),標(biāo)題蓝丙,內(nèi)容等)后级遭,最后會(huì)調(diào)用build
方法來(lái)得到一個(gè)Notification望拖,然后使用NotificationManager
來(lái)發(fā)出通知。我們就先來(lái)看看build方法做了什么事挫鸽。
NotificationCompat是v4包中的一個(gè)類(lèi)说敏,做了android各個(gè)版本的兼容,但是不論是哪個(gè)版本丢郊,最后build方法都是調(diào)用的Notification
的build方法盔沫,所以我們直接看Notification的build方法。
frameworks/base/core/java/android/app/Notification.java
/**
* Combine all of the options that have been set and return a new {@link Notification}
* object.
*/
public Notification build() {
...
//設(shè)置通知的默認(rèn)信息
Notification n = buildUnstyled();
//設(shè)置通知的樣式信息
if (mStyle != null) {
n = mStyle.buildStyled(n);
}
...
return n;
}
方法的注釋說(shuō)得很清楚了枫匾,就是將所有的設(shè)置選項(xiàng)聯(lián)合在一起返回一個(gè)新的通知架诞。
buildUnstyled
其中buildUnstyled()所說(shuō)的默認(rèn)信息就是在android4.0以前還不能展開(kāi)的時(shí)候所包括的所有信息,包括大/小圖標(biāo)干茉,時(shí)間谴忧,標(biāo)題,內(nèi)容角虫,自定義view等信息沾谓。
/**
* Apply the unstyled operations and return a new {@link Notification} object.
* @hide
*/
public Notification buildUnstyled() {
Notification n = new Notification();
n.when = mWhen;
n.icon = mSmallIcon;
...
setBuilderContentView(n, makeContentView());
n.contentIntent = mContentIntent;
...
setBuilderBigContentView(n, makeBigContentView());
setBuilderHeadsUpContentView(n, makeHeadsUpContentView());
// Note: If you're adding new fields, also update restoreFromNotitification().
return n;
}
setBuilderContentView用于設(shè)置通知欄的ContentView屬性
private void setBuilderContentView(Notification n, RemoteViews contentView) {
n.contentView = contentView;
...
}
makeContentView()是構(gòu)造出所需要填充的view
private RemoteViews makeContentView() {
if (mContentView != null) {
return mContentView;
} else {
return applyStandardTemplate(getBaseLayoutResource());
}
}
如果你沒(méi)有使用自定view,將會(huì)使用標(biāo)準(zhǔn)的模板樣式
private int getBaseLayoutResource() {
return R.layout.notification_template_material_base;
}
這里只講了setBuilderContentView(n, makeContentView());
方法上遥, 后面的setBuilderBigContentView(n, makeBigContentView());
和setBuilderHeadsUpContentView(n, makeHeadsUpContentView());
方法與其類(lèi)似都是設(shè)置通知的相應(yīng)屬性搏屑,直接給出結(jié)果,不再累述
<pre>
setBuilderHeadsUpContentView --> n.headsUpContentView
setBuilderBigContentView --> n.bigContentView = bigContentView;
</pre>
這樣粉楚,通知的顯示內(nèi)容就已經(jīng)構(gòu)造好了辣恋。
1 .可以看出,在構(gòu)造階段模软,并沒(méi)有對(duì)通知欄的自定義view高度做出限制伟骨,但最后顯示的時(shí)候卻是一個(gè)固定高度,why?
2.先記住這里的bigContentView屬性燃异,后面會(huì)在提到携狭。
buildStyled
4.0后如果設(shè)置了BigText,BigPic等樣式回俐,則會(huì)調(diào)用buildStyled方法逛腿。buildStyled是Notification.Style中的一個(gè)方法
public Notification buildStyled(Notification wip) {
...
populateBigContentView(wip);
...
return wip;
}
populateBigContentView是一個(gè)protected所修飾的方法,具體的實(shí)現(xiàn)是在所設(shè)置的Style中仅颇,這里里BigPic Style為例单默,在BigPictureStyle
類(lèi)中,重寫(xiě)了該方法
@Override
public void populateBigContentView(Notification wip) {
mBuilder.setBuilderBigContentView(wip, makeBigContentView());
}
private RemoteViews makeBigContentView() {
RemoteViews contentView = getStandardView(mBuilder.getBigPictureLayoutResource());
contentView.setImageViewBitmap(R.id.big_picture, mPicture);
...
return contentView;
}
private int getBigPictureLayoutResource() {
return R.layout.notification_template_material_big_picture;
}
如果是BigPic Style樣式的通知忘瓦,其實(shí)也是調(diào)用了系統(tǒng)中設(shè)置的一個(gè)模板布局notification_template_material_big_picture.
這里又調(diào)用了一次mBuilder.setBuilderBigContentView
搁廓,前面提到了該方法是給notification的bigContentView的屬性賦值。所以如果設(shè)置了樣式,則會(huì)覆蓋默認(rèn)的bigContentView值
總結(jié)
在通知構(gòu)造環(huán)節(jié)境蜕,我們需要記住做了最重要的2件事
- 給Notification的contentView屬性賦值蝙场,該值可以是自定義的view也可以是系統(tǒng)默認(rèn)樣式的view
- 給Notification的bigContentView屬性賦值,該值可以使自定義的view也可以是系統(tǒng)默認(rèn)樣式的view
相關(guān)閱讀
Notification之---NotificationListenerService5.0實(shí)現(xiàn)原理
Notification之----Android5.0實(shí)現(xiàn)原理(二)
Notification之----自定義樣式
Notification之----默認(rèn)樣式
Notification之----任務(wù)棧