这篇文章主要是记录一个自定义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等方法使用。意图跳转。
这大概就是我学习自定通知的一个记录。仅仅是为了作为学习记录来写下这篇博客。