Notification彈出實現

来源:http://www.cnblogs.com/zh-yale/archive/2017/08/28/7441244.html
-Advertisement-
Play Games

Notification的幾種基本使用方法,大家肯定都已經爛熟於心,我也不必多說.給一個鏈接:https://zhuanlan.zhihu.com/p/25841482 接下來我想說的是android5.0 後的彈出通知, 網上的方法是: 但上面的做法並不能在android5.0以下的設備上使通知彈 ...


  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,發送顯示通知

廢話不多說,先上主要代碼:

  1 public class HeadsUp   {
  2 
  3     private Context context;
  4     /**
  5      * 出現時間  單位是 second
  6      */
  7     private long duration= 3;
  8     /**
  9      *
 10      */
 11     private Notification notification;
 12 
 13     private Builder builder;
 14 
 15     private boolean isSticky=false;
 16 
 17 
 18     private boolean activateStatusBar=true;
 19 
 20     private Notification silencerNotification;
 21     /**
 22      * 間隔時間
 23      */
 24     private int code;
 25     private CharSequence titleStr;
 26     private CharSequence msgStr;
 27     private int icon;
 28     private View customView;
 29     private boolean isExpand;
 30     private HeadsUp(Context context) {
 31         this.context=context;
 32     }
 33     public static class Builder  extends  NotificationCompat.Builder {
 34         private HeadsUp headsUp;
 35         public Builder(Context context) {
 36             super(context);
 37             headsUp=new HeadsUp(context);
 38         }
 39         public Builder setContentTitle(CharSequence title) {
 40             headsUp.setTitle(title);
 41             super.setContentTitle(title);        //狀態欄顯示內容
 42             return this;
 43         }
 44         public Builder setContentText(CharSequence text) {
 45             headsUp.setMessage(text);
 46             super.setContentText(text);
 47             return this;
 48         }
 49         public Builder setSmallIcon(int icon) {
 50             headsUp.setIcon(icon);
 51             super.setSmallIcon(icon);
 52             return this;
 53         }
 54         public HeadsUp buildHeadUp(){
 55             headsUp.setNotification(this.build());
 56             headsUp.setBuilder(this);
 57             return  headsUp;
 58         }
 59         public Builder setSticky(boolean isSticky){
 60             headsUp.setSticky(isSticky);
 61             return this;
 62         }
 63     }
 64 
 65     public Context getContext() {
 66         return context;
 67     }
 68 
 69     public long getDuration() {
 70         return duration;
 71     }
 72 
 73     public Notification getNotification() {
 74         return notification;
 75     }
 76 
 77     protected void setNotification(Notification notification) {
 78         this.notification = notification;
 79     }
 80 
 81     public View getCustomView() {
 82         return customView;
 83     }
 84 
 85     public void setCustomView(View customView) {
 86         this.customView = customView;
 87     }
 88 
 89     public int getCode() {
 90         return code;
 91     }
 92 
 93     protected void setCode(int code) {
 94         this.code = code;
 95     }
 96 
 97     protected Builder getBuilder() {
 98         return builder;
 99     }
100 
101     private void setBuilder(Builder builder) {
102         this.builder = builder;
103     }
104 
105 
106     public boolean isSticky() {
107         return isSticky;
108     }
109 
110     public void setSticky(boolean isSticky) {
111         this.isSticky = isSticky;
112     }
113 
114 }
View Code

 

  1 public class HeadsUpManager  {
  2 
  3     private  WindowManager wmOne;
  4     private FloatView floatView;
  5     private Queue<HeadsUp> msgQueue;
  6     private static HeadsUpManager manager;
  7     private Context context;
  8 
  9     private boolean isPolling = false;
 10 
 11     private Map<Integer, HeadsUp> map;
 12     private   NotificationManager notificationManager=null;
 13 
 14     public static HeadsUpManager getInstant(Context c) {
 15 
 16         if (manager == null) {
 17             manager = new HeadsUpManager(c);
 18 
 19         }
 20         return manager;
 21 
 22     }
 23 
 24     private HeadsUpManager(Context context) {
 25         this.context = context;
 26         map = new HashMap<Integer, HeadsUp>();
 27         msgQueue = new LinkedList<HeadsUp>();
 28         wmOne = (WindowManager) context
 29                 .getSystemService(Context.WINDOW_SERVICE);
 30 
 31         notificationManager= (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
 32     }
 33 
 34     public  void notify(HeadsUp headsUp) {
 35 
 36 
 37         if (map.containsKey(headsUp.getCode())) {
 38             msgQueue.remove(map.get(headsUp.getCode()));
 39         }
 40         map.put(headsUp.getCode(), headsUp);
 41         msgQueue.add(headsUp);
 42 
 43         if (!isPolling) {
 44             poll();
 45         }
 46     }
 47     public synchronized void notify(int code,HeadsUp headsUp) {
 48         headsUp.setCode(code);
 49         notify(headsUp);
 50         
 51     }
 52     public synchronized void cancel(HeadsUp headsUp) {
 53         cancel(headsUp.getCode());
 54     }
 55 
 56 
 57     private synchronized void poll() {
 58         if (!msgQueue.isEmpty()) {
 59             HeadsUp headsUp = msgQueue.poll();
 60             map.remove(headsUp.getCode());
 61 
 62 //            if ( Build.VERSION.SDK_INT < 21 ||   headsUp.getCustomView() != null ){
 63                 isPolling = true;
 64                 show(headsUp);
 65                 System.out.println("自定義notification");
 66 //            }else {
 67 //                //當 系統是 lollipop 以上,並且沒有自定義佈局以後,調用系統自己的 notification
 68 //                isPolling = false;
 69 //                notificationManager.notify(headsUp.getCode(),headsUp.getBuilder().setSmallIcon(headsUp.getIcon()).build());
 70 //                System.out.println("調用系統notification");
 71 //            }
 72             
 73         } else {
 74             isPolling = false;
 75         }
 76     }
 77     private void show(HeadsUp headsUp) {
 78         floatView = new FloatView(context, 20);
 79         WindowManager.LayoutParams params = FloatView.winParams;
 80         params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
 81                 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
 82                 |WindowManager.LayoutParams.FLAG_FULLSCREEN
 83                 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
 84         params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
 85         params.width = WindowManager.LayoutParams.MATCH_PARENT;
 86         params.height = WindowManager.LayoutParams.WRAP_CONTENT;
 87         params.format = -3;
 88         params.gravity = Gravity.CENTER | Gravity.TOP;
 89         params.x = floatView.originalLeft;
 90         params.y = 10;
 91         params.alpha = 1f;
 92         wmOne.addView(floatView, params);
 93         ObjectAnimator a = ObjectAnimator.ofFloat(floatView.rootView, "translationY", -700, 0);
 94         a.setDuration(600);
 95         a.start();
 96         floatView.setNotification(headsUp);
 97         if(headsUp.getNotification()!=null){
 98             notificationManager.notify(headsUp.getCode(), headsUp.getNotification());
 99         }
100     }
101 
102     public void cancel(){
103 
104         if(floatView !=null && floatView.getParent()!=null) {
105 
106             floatView.cancel();
107         }
108     }
109 
110     protected void dismiss() {
111         if (floatView.getParent()!=null) {
112             wmOne.removeView(floatView);
113             floatView.postDelayed(new Runnable() {
114                 @Override
115                 public void run() {
116                     poll();
117                 }
118             }, 200);
119         }
120 
121     }
122 
123     protected   void  animDismiss(){
124         if(floatView !=null && floatView.getParent()!=null){
125 
126             ObjectAnimator a = ObjectAnimator.ofFloat(floatView.rootView, "translationY", 0, -700);
127             a.setDuration(700);
128             a.start();
129 
130             a.addListener(new Animator.AnimatorListener() {
131                 @Override
132                 public void onAnimationStart(Animator animator) {
133 
134                 }
135                 @Override
136                 public void onAnimationEnd(Animator animator) {
137 
138                     dismiss();
139                 }
140                 @Override
141                 public void onAnimationCancel(Animator animator) {
142                 }
143                 @Override
144                 public void onAnimationRepeat(Animator animator) {
145 
146                 }
147             });
148         }
149 
150     }
151 
152     protected  void  animDismiss(HeadsUp headsUp){
153            if(floatView.getHeadsUp().getCode()==headsUp.getCode()){
154                animDismiss();
155            }
156 
157     }
158     public void cancel(int code) {
159         if (map.containsKey(code)) {
160             msgQueue.remove(map.get(code));
161         }
162         if(floatView!=null && floatView.getHeadsUp().getCode()==code){
163             animDismiss();
164         }
165 
166     }
167     public void close() {
168         cancelAll();
169         manager = null;
170     }
171     public void cancelAll() {
172         msgQueue.clear();
173         if (floatView!=null && floatView.getParent()!=null) {
174             animDismiss();
175         }
176     }
177 }
View Code

 

  1 public class FloatView extends LinearLayout {
  2     private float rawX = 0;
  3     private float rawY=0;
  4     private float touchX = 0;
  5     private float startY = 0;
  6     public LinearLayout rootView;
  7     public int originalLeft;
  8     public int viewWidth;
  9     private float validWidth;
 10     private VelocityTracker velocityTracker;
 11     private  int maxVelocity;
 12     private Distance distance;
 13 
 14     private ScrollOrientationEnum scrollOrientationEnum=ScrollOrientationEnum.NONE;
 15 
 16     public static WindowManager.LayoutParams winParams = new WindowManager.LayoutParams();
 17 
 18     public FloatView(final Context context, int i) {
 19         super(context);
 20         LinearLayout view = (LinearLayout) LayoutInflater.from(getContext()).inflate(R.layout.notification_bg, null);
 21         maxVelocity= ViewConfiguration.get(context).getScaledMaximumFlingVelocity();
 22         rootView = (LinearLayout) view.findViewById(R.id.rootView);
 23         addView(view);
 24         viewWidth = context.getResources().getDisplayMetrics().widthPixels;
 25         validWidth=viewWidth/2.0f;
 26         originalLeft = 0;
 27      
 28     }
 29 
 30     public void setCustomView(View view) {
 31         rootView.addView(view);
 32     }
 33 
 34 
 35     @Override
 36     protected void onFinishInflate() {
 37         super.onFinishInflate();
 38     }
 39 
 40 
 41     private HeadsUp headsUp;
 42     private long cutDown;
 43     private   Handler mHandle=null;
 44     private CutDownTime cutDownTime;
 45     private class CutDownTime extends Thread{
 46 
 47         @Override
 48         public void run() {
 49             super.run();
 50 
 51 
 52             while (cutDown>0){
 53                 try {
 54                     Thread.sleep(1000);
 55                     cutDown--;
 56                 } catch (InterruptedException e) {
 57                     e.printStackTrace();
 58                 }
 59             }
 60 
 61             if(cutDown==0) {
 62                 mHandle.sendEmptyMessage(0);
 63             }
 64 
 65 
 66         }
 67     };
 68 
 69 
 70 
 71     public HeadsUp getHeadsUp() {
 72         return headsUp;
 73     }
 74 
 75 private int pointerId;
 76     public boolean onTouchEvent(MotionEvent event) {
 77         rawX = event.getRawX();
 78         rawY=event.getRawY();
 79         acquireVelocityTracker(event);
 80         cutDown= headsUp.getDuration();
 81         switch (event.getAction()) {
 82             case MotionEvent.ACTION_DOWN:
 83                 touchX = event.getX();
 84                 startY = event.getRawY();
 85                 pointerId=event.getPointerId(0);
 86                 break;
 87             case MotionEvent.ACTION_MOVE:
 88                 switch (scrollOrientationEnum){
 89                     case NONE:
 90                         if(Math.abs((rawX - touchX))>20) {
 91                             scrollOrientationEnum=ScrollOrientationEnum.HORIZONTAL;
 92 
 93                         }else if(startY-rawY>20){
 94                             scrollOrientationEnum=ScrollOrientationEnum.VERTICAL;
 95 
 96                         }
 97 
 98                         break;
 99                     case HORIZONTAL:
100                         updatePosition((int) (rawX - touchX));
101                         break;
102                     case VERTICAL:
103                         if(startY-rawY>20) {
104                            cancel();
105                         }
106                         break;
107                 }
108 
109                 break;
110             case MotionEvent.ACTION_UP:
111                 velocityTracker.computeCurrentVelocity(1000,maxVelocity);
112                 int dis= (int) velocityTracker.getYVelocity(pointerId);
113                 if(scrollOrientationEnum==ScrollOrientationEnum.NONE){
114                     if(headsUp.getNotification().contentIntent!=null){
115 
116                         try {
117                             headsUp.getNotification().contentIntent.send();
118                             cancel();
119                         } catch (PendingIntent.CanceledException e) {
120                             e.printStackTrace();
121                         }
122                     }
123                     break;
124                 }
125 
126 
127                 int toX;
128                 if(preLeft>0){
129                     toX= (int) (preLeft+Math.abs(dis));
130                 }else{
131                     toX= (int) (preLeft-Math.abs(dis));
132                 }
133                 if (toX <= -validWidth) {
134                     float preAlpha=1-Math.abs(preLeft)/validWidth;
135                     preAlpha=preAlpha>=0?preAlpha:0;
136                     translationX(preLeft,-(validWidth+10),preAlpha,0);
137                 } else if (toX <= validWidth) {
138                     float preAlpha=1-Math.abs(preLeft)/validWidth;
139                     preAlpha=preAlpha>=0?preAlpha:0;
140                     translationX(preLeft,0,preAlpha,1);
141 
142                 }else{
143                     float preAlpha=1-Math.abs(preLeft)/validWidth;
144                     preAlpha=preAlpha>=0?preAlpha:0;
145                     translationX(preLeft, validWidth + 10, preAlpha, 0);
146                 }
147                 preLeft = 0;
148                 scrollOrientationEnum=ScrollOrientationEnum.NONE;
149                 break;
150         }
151 
152         return super.onTouchEvent(event);
153 
154     }
155     /**
156      *
157      * @param event 向VelocityTracker添加MotionEvent
	   

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 實例詳解Android快速開發工具類總結 作者:LiJinlun 字體:[增加 減小] 類型:轉載 時間:2016-01-24 我要評論 實例詳解Android快速開發工具類總結 作者:LiJinlun 字體:[增加 減小] 類型:轉載 時間:2016-01-24 我要評論 這篇文章主要介紹了實例詳 ...
  • Android精選源碼 Android優質博客 前幾天看到同事里有一個界面絢麗的應用,覺得有點意思,就讓他把APK發給我,我想反編譯看看裡面的代碼。結果,這哥們在手機里找了好一陣子,最後給我說:手機沒有root,找不到APK文件在哪裡。我再讓他試試其他機子,結果都差不多:要不然找起來很麻煩,要不然根 ...
  • Android開機圖片替換 Android從啟動到進入Launcher一共會展示三張圖片,如果只是更換靜態圖則更換這三張圖片即可,要想換成動畫那就要另外操作。 首先查找這個文件: /bootable/bootloader/lk/project/<project>.mk 裡邊有這個配置,記住這個等號後 ...
  • UX設計師是以用戶體驗為中心,進行產品設計,他們的任務就是讓用戶說出“Yes”。UX設計涉及到人機交互的各個方面,如可用性、功能性、交互設計、信息架構設計等等。就這些方面來說,原型工具不可或缺。市場上的原型工具有很多,但想找到合心意的卻比較困難。其實,挑選工具也是有門道的,在確定具體用戶及項目需求前 ...
  • iOS精選源碼 iOS優質博客 前言發現好久沒有研究、學習iOS優秀開源代碼,現在大部分時間都在寫業務代碼, 學習其他語言及一些雜七雜八的事情。所以現在就從簡短的開源代碼開始學習。這一篇就寫FaceBook, 這個極度熱愛開源的公司, 它的一套關於KVO的開源代碼。GitHub代碼演示代碼地址正文F ...
  • 一、前沿||潛心修心,學無止盡。生活如此,coding亦然。本人鳥窩,一隻正在求職的鳥。聯繫我可以直接微信:jkxx123321 二、項目總結 **||**文章參考資料:1. http://blog.csdn.net/u011272795/article/details/73824558 2.htt ...
  • 參考資料:https://github.com/sunyardTime/React-Native-CodeStyle 感謝情書哥無私奉獻 ##一、編程規約 ###(一) 命名規約 【強制】 代碼中命名均不能以下劃線或美元符號開始,也不能以下劃線或美元符號結束; 【強制】 代碼中命名嚴禁使用拼音與英文 ...
  • ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...