看著手機上的360浮動小球,不評價其具體的功能與實用性,至少在UI設計與交互方面是個不小的創新。
如圖片左上角所示,球中還會顯示當前手機的運行狀況,向下拉動還會有彈射來達到加速、清理等目的。
那好,先來實現一個類似的小球(僅限於形狀,功能你懂得)。
查閱了相關資料,整個界面除了小球以外,其他部分均是做透明處理。
1、由於用到了CompatModeWrapper,所以需要在AndroidManifest.xml中添加以下權限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
要想在應用中被啟動為一個Activity或Service,需要注冊,這裡是Service:
<service android:name=".Service1" />
2、界面透明化處理,整體代碼如下:
package com.XXX.autostart;
import android.view.View;
import android.app.Service;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.Handler;
import android.os.IBinder;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.WindowManager.LayoutParams;
import android.widget.ImageButton;
import android.widget.LinearLayout;
public class Service1 extends Service
{
LinearLayout mFloatLayout;
WindowManager.LayoutParams wmParams;
WindowManager mWindowManager;
ImageButton mFloatView;
@Override
public void onCreate()
{
// TODO Auto-generated method stub
super.onCreate();
createFloatView();
}
@Override
public IBinder onBind(Intent intent)
{
// TODO Auto-generated method stub
return null;
}
private void createFloatView()
{
wmParams = new WindowManager.LayoutParams();
mWindowManager = (WindowManager)getApplication().getSystemService(getApplication().WINDOW_SERVICE);
wmParams.type = LayoutParams.TYPE_PHONE;
wmParams.format = PixelFormat.RGBA_8888;
wmParams.flags = LayoutParams.FLAG_NOT_FOCUSABLE;
wmParams.gravity = Gravity.LEFT | Gravity.TOP;
wmParams.x = 0;
wmParams.y = 0;
wmParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
wmParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
LayoutInflater inflater = LayoutInflater.from(getApplication());
mFloatLayout = (LinearLayout) inflater.inflate(R.layout.float_layout, null);
mWindowManager.addView(mFloatLayout, wmParams);
mFloatView = (ImageButton)mFloatLayout.findViewById(R.id.float_id);
mFloatLayout.measure(View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED), View.MeasureSpec
.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
mFloatView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
wmParams.x = (int) event.getRawX() - mFloatView.getMeasuredWidth() / 2;
wmParams.y = (int) event.getRawY() - mFloatView.getMeasuredHeight() / 2 - 25;
mWindowManager.updateViewLayout(mFloatLayout, wmParams);
return false;
}
});
mFloatView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
mFloatView.setVisibility(View.INVISIBLE);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
mFloatView.setVisibility(View.VISIBLE);
}
}, 3000);
}
});
}
@Override
public void onDestroy()
{
// TODO Auto-generated method stub
super.onDestroy();
if(mFloatLayout != null)
{
mWindowManager.removeView(mFloatLayout);
}
}
}
這裡是利用ImageButton組件來實現小球,關鍵在於其顯示的圖片是圓形。
因此,要想將浮動窗口實現為其他形狀,只需制作相應的圖片賦給組件。
對於小球的功能,只是實現了在手機屏幕上隨意拖動,單擊消失三秒後重現。
3、浮動小球有了,怎麼讓它啟動呢?注意上面實現的類Service1,繼承的是Service。
在ManiActivity.java中,讓其顯現的方式很簡單,代碼如下:
finish();
Intent intent = new Intent(getApplicationContext(), Service1.class);
startService(intent);
注意,這裡對於MainActivity類不需要做任何處理,新建工程時默認就好。當然,要實現其他功能例外。
代碼finish();可加可不加,加上之後使得程序一運行就只剩下小球,原來的界面讓其消失。
效果圖如下,圖形找的是紅色小火焰。
4、到此,浮動小球就實現了,那怎麼讓它開機自啟動呢?
其實也很簡單,用到了BroadcastReceiver。
還是先添加權限:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
另外,對於系統的廣播消息,要想在開機等時刻能夠捕獲到,還需添加以下內容:
<receiver android:name=".BootBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
實現代碼如下:
package com.XXX.autostart;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class BootBroadcastReceiver extends BroadcastReceiver {
static final String ACTION = "android.intent.action.BOOT_COMPLETED";
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION)) {
Intent intent1 = new Intent(context, Service1.class);
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startService(intent1);
}
}
}
將手機ReBoot,可以發現紅色小球會自行啟動,不過速度比較慢(和360安全衛士相比)。
更多Android相關信息見Android 專題頁面 http://www.linuxidc.com/topicnews.aspx?tid=11