這篇文章主要是記錄一個自定義Notification樣式的學習過程。界面比較簡單,也沒有格外去用心的搭建,只是爲了實現自定義效果。
先來看看效果圖,通過Activity中的button點擊彈出通知。
現在我們先來看看佈局界面,第一個界面主要就是一個button所以就不拿出來了,看看我們自定義的通知界面。
notification_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent"
tools:context="com.example.administrator.learnnotification.MainActivity">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:src="@mipmap/ic_launcher"
android:layout_width="wrap_content"
android:layout_height="80dp" />
<TextView
android:id="@+id/text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
></TextView>
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/btn_1"
android:layout_toLeftOf="@+id/btn_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button1"/>
<Button
android:layout_alignParentRight="true"
android:id="@+id/btn_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button2"/>
</RelativeLayout>
</LinearLayout>
這個界面也是很單純的搭建了一個如圖通知所示的界面。然後讓我們看看如何加載並且給這個界面按鈕設置監聽。
在這裏先說一下,因爲系統的默認主題顏色我們不確定,所以沒辦法在設置文本字體顏色的時候把參數定死,所以我們需要去判斷系統的默認主題顏色,然後來設置通知字體顏色。
NotificationUtils.java
public class NotificationUtils {
public static boolean isDarkNotificationTheme(Context context) {
return !isSimilarColor(Color.BLACK, getNotificationColor(context));
}
/**
* 獲取通知欄顏色
* @param context
* @return
*/
public static int getNotificationColor(Context context) {
NotificationCompat.Builder builder=new NotificationCompat.Builder(context);
Notification notification=builder.build();
int layoutId=notification.contentView.getLayoutId();
ViewGroup viewGroup= (ViewGroup) LayoutInflater.from(context).inflate(layoutId, null, false);
if (viewGroup.findViewById(android.R.id.title)!=null) {
return ((TextView) viewGroup.findViewById(android.R.id.title)).getCurrentTextColor();
}
return findColor(viewGroup);
}
private static boolean isSimilarColor(int baseColor, int color) {
int simpleBaseColor=baseColor|0xff000000;
int simpleColor=color|0xff000000;
int baseRed=Color.red(simpleBaseColor)-Color.red(simpleColor);
int baseGreen=Color.green(simpleBaseColor)-Color.green(simpleColor);
int baseBlue=Color.blue(simpleBaseColor)-Color.blue(simpleColor);
double value=Math.sqrt(baseRed*baseRed+baseGreen*baseGreen+baseBlue*baseBlue);
if (value<180.0) {
return true;
}
return false;
}
private static int findColor(ViewGroup viewGroupSource) {
int color=Color.TRANSPARENT;
LinkedList<ViewGroup> viewGroups=new LinkedList<>();
viewGroups.add(viewGroupSource);
while (viewGroups.size()>0) {
ViewGroup viewGroup1=viewGroups.getFirst();
for (int i = 0; i < viewGroup1.getChildCount(); i++) {
if (viewGroup1.getChildAt(i) instanceof ViewGroup) {
viewGroups.add((ViewGroup) viewGroup1.getChildAt(i));
}
else if (viewGroup1.getChildAt(i) instanceof TextView) {
if (((TextView) viewGroup1.getChildAt(i)).getCurrentTextColor()!=-1) {
color=((TextView) viewGroup1.getChildAt(i)).getCurrentTextColor();
}
}
}
viewGroups.remove(viewGroup1);
}
return color;
}
}
在這個類中,我們獲取到系統默認通知的顏色。由和這個顏色來設定我們通知中文本字體顏色。
然後呢,我們系統定義的通知高度可能有限,如果你的通知高度太大,可能導致顯示不完全。這裏我們使用
/*
* 判斷SDK後使用bigContentView讓通知顯示高度變大
* */
Notification notification = new Notification();
if(android.os.Build.VERSION.SDK_INT >= 16) {
notification = builder.build();
notification.bigContentView = remoteViews;
}
notification.contentView = remoteViews;
判斷SDK後使用bigContentView就可以在Sdk>=16的設備上解決這個問題。
MainActivity.java
public class MainActivity extends AppCompatActivity {
private static final String NOTIFICATION_BUTTON1_CLICK= "notification_button1_click";
private static final String NOTIFICATION_BUTTON2_CLICK= "notification_button2_click";
private ButtonRecvier recvier;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recvier = new ButtonRecvier();
findViewById(R.id.sure).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
sendNotification();
}
});
}
/*
* 在Oresume中註冊廣播
* */
@Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter();
filter.addAction(NOTIFICATION_BUTTON1_CLICK);
filter.addAction(NOTIFICATION_BUTTON2_CLICK);
registerReceiver(recvier, filter);
}
@Override
protected void onPause() {
super.onPause();
if(recvier!=null){
unregisterReceiver(recvier);
}
}
/*
* 發送一個通知
* */
public void sendNotification(){
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
android.support.v4.app.NotificationCompat.Builder builder = new NotificationCompat.Builder(this).setSmallIcon(R.mipmap.ic_launcher);
RemoteViews remoteViews = new RemoteViews(getPackageName(),R.layout.notification_layout);
Intent intent = new Intent(this,ButtonRecvier.class);
intent.setAction(NOTIFICATION_BUTTON1_CLICK);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this,0,intent,0);
remoteViews.setOnClickPendingIntent(R.id.btn_1,pendingIntent);
intent.setAction(NOTIFICATION_BUTTON2_CLICK);
pendingIntent = PendingIntent.getBroadcast(this,0,intent,0);
remoteViews.setOnClickPendingIntent(R.id.btn_2,pendingIntent);
remoteViews.setTextViewText(R.id.text_view,"啦啦啦德瑪西亞");
/*
* 獲取到系統默認通知顏色,並設置通知字體顏色
* */
remoteViews.setInt(R.id.text_view,"setTextColor",NotificationUtils.isDarkNotificationTheme(MainActivity.this)==true?Color.WHITE:Color.BLACK);
/*
* 判斷SDK後使用bigContentView讓通知顯示高度變大
* */
Notification notification = new Notification();
if(android.os.Build.VERSION.SDK_INT >= 16) {
notification = builder.build();
notification.bigContentView = remoteViews;
}
notification.contentView = remoteViews;
manager.notify(1,notification);
}
}
ButtonRecevier.java
public class ButtonRecvier extends BroadcastReceiver {
private static final String NOTIFICATION_BUTTON1_CLICK= "notification_button1_click";
private static final String NOTIFICATION_BUTTON2_CLICK= "notification_button2_click";
@Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(NOTIFICATION_BUTTON1_CLICK)&&intent!=null){
Toast.makeText(context, "you click btn1", Toast.LENGTH_SHORT).show();
}else if(intent.getAction().equals(NOTIFICATION_BUTTON2_CLICK)&&intent!=null){
Toast.makeText(context, "you click btn2", Toast.LENGTH_SHORT).show();
}
}
}
這裏可以看到我們建立了一個名爲ButtonRecevier的類,用來接收廣播。而我們在MainActivity的Onresume中去註冊廣播,並且添加兩個Action,這個主要是爲了設置通知中按鍵的監聽、
在廣播接收器中 我們加添了
if(intent.getAction().equals(NOTIFICATION_BUTTON1_CLICK)&&intent!=null){
Toast.makeText(context, "you click btn1", Toast.LENGTH_SHORT).show();
}else if(intent.getAction().equals(NOTIFICATION_BUTTON2_CLICK)&&intent!=null){
Toast.makeText(context, "you click btn2", Toast.LENGTH_SHORT).show();
}
來判斷不同的Action對應的是哪一個按鈕觸發的廣播。
在MainActivity的sendNotification方法中。
RemoteViews remoteViews = new RemoteViews(getPackageName(),R.layout.notification_layout);
notification.contentView = remoteViews;
這樣先生成一個remoteViews對象,然後給Notification設置contentView就可以達到自定義界面的目的。
然後監聽器和文本內容的設置:
RemoteViews remoteViews = new RemoteViews(getPackageName(),R.layout.notification_layout);
Intent intent = new Intent(this,ButtonRecvier.class);
intent.setAction(NOTIFICATION_BUTTON1_CLICK);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this,0,intent,0);
remoteViews.setOnClickPendingIntent(R.id.btn_1,pendingIntent);
intent.setAction(NOTIFICATION_BUTTON2_CLICK);
pendingIntent = PendingIntent.getBroadcast(this,0,intent,0);
remoteViews.setOnClickPendingIntent(R.id.btn_2,pendingIntent);
remoteViews.setTextViewText(R.id.text_view,"啦啦啦德瑪西亞");
remoteViews.setInt(R.id.text_view,"setTextColor",NotificationUtils.isDarkNotificationTheme(MainActivity.this)==true?Color.WHITE:Color.BLACK);
可以看到當我們實例化一個remoteviews的對象後,我們通過對他設置的方法來實現內部控件的設置,在設置監聽的時候需要傳入一個PendingIntent
這裏的PendingIntent我們就可啓動剛纔的廣播,然後設置Action來達到按鈕監聽的目的
Intent intent = new Intent(this,ButtonRecvier.class);
intent.setAction(NOTIFICATION_BUTTON1_CLICK);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this,0,intent,0);
remoteViews.setOnClickPendingIntent(R.id.btn_1,pendingIntent);
這樣基本就能實現自定義通知並設置監聽的目的,當然除了PendingIntent.getBroadcast(this,0,intent,0);
還有.getService和getActivity等方法使用。意圖跳轉。
這大概就是我學習自定通知的一個記錄。僅僅是爲了作爲學習記錄來寫下這篇博客。