Android 自定義Notification通知樣式並設定按鈕監聽.
這篇文章主要是記錄一個自定義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等方法使用。意圖跳轉。
這大概就是我學習自定通知的一個記錄。僅僅是為了作為學習記錄來寫下這篇部落格。