看着手機上的360浮動小球,不評價其具體的功能與實用性,至少在UI設計與交互方面是個不小的創新。java
如圖片左上角所示,球中還會顯示當前手機的運行情況,向下拉動還會有彈射來達到加速、清理等目的。android
那好,先來實現一個相似的小球(僅限於形狀,功能你懂得)。安全
查閱了相關資料,整個界面除了小球之外,其餘部分均是作透明處理。app
一、因爲用到了CompatModeWrapper,因此須要在AndroidManifest.xml中添加如下權限:ide
1 <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
要想在應用中被啓動爲一個Activity或Service,須要註冊,這裏是Service:post
1 <service android:name=".Service1" />
二、界面透明化處理,總體代碼以下:spa
1 package com.XXX.autostart; 2
3 import android.view.View; 4
5 import android.app.Service; 6 import android.content.Intent; 7 import android.graphics.PixelFormat; 8 import android.os.Handler; 9 import android.os.IBinder; 10 import android.view.Gravity; 11 import android.view.LayoutInflater; 12 import android.view.MotionEvent; 13 import android.view.WindowManager; 14 import android.view.View.OnClickListener; 15 import android.view.View.OnTouchListener; 16 import android.view.WindowManager.LayoutParams; 17 import android.widget.ImageButton; 18 import android.widget.LinearLayout; 19
20 public class Service1 extends Service 21 { 22 LinearLayout mFloatLayout; 23 WindowManager.LayoutParams wmParams; 24 WindowManager mWindowManager; 25
26 ImageButton mFloatView; 27
28 @Override 29 public void onCreate() 30 { 31 // TODO Auto-generated method stub
32 super.onCreate(); 33
34 createFloatView(); 35 } 36
37 @Override 38 public IBinder onBind(Intent intent) 39 { 40 // TODO Auto-generated method stub
41 return null; 42 } 43
44 private void createFloatView() 45 { 46 wmParams = new WindowManager.LayoutParams(); 47
48 mWindowManager = (WindowManager)getApplication().getSystemService(getApplication().WINDOW_SERVICE); 49
50 wmParams.type = LayoutParams.TYPE_PHONE; 51 wmParams.format = PixelFormat.RGBA_8888; 52
53 wmParams.flags = LayoutParams.FLAG_NOT_FOCUSABLE; 54
55 wmParams.gravity = Gravity.LEFT | Gravity.TOP; 56
57 wmParams.x = 0; 58 wmParams.y = 0; 59
60 wmParams.width = WindowManager.LayoutParams.WRAP_CONTENT; 61 wmParams.height = WindowManager.LayoutParams.WRAP_CONTENT; 62
63 LayoutInflater inflater = LayoutInflater.from(getApplication()); 64 mFloatLayout = (LinearLayout) inflater.inflate(R.layout.float_layout, null); 65
66 mWindowManager.addView(mFloatLayout, wmParams); 67
68 mFloatView = (ImageButton)mFloatLayout.findViewById(R.id.float_id); 69
70 mFloatLayout.measure(View.MeasureSpec.makeMeasureSpec(0, 71 View.MeasureSpec.UNSPECIFIED), View.MeasureSpec 72 .makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); 73
74
75 mFloatView.setOnTouchListener(new OnTouchListener() { 76 @Override 77 public boolean onTouch(View v, MotionEvent event) { 78 // TODO Auto-generated method stub
79
80 wmParams.x = (int) event.getRawX() - mFloatView.getMeasuredWidth() / 2; 81
82 wmParams.y = (int) event.getRawY() - mFloatView.getMeasuredHeight() / 2 - 25; 83
84 mWindowManager.updateViewLayout(mFloatLayout, wmParams); 85 return false; 86 } 87 }); 88
89 mFloatView.setOnClickListener(new OnClickListener() { 90
91 @Override 92 public void onClick(View v) { 93 // TODO Auto-generated method stub
94 mFloatView.setVisibility(View.INVISIBLE); 95
96 Handler handler = new Handler(); 97 handler.postDelayed(new Runnable() { 98 public void run() { 99 mFloatView.setVisibility(View.VISIBLE); 100 } 101 }, 3000); 102
103 } 104 }); 105 } 106
107 @Override 108 public void onDestroy() 109 { 110 // TODO Auto-generated method stub
111 super.onDestroy(); 112 if(mFloatLayout != null) 113 { 114 mWindowManager.removeView(mFloatLayout); 115 } 116 } 117
118 }
這裏是利用ImageButton組件來實現小球,關鍵在於其顯示的圖片是圓形。設計
所以,要想將浮動窗口實現爲其餘形狀,只需製做相應的圖片賦給組件。
code
對於小球的功能,只是實現了在手機屏幕上隨意拖動,單擊消失三秒後重現。orm
三、浮動小球有了,怎麼讓它啓動呢?注意上面實現的類Service1,繼承的是Service。
在ManiActivity.java中,讓其顯現的方式很簡單,代碼以下:
1 finish(); 2 Intent intent = new Intent(getApplicationContext(), Service1.class); 3 startService(intent);
注意,這裏對於MainActivity類不須要作任何處理,新建工程時默認就好。固然,要實現其餘功能例外。
代碼finish();可加可不加,加上以後使得程序一運行就只剩下小球,原來的界面讓其消失。
效果圖以下,圖形找的是紅色小火焰。
四、到此,浮動小球就實現了,那怎麼讓它開機自啓動呢?
其實也很簡單,用到了BroadcastReceiver。
仍是先添加權限:
1 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
另外,對於系統的廣播消息,要想在開機等時刻可以捕獲到,還需添加如下內容:
1 <receiver android:name=".BootBroadcastReceiver">
2 <intent-filter>
3 <action android:name="android.intent.action.BOOT_COMPLETED" />
4 </intent-filter>
5 </receiver>
實現代碼以下:
1 package com.XXX.autostart; 2
3 import android.content.BroadcastReceiver; 4 import android.content.Context; 5 import android.content.Intent; 6
7 public class BootBroadcastReceiver extends BroadcastReceiver { 8
9 static final String ACTION = "android.intent.action.BOOT_COMPLETED"; 10
11 @Override 12 public void onReceive(Context context, Intent intent) { 13
14 if (intent.getAction().equals(ACTION)) { 15 Intent intent1 = new Intent(context, Service1.class); 16 intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 17 context.startService(intent1); 18 } 19 } 20 }
將手機ReBoot,能夠發現紅色小球會自行啓動,不過速度比較慢(和360安全衛士相比)。