1. 程式人生 > >Android 自定義Notification通知樣式並設定按鈕監聽.

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等方法使用。意圖跳轉。

這大概就是我學習自定通知的一個記錄。僅僅是為了作為學習記錄來寫下這篇部落格。