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

這大概就是我學習自定通知的一個記錄。僅僅是爲了作爲學習記錄來寫下這篇博客。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章