Notification弹出实现
Notification的几种基本使用方法,大家肯定都已经烂熟于心,我也不必多说.给一个链接:https://zhuanlan.zhihu.com/p/25841482
接下来我想说的是android5.0 后的弹出通知,
网上的方法是:
//第一步:实例化通知栏构造器Notification.Builder:
Notification.Builder builder =new Notification.Builder(MainActivity.this);//实例化通知栏构造器Notification.Builder,参数必填(Context类型),为创建实例的上下文
//第二步:获取状态通知栏管理:
NotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);//获取状态栏通知的管理类(负责发通知、清除通知等操作)
//第三步:设置通知栏PendingIntent(点击动作事件等都包含在这里):
Intent push =new Intent(MainActivity.this,MainActivity.class);//新建一个显式意图,第一个参数 Context 的解释是用于获得 package name,以便找到第二个参数 Class 的位置
//PendingIntent可以看做是对Intent的包装,通过名称可以看出PendingIntent用于处理即将发生的意图,而Intent用来用来处理马上发生的意图
//本程序用来响应点击通知的打开应用,第二个参数非常重要,点击notification 进入到activity, 使用到pendingIntent类方法,PengdingIntent.getActivity()的第二个参数,即请求参数,实际上是通过该参数来区别不同的Intent的,如果id相同,就会覆盖掉之前的Intent了
PendingIntent contentIntent = PendingIntent.getActivity(MainActivity.this,0,push,0);
//第四步:对Builder进行配置:
builder
.setContentTitle("My notification")//标题
.setContentText("Hello World!")// 详细内容
.setContentIntent(contentIntent)//设置点击意图
.setTicker("New message")//第一次推送,角标旁边显示的内容
.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher))//设置大图标
.setDefaults(Notification.DEFAULT_ALL);//打开呼吸灯,声音,震动,触发系统默认行为
/*Notification.DEFAULT_VIBRATE //添加默认震动提醒 需要VIBRATE permission
Notification.DEFAULT_SOUND //添加默认声音提醒
Notification.DEFAULT_LIGHTS//添加默认三色灯提醒
Notification.DEFAULT_ALL//添加默认以上3种全部提醒*/
//.setLights(Color.YELLOW, 300, 0)//单独设置呼吸灯,一般三种颜色:红,绿,蓝,经测试,小米支持黄色
//.setSound(url)//单独设置声音
//.setVibrate(new long[] { 100, 250, 100, 250, 100, 250 })//单独设置震动
//比较手机sdk版本与Android 5.0 Lollipop的sdk
if(android.os.Build.VERSION.SDK_INT>= android.os.Build.VERSION_CODES.LOLLIPOP) {
builder
/*android5.0加入了一种新的模式Notification的显示等级,共有三种:
VISIBILITY_PUBLIC只有在没有锁屏时会显示通知
VISIBILITY_PRIVATE任何情况都会显示通知
VISIBILITY_SECRET在安全锁和没有锁屏的情况下显示通知*/
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setPriority(Notification.PRIORITY_DEFAULT)//设置该通知优先级
.setCategory(Notification.CATEGORY_MESSAGE)//设置通知类别
//.setColor(context.getResources().getColor(R.color.small_icon_bg_color))//设置smallIcon的背景色
.setFullScreenIntent(contentIntent, true)//将Notification变为悬挂式Notification
.setSmallIcon(R.drawable.ic_launcher);//设置小图标
}
else{
builder
.setSmallIcon(R.drawable.ic_launcher);//设置小图标
}
//第五步:发送通知请求:
Notification notify = builder.build();//得到一个Notification对象
mNotifyMgr.notify(1,notify);//发送通知请求
}
但上面的做法并不能在android5.0以下的设备上使通知弹出,因此下面的做法是自己重写Notification(网上查找的一些资料,来源忘记了,不好意思)
如果需要使通知自动显示,那么就需要我们在接收到通知后重新定义通知的界面,并使其加载显示在Window界面上,这点需要读者了解Window的加载机制.
其实简单点来说,就是通过windowManager的仅有的三个方法(加载,更新,删除)来实现的.如果有大神熟悉这方面的知识可以分享分享.
自定义Notification的思路:
1.继承重写NotificationCompat,Builder来实现类似的Notification
2.自定义通知界面
3.自定义NotificationManager,发送显示通知
废话不多说,先上主要代码:
public class HeadsUp { private Context context;
/**
* 出现时间 单位是 second
*/
private long duration= 3;
/**
*
*/
private Notification notification; private Builder builder; private boolean isSticky=false; private boolean activateStatusBar=true; private Notification silencerNotification;
/**
* 间隔时间
*/
private int code;
private CharSequence titleStr;
private CharSequence msgStr;
private int icon;
private View customView;
private boolean isExpand;
private HeadsUp(Context context) {
this.context=context;
}
public static class Builder extends NotificationCompat.Builder {
private HeadsUp headsUp;
public Builder(Context context) {
super(context);
headsUp=new HeadsUp(context);
}
public Builder setContentTitle(CharSequence title) {
headsUp.setTitle(title);
super.setContentTitle(title); //状态栏显示内容
return this;
}
public Builder setContentText(CharSequence text) {
headsUp.setMessage(text);
super.setContentText(text);
return this;
}
public Builder setSmallIcon(int icon) {
headsUp.setIcon(icon);
super.setSmallIcon(icon);
return this;
}
public HeadsUp buildHeadUp(){
headsUp.setNotification(this.build());
headsUp.setBuilder(this);
return headsUp;
}
public Builder setSticky(boolean isSticky){
headsUp.setSticky(isSticky);
return this;
}
} public Context getContext() {
return context;
} public long getDuration() {
return duration;
} public Notification getNotification() {
return notification;
} protected void setNotification(Notification notification) {
this.notification = notification;
} public View getCustomView() {
return customView;
} public void setCustomView(View customView) {
this.customView = customView;
} public int getCode() {
return code;
} protected void setCode(int code) {
this.code = code;
} protected Builder getBuilder() {
return builder;
} private void setBuilder(Builder builder) {
this.builder = builder;
} public boolean isSticky() {
return isSticky;
} public void setSticky(boolean isSticky) {
this.isSticky = isSticky;
} }
public class HeadsUpManager { private WindowManager wmOne;
private FloatView floatView;
private Queue<HeadsUp> msgQueue;
private static HeadsUpManager manager;
private Context context; private boolean isPolling = false; private Map<Integer, HeadsUp> map;
private NotificationManager notificationManager=null; public static HeadsUpManager getInstant(Context c) { if (manager == null) {
manager = new HeadsUpManager(c); }
return manager; } private HeadsUpManager(Context context) {
this.context = context;
map = new HashMap<Integer, HeadsUp>();
msgQueue = new LinkedList<HeadsUp>();
wmOne = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE); notificationManager= (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
} public void notify(HeadsUp headsUp) { if (map.containsKey(headsUp.getCode())) {
msgQueue.remove(map.get(headsUp.getCode()));
}
map.put(headsUp.getCode(), headsUp);
msgQueue.add(headsUp); if (!isPolling) {
poll();
}
}
public synchronized void notify(int code,HeadsUp headsUp) {
headsUp.setCode(code);
notify(headsUp); }
public synchronized void cancel(HeadsUp headsUp) {
cancel(headsUp.getCode());
} private synchronized void poll() {
if (!msgQueue.isEmpty()) {
HeadsUp headsUp = msgQueue.poll();
map.remove(headsUp.getCode()); // if ( Build.VERSION.SDK_INT < 21 || headsUp.getCustomView() != null ){
isPolling = true;
show(headsUp);
System.out.println("自定义notification");
// }else {
// //当 系统是 lollipop 以上,并且没有自定义布局以后,调用系统自己的 notification
// isPolling = false;
// notificationManager.notify(headsUp.getCode(),headsUp.getBuilder().setSmallIcon(headsUp.getIcon()).build());
// System.out.println("调用系统notification");
// } } else {
isPolling = false;
}
}
private void show(HeadsUp headsUp) {
floatView = new FloatView(context, 20);
WindowManager.LayoutParams params = FloatView.winParams;
params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|WindowManager.LayoutParams.FLAG_FULLSCREEN
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
params.width = WindowManager.LayoutParams.MATCH_PARENT;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.format = -3;
params.gravity = Gravity.CENTER | Gravity.TOP;
params.x = floatView.originalLeft;
params.y = 10;
params.alpha = 1f;
wmOne.addView(floatView, params);
ObjectAnimator a = ObjectAnimator.ofFloat(floatView.rootView, "translationY", -700, 0);
a.setDuration(600);
a.start();
floatView.setNotification(headsUp);
if(headsUp.getNotification()!=null){
notificationManager.notify(headsUp.getCode(), headsUp.getNotification());
}
} public void cancel(){ if(floatView !=null && floatView.getParent()!=null) { floatView.cancel();
}
} protected void dismiss() {
if (floatView.getParent()!=null) {
wmOne.removeView(floatView);
floatView.postDelayed(new Runnable() {
@Override
public void run() {
poll();
}
}, 200);
} } protected void animDismiss(){
if(floatView !=null && floatView.getParent()!=null){ ObjectAnimator a = ObjectAnimator.ofFloat(floatView.rootView, "translationY", 0, -700);
a.setDuration(700);
a.start(); a.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) { }
@Override
public void onAnimationEnd(Animator animator) { dismiss();
}
@Override
public void onAnimationCancel(Animator animator) {
}
@Override
public void onAnimationRepeat(Animator animator) { }
});
} } protected void animDismiss(HeadsUp headsUp){
if(floatView.getHeadsUp().getCode()==headsUp.getCode()){
animDismiss();
} }
public void cancel(int code) {
if (map.containsKey(code)) {
msgQueue.remove(map.get(code));
}
if(floatView!=null && floatView.getHeadsUp().getCode()==code){
animDismiss();
} }
public void close() {
cancelAll();
manager = null;
}
public void cancelAll() {
msgQueue.clear();
if (floatView!=null && floatView.getParent()!=null) {
animDismiss();
}
}
}
public class FloatView extends LinearLayout {
private float rawX = 0;
private float rawY=0;
private float touchX = 0;
private float startY = 0;
public LinearLayout rootView;
public int originalLeft;
public int viewWidth;
private float validWidth;
private VelocityTracker velocityTracker;
private int maxVelocity;
private Distance distance; private ScrollOrientationEnum scrollOrientationEnum=ScrollOrientationEnum.NONE; public static WindowManager.LayoutParams winParams = new WindowManager.LayoutParams(); public FloatView(final Context context, int i) {
super(context);
LinearLayout view = (LinearLayout) LayoutInflater.from(getContext()).inflate(R.layout.notification_bg, null);
maxVelocity= ViewConfiguration.get(context).getScaledMaximumFlingVelocity();
rootView = (LinearLayout) view.findViewById(R.id.rootView);
addView(view);
viewWidth = context.getResources().getDisplayMetrics().widthPixels;
validWidth=viewWidth/2.0f;
originalLeft = 0; } public void setCustomView(View view) {
rootView.addView(view);
} @Override
protected void onFinishInflate() {
super.onFinishInflate();
} private HeadsUp headsUp;
private long cutDown;
private Handler mHandle=null;
private CutDownTime cutDownTime;
private class CutDownTime extends Thread{ @Override
public void run() {
super.run(); while (cutDown>0){
try {
Thread.sleep(1000);
cutDown--;
} catch (InterruptedException e) {
e.printStackTrace();
}
} if(cutDown==0) {
mHandle.sendEmptyMessage(0);
} }
}; public HeadsUp getHeadsUp() {
return headsUp;
} private int pointerId;
public boolean onTouchEvent(MotionEvent event) {
rawX = event.getRawX();
rawY=event.getRawY();
acquireVelocityTracker(event);
cutDown= headsUp.getDuration();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touchX = event.getX();
startY = event.getRawY();
pointerId=event.getPointerId(0);
break;
case MotionEvent.ACTION_MOVE:
switch (scrollOrientationEnum){
case NONE:
if(Math.abs((rawX - touchX))>20) {
scrollOrientationEnum=ScrollOrientationEnum.HORIZONTAL; }else if(startY-rawY>20){
scrollOrientationEnum=ScrollOrientationEnum.VERTICAL; } break;
case HORIZONTAL:
updatePosition((int) (rawX - touchX));
break;
case VERTICAL:
if(startY-rawY>20) {
cancel();
}
break;
} break;
case MotionEvent.ACTION_UP:
velocityTracker.computeCurrentVelocity(1000,maxVelocity);
int dis= (int) velocityTracker.getYVelocity(pointerId);
if(scrollOrientationEnum==ScrollOrientationEnum.NONE){
if(headsUp.getNotification().contentIntent!=null){ try {
headsUp.getNotification().contentIntent.send();
cancel();
} catch (PendingIntent.CanceledException e) {
e.printStackTrace();
}
}
break;
} int toX;
if(preLeft>0){
toX= (int) (preLeft+Math.abs(dis));
}else{
toX= (int) (preLeft-Math.abs(dis));
}
if (toX <= -validWidth) {
float preAlpha=1-Math.abs(preLeft)/validWidth;
preAlpha=preAlpha>=0?preAlpha:0;
translationX(preLeft,-(validWidth+10),preAlpha,0);
} else if (toX <= validWidth) {
float preAlpha=1-Math.abs(preLeft)/validWidth;
preAlpha=preAlpha>=0?preAlpha:0;
translationX(preLeft,0,preAlpha,1); }else{
float preAlpha=1-Math.abs(preLeft)/validWidth;
preAlpha=preAlpha>=0?preAlpha:0;
translationX(preLeft, validWidth + 10, preAlpha, 0);
}
preLeft = 0;
scrollOrientationEnum=ScrollOrientationEnum.NONE;
break;
} return super.onTouchEvent(event); }
/**
*
* @param event 向VelocityTracker添加MotionEvent
*
* @see android.view.VelocityTracker#obtain()
* @see android.view.VelocityTracker#addMovement(MotionEvent)
*/
private void acquireVelocityTracker( MotionEvent event) {
if(null == velocityTracker) {
velocityTracker = VelocityTracker.obtain();
}
velocityTracker.addMovement(event);
}
private int preLeft; public void updatePosition(int left) { float preAlpha=1-Math.abs(preLeft)/validWidth;
float leftAlpha=1-Math.abs(left)/validWidth;
preAlpha = preAlpha>=0 ? preAlpha : 0;
leftAlpha = leftAlpha>=0 ? leftAlpha : 0;
translationX(preLeft,left,preAlpha,leftAlpha); preLeft = left;
} public void translationX(float fromX,float toX,float formAlpha, final float toAlpha ){
ObjectAnimator a1=ObjectAnimator.ofFloat(rootView,"alpha",formAlpha,toAlpha);
ObjectAnimator a2 = ObjectAnimator.ofFloat(rootView, "translationX", fromX, toX);
AnimatorSet animatorSet=new AnimatorSet();
animatorSet.playTogether(a1,a2);
animatorSet.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
} @Override
public void onAnimationEnd(Animator animation) {
if(toAlpha==0){
HeadsUpManager.getInstant(getContext()).dismiss(); cutDown=-1;
if(velocityTracker!=null) {
velocityTracker.clear();
try {
velocityTracker.recycle();
} catch (IllegalStateException e) { }
} }
} @Override
public void onAnimationCancel(Animator animation) {
} @Override
public void onAnimationRepeat(Animator animation) {
}
});
animatorSet.start();
} public void setNotification(final HeadsUp headsUp) { this.headsUp = headsUp; mHandle= new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
HeadsUpManager.getInstant(getContext()).animDismiss(headsUp);
}
}; cutDownTime= new CutDownTime(); if(!headsUp.isSticky()){
cutDownTime.start();
} cutDown= headsUp.getDuration(); if (headsUp.getCustomView() == null) { View defaultView = LayoutInflater.from(getContext()).inflate(R.layout.notification, rootView, false);
rootView.addView(defaultView);
ImageView imageView = (ImageView) defaultView.findViewById(R.id.iconIM);
TextView titleTV = (TextView) defaultView.findViewById(R.id.titleTV);
TextView timeTV = (TextView) defaultView.findViewById(R.id.timeTV);
TextView messageTV = (TextView) defaultView.findViewById(R.id.messageTV);
imageView.setImageResource(headsUp.getIcon());
titleTV.setText(headsUp.getTitleStr());
messageTV.setText(headsUp.getMsgStr());
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("HH:mm");
timeTV.setText( simpleDateFormat.format(new Date())); } else {
setCustomView(headsUp.getCustomView());
} } protected void cancel(){
HeadsUpManager.getInstant(getContext()).animDismiss();
cutDown = -1;
cutDownTime.interrupt(); if(velocityTracker!=null) {
try {
velocityTracker.clear();
velocityTracker.recycle();
} catch (IllegalStateException e) { }
}
} enum ScrollOrientationEnum {
VERTICAL,HORIZONTAL,NONE
}
}
具体用法:
PendingIntent pendingIntent=PendingIntent.getActivity(MainActivity.this,11,new Intent(MainActivity.this,MainActivity.class),PendingIntent.FLAG_UPDATE_CURRENT); View view=getLayoutInflater().inflate(R.layout.custom_notification, null); view.findViewById(R.id.openSource).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) { }
}); HeadsUpManager manage = HeadsUpManager.getInstant(getApplication());
HeadsUp.Builder builder = new HeadsUp.Builder(MainActivity.this);
builder.setContentTitle("提醒")
//要显示通知栏通知,这个一定要设置
.setSmallIcon(R.drawable.icon)
.setContentText("你有新的消息")
//2.3 一定要设置这个参数,负责会报错
.setContentIntent(pendingIntent)
//.setFullScreenIntent(pendingIntent, false) HeadsUp headsUp = builder.buildHeadUp();
headsUp.setCustomView(view);
manage.notify(1, headsUp); }
目前先这样吧,以后继续更新。。。
Notification弹出实现的更多相关文章
- Notification 弹出一个通知在桌面右下角
if (!("Notification" in window)) { //alert("This browser does not support desktop not ...
- 【wpf】在win10系统上弹出toast和notification
原文:[wpf]在win10系统上弹出toast和notification 老规矩,先看效果 右下角的notification: 操作中心的notification: 整体效果: 前提条件 1.需要在 ...
- iOS 自定义键盘ToolBar(与键盘的弹出、收起保持一致)
1.监听键盘改变的通知 [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyBoardWillCha ...
- iOS8无法弹出本地通知?
最近在看<iOS编程(第4版)>(就是Big Nerd Ranch用的那本教材).这本书写的不错,推荐一下,写的很细致,循序渐进,不能不赞一下外国人写书的思路,确实跟国人不同.之前学And ...
- 用Masonry实现键盘的收回和弹出
首先说几点:我一般将数值类型的约束用mas_equalTo,而相对于某个控件,或者某个控件的某个约束,我会使用equalTo,如:make.size.mas_equalTo(CGSizeMake(10 ...
- IOS开发之自定义系统弹出键盘上方的view(转载)
这篇文章解决的一个开发中的实际问题就是:当弹出键盘时,自定义键盘上方的view.目前就我的经验来看,有两种解决方法.一个就是利用UITextField或者UITextView的inputAccesso ...
- Android EditText 不弹出输入法
当第一次进入一个activity的时候 一般是第一个edittext是默认选中的,但是该死的软键盘也一起弹出来了 那是相当的不美观哈!(#‵′)凸.为此, 本大人就去寻找在刚进入这个activity ...
- [Prism框架实用分享]如何在主程序中合理的弹出子窗体
大家好 说起子窗体,大家都会想到ChildWindow,多熟悉的一个控件.不错,Sliverlight中已经提供了子窗体的具体实现,而在WPF中却没有这么好的事情(有的第三方控件商已经提供此控件).最 ...
- VS2010/MFC:模态对话框及其弹出过程
模态对话框及其弹出过程 加法计算器对话框程序大家照着做一遍后,相信对基于对话框的程序有些了解了,有个好的开始对于以后的学习大有裨益.趁热打铁,这一节讲讲什么是模态对话框和非模态对话框,以及模态对话框怎 ...
随机推荐
- 51nod_1120:机器人走方格 V3
题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1120 Catalan数 基础题,ans=C(2n-2,n-2 ...
- Spring源码情操陶冶-ContextLoaderListener
前言:通过实例结合源码的方式解读,其中涉及到的文件来自于博主的Github毕设项目wxServer Note: Springboot应用不在本文章讨论范围 web.xml中启用Spring 在一般的w ...
- Vivado完成综合_实现_生成比特流后发出提醒声音-原创☺
之前做技术支持时,有过客户吐槽Vivado运行时间长,又不能在完成工作后发送提醒,这两天又有人提起,所以决定写篇帖子. 大家知道,Vivado的技术文档总提及tcl,不过似乎很不招人待见,很少有人研究 ...
- 16. leetcode 404. Sum of Left Leaves
Find the sum of all left leaves in a given binary tree. Example: 3 / \ 9 20 / \ 15 ...
- HDU 2202 最大三角形(凸包)
Problem Description 老师在计算几何这门课上给Eddy布置了一道题目,题目是这样的:给定二维的平面上n个不同的点,要求在这些点里寻找三个点,使他们构成的三角形拥有的面积最大.Eddy ...
- Uva140 Bandwidth 全排列+生成测试法+剪枝
参考过仰望高端玩家的小清新的代码... 思路:1.按字典序对输入的字符串抽取字符,id[字母]=编号,id[编号]=字母,形成双射 2.邻接表用两个vector存储,存储相邻关系 ...
- Tornado session 插件 pycket 定制时间和时间续租
功能描述:10分钟用户没有任何操作,跳转到登录页面. 分析:这个功能用session就能实现(由于pycket 的session内容是存储在memcached或者redis里面的.所以,session ...
- Django 1.9 admin 使用suit 小记
最近项目做到了后台管理的部分.Django虽然提供了后台管理,但是界面不咋好看.所以我使用了suit.官网http://djangosuit.com/ 步骤: 1,安装suit 项目settings. ...
- 【机器学习笔记之二】决策树的python实现
本文结构: 是什么? 有什么算法? 数学原理? 编码实现算法? 1. 是什么? 简单地理解,就是根据一些 feature 进行分类,每个节点提一个问题,通过判断,将数据分为几类,再继续提问.这些问题是 ...
- MySQL编程基础
本文是关于MySQL编程中的一些基础知识,包括变量和运算符.常用语句.函数. 一.变量与运算符 1.用户会话变量声明:SET @变量名 = 表达式;//即:用户会话变量无需提前定义,直接用赋值语句赋值 ...